designing4u.de Yet Another Coding Blog

13Sep/090

Accessing Google Analytics API with Zend Framework

After a long time Google finally released the API which allows the read access to the Google Analytics accounts. Since I needed it to perform some analytics and included it into one of my projects written with Zend Framework. Zend framework provides a massive library collection which you can use to access Google services, but unfortunately it does not provide the interface for accessing the analytics yet. Therefore I decided to share the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
/**
 * 
 *  @author Wojciech Gancarczyk <gancarczyk@gmail.com>
 */
class App_Analytics_Helper
{
    const CLIENTLOGIN_URL = 'https://www.google.com/accounts/ClientLogin';
    const ACCOUNT_FEED_URL = 'http://www.google.com/analytics/feeds/accounts/default';
    const DATA_FEED_URL = 'https://www.google.com/analytics/feeds/data';
    const SERVICE_NAME = 'analytics';
 
    /**
     * @var string
     */
    protected $_auth;
 
    /**
     * @var string
     */
    protected $_applicationName = 'MyApp-MyDesc-0.1';
 
    /**
     * @var string
     */
    protected $_username;
 
    /**
     * @var string
     */
    protected $_password;
 
    /**
     * @var int
     */
    protected $_ga;
 
    /**
     * Class counstructor. It accepts only array as a parameter. It then
     * checks, if the array keys correspond to the setters of this class
     * and if they do, it sets them. After that it is trying to perform
     * authentication.
     *
     * @param array $params
     * @throws Exception
     */
    public function __construct($params = array())
    {
        if (!is_array($params))
            throw new Exception(
                'Constructor accepts only an array as a parameter');
 
        if (!empty($params)) {
            $methods = get_class_methods($this);
 
            foreach ($params as $key => $value) {
                $method = 'set' . ucfirst($key);
                if (in_array($method, $methods))
                    $this->$method($value);
            }
            $this->authenticate();
        }
    }
 
    /**
     * Performs authentication. It has to be calles before any data
     * can be received, because auth is neccassary for each call.
     *
     * @param string $username
     * @param string $password
     * @throws Exception
     */
    public function authenticate($username = null, $password = null)
    {
        if (null === $username && null === $this->getUsername())
            throw new Exception(
                'Username is necessary to perform authentication');
 
        if (null === $password && null === $this->getPassword())
            throw new Exception(
                'Password is necessary to perform authentication');
 
        if (is_string($username))
            $this->setUsername($username);
 
        if (is_string($password))
            $this->setPassword($password);
 
        $client = new Zend_Http_Client(self::CLIENTLOGIN_URL);
        $client->setMethod(Zend_Http_Client::POST);
 
        $client->setParameterPost(array(
		'Email'       => $this->getUsername(),
		'Passwd'      => $this->getPassword(),
                'AccountType' => 'GOOGLE',
                'service'     => self::SERVICE_NAME,
                'source'      => $this->getApplicationName(),
        ));
        $response = $client->request('POST');
 
        if ($response->getStatus() != '200')
            throw new Exception(
                'Authentication failed. Status returned: ' .
                $response->getStatus());
 
        $return = explode('=', $response->getBody());
        $this->setAuth($return[3]);
    }
 
    /**
     * Recieves the account feed.
     *
     * @return string XML stream
     * @throws Exception
     */
    public function getAccountFeed()
    {
        if (null === $this->getAuth())
            throw new Exception(
                'Account Feed cannot retrieve any results, ' .
                'because the client was not authenticated');
 
        $client = new Zend_Http_Client(self::ACCOUNT_FEED_URL);
        $client->setMethod(Zend_Http_Client::GET);
        $client->setParameterGet('start-index', '1');
        $client->setParameterGet('max-results', '2');
        $client->setParameterGet('prettyprint', 'true');
        $client->setHeaders('Authorization', 'GoogleLogin auth=' . $this->getAuth());
        $response = $client->request('GET');
 
        if ($response->getStatus() != '200')
            throw new Exception(
                'Authentication failed. Status returned: ' .
                $response->getStatus());
 
        return $response->getBody();
    }
 
