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.