Google Analytics Accounts API

I'm working with Google Analytics at the moment, to pull information about web traffic from analytics into another system. Google have excellent APIs and that makes this job much easier. I'm using pecl_oauth to authenticate users against their google accounts (see my post about using OAuth from PHP), but even after I have a valid google user, working out which analytics accounts they have access to and how to refer to them is a puzzle in itself, so I thought I'd share what I learned.These examples use pecl_http, since I have control of my platform and I find it easy to work with. I've tried to write this with explanations of the overall process in between the code snippets so hopefully this makes the process clear whether or not you will use exactly the same implementation.

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 element for each account. The key information you want here is inside the entries, there are tags, and here we can find both the account name and it's identifier. To retrieve these in a nice list, I used code that looked like this:

            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 tags representing each result. I am capturing various fields from each entry and storing them for reference, so here is my code (NB I was using SimpleXML and found the way it handled these namespaced elements quite ... interesting. It would probably have been cleaner to do this in DOM - however this code worked for me so here it is)

            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!

2 thoughts on “Google Analytics Accounts API

  1. 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.

  2. 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 ...

Leave a Reply

Please use [code] and [/code] around any source code you wish to share.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>