    /**
     * Performs data feed.
     *
     * @return string XML stream
     * @throws Exception
     */
    public function getDataFeed()
    {
        if (null === $this->getAuth())
            throw new Exception(
                'Account Feed cannot retrieve any results, ' .
                'because the client was not authenticated');
 
        if (null === $this->getGa())
            throw new Exception(
                'Account ID was not provided');
 
        $client = new Zend_Http_Client(self::DATA_FEED_URL);
        $client->setMethod(Zend_Http_Client::GET);
        $client->setParameterGet('ids', 'ga:' . $this->getGa());
        $client->setParameterGet('dimensions', 'ga:source,ga:medium');
        $client->setParameterGet('metrics', 'ga:visits,ga:bounces');
        $client->setParameterGet('sort', '-ga:visits');
        $client->setParameterGet('start-date', '2009-08-01');
        $client->setParameterGet('end-date', '2009-08-31');
        $client->setParameterGet('start-index', '10');
        $client->setParameterGet('max-results', '100');
        $client->setHeaders('Authorization', 'GoogleLogin auth=' . $this->getAuth());
        $response = $client->request('GET');
 
        if ($response->getStatus() != '200')
            throw new Exception(
                'Authentication failed. Status returned: ' .
                $response->getStatus());
 
        return $response->getBody();
    }
 
    /**
     * Setter for username.
     *
     * @param string $username
     */
    public function setUsername($username)
    {
        $this->_username = (string) $username;
    }
 
    /**
     * Getter for username.
     *
     * @return string
     */
    public function getUsername()
    {
        return $this->_username;
    }
 
    /**
     * Setter for password.
     *
     * @param string $password
     */
    public function setPassword($password)
    {
        $this->_password = (string) $password;
    }
 
    /**
     * Getter for password.
     *
     * @return string
     */
    public function getPassword()
    {
        return $this->_password;
    }
 
    /**
     * Setter for auth.
     *
     * @param string $auth
     */
    public function setAuth($auth)
    {
        $this->_auth = (string) $auth;
    }
 
    /**
     * Getter for getAuth.
     *
     * @return string
     */
    public function getAuth()
    {
        return $this->_auth;
    }
 
    /**
     * Setter for applicationName.
     *
     * @param string applicationName
     */
    public function setApplicationName($name)
    {
        $this->_applicationName = (string) $name;
    }
 
    /**
     * Getter for applicationName.
     *
     * @return string
     */
    public function getApplicationName()
    {
        return $this->_applicationName;
    }
 
    /**
     * Setter for ga.
     *
     * @param integer $ga
     */
    public function setGa($ga)
    {
        $this->_ga = (int) $ga;
    }
 
    /**
     * Getter for ga.
     *
     * @return integer
     */
    public function getGa()
    {
        return $this->_ga;
    }
}

As you can see this class is not perfect yet. It basically utilizes Zend_Http_Client and its methods to perform the request and retrieve the results. First of all it needs a better support for setting the parameters to retrieve data and account feeds. Right now they are just hard coded and you cannot influence their values. Besides that as a return value it returns the XML stream. Zend Framework comes with an awesome library Zend_Dom which can be used to read the values from the response. I will definitely put that in this class, but it is a good subject for a next post. You may also consider using it as a controller helper, but then you will need to rewrite it a little bit. It might be another interesting subject for a post.

One more thing left mentioning is the usage of this class. Well, there are two ways of using it. You can either create an array of parameters and pass it while you instantiating this class:

$params = array(
    'username' => 'yourUserName',
    'password' => 'yourPassword',
    'ga' => 'accountId'
);
$analytics = new App_Analytics_Helper($params);
$dataFeed = $analytics->getDataFeed();
$accountFeed = $analytics->getAccountFeed();

You can also use the setters and perform authentication "manually":

$analytics = new App_Analytics_Helper();
$analytics->setUsername('yourUserName');
$analytics->setPassword('yourPassword');
$analytics->setGa('accountId');
$analytics->authenticate();
$dataFeed = $analytics->getDataFeed();
$accountFeed = $analytics->getAccountFeed();

I'm waiting for your comments about this class. I hope it will save you some time.

Comments (0) Trackbacks (2)

No comments yet.


Leave a comment


Pages

Categories

Blogroll

Archive

Meta