Google Analytics Accounts API
Analytics Accounts
Your google account can have access to one or more analytics accounts. For example when I log in I have access to accounts which hold the data for lornajane.net, phpwomen.org, joind.in and a few other things I’m involved with. Only lornajane.net actually belongs to me, the others are accounts created by someone else and which I have access to. The first challenge therefore is to work out which a user has access to – the best place to start is the reference page for the Management API, part of google’s own documentation. In a nutshell, we build up a URL like this, being increasingly specific by fleshing out the values in square brackets on subsequent calls:
https://www.google.com/analytics/feeds/datasources/ga/accounts/[accountID]/
webproperties/[webPropertyID]/profiles/[profileID]/goals
First up then, is to get a list of accounts for our authorized user – I already have a valid oauth access token to use in this example
$oauth = new OAuth($consumer_key,
$consumer_secret
);
$oauth->setToken($access_token, $access_token_secret);
$result = $oauth->fetch('https://www.google.com/analytics/feeds/datasources/ga/accounts');
This returns some XML containing some information about the results and an
if($result) {
$response = $oauth->getLastResponse();
$xml = new SimpleXMLElement($response);
$xml->registerXpathNamespace("w3", "http://www.w3.org/2005/Atom");
$entries = $xml->xpath('/w3:feed/w3:entry');
$account_list = array();
foreach($entries as $item) {
$account = array();
$properties = $item->children('http://schemas.google.com/analytics/2009');
foreach($properties as $p) {
// get the attributes
$attrs = $p->attributes();
$name = (string)$attrs['name'];
$value = (string)$attrs['value'];
if($name == 'ga:accountId') {
$account['id'] = $value;
} elseif($name == 'ga:accountName') {
$account['name'] = $value;
} else {
// shouldn't have any other options
}
}
$account_list[$account['id']] = $account;
}
return $account_list;
}
This provides me with a list of accounts I can use to retrieve a list of which actual sites I can see.
Analytics Profiles
In theory, the next level of hierarchy is the web properties, but I found that I didn’t need the intermediate call and instead used the special ~all identifier offered by google to allow me to present the user with a full list of profiles to choose from. The profile data includes the magic “tableId” which is the information we need in order to pull actual web stats data from analytics itself. In this case I’m making a request to a URL that looks like this:
https://www.google.com/analytics/feeds/datasources/ga/accounts/[account_id]/
webproperties/~all/profiles
The [account_id] comes from the previous result set, and we make our call in a similar way to before:
$oauth = new OAuth($consumer_key,
$consumer_secret
);
$oauth->setToken($access_token, $access_token_secret);
$result = $oauth->fetch('https://www.google.com/analytics/feeds/datasources/ga/accounts/'
. $account_id . '/webproperties/~all/profiles');
Again we get some XML back in a defined format and containing
if($result) {
$response = $oauth->getLastResponse();
$xml = new SimpleXMLElement($response);
$xml->registerXpathNamespace("w3", "http://www.w3.org/2005/Atom");
$entries = $xml->xpath('/w3:feed/w3:entry');
$profile_list = array();
foreach($entries as $item) {
$profile = array();
$properties = $item->children('http://schemas.google.com/analytics/2009');
foreach($properties as $p) {
// get the attributes
$attrs = $p->attributes();
$name = (string)$attrs['name'];
$value = (string)$attrs['value'];
switch($name) {
case 'dxp:tableId':
$profile['tableId'] = $value;
break;
case 'ga:accountId':
$profile['accountId'] = $value;
break;
case 'ga:webPropertyId':
$profile['webPropertyId'] = $value;
break;
case 'ga:profileId':
$profile['profileId'] = $value;
break;
case 'ga:profileName':
$profile['profileName'] = $value;
break;
default:
// not interested in any other options
break;
}
}
$profile_list[$profile['webPropertyId']] = $profile;
}
return $profile_list;
}
At this point, I have the magic tableId for each profile – which is the key to retrieving data from the Export API for Analytics. Perhaps I’ll write more about how to actually retrieve data in the future, analytics collects a lot of data and as a result the API has many options – but still manages to be fairly simple to use, so all credit to google for that!
I’m battling with this API myself at the moment – it’s good to know I’m not the only one who finds SimpleXML quizzical! I like DOM but it can be a little verbose at times.
I’d be interested in how you tacked the statistics side of things because that’s been rather painful :-) – I’ve ended up going down a similar route to the Java client Google provide.
Craig: I’m still only pulling “play” statistics at this point but I’ll be blogging as soon as I have a bigger picture. There are a lot of stats to handle so I can imagine it all gets quite big quite fast …