A CakePHP plugin for displaying Google Analytics data in your own application. The bulk of the code is in 3 datasources, a generic one for working with any REST APIs, a Gdata datasource for handling authentication with any of the 18 Gdata APIs and the Gdata Analytics datasource driver itself.
I’ve written a CakePHP plugin for accessing Google Analytics data in your own application using the Google Analytics Data Export API.
The plugin itself contains the usual model/controller/view but these are really just for the demo, the real magic lies in the datasource. Well, there’s actually 3 datasources, more on that later.
As the demo indicates, you can access any of the metrics you can get in Google Analytics itself and break it down by any of the dimensions GA supports, for any date range.
Click on the red labels to toggle the list of check boxes allowing you to select the metrics and dimensions you want to see, then click the show button.
The results are shown in the table below, the initial view is showing the visitors metric broken down by year and month for the last month.
Don’t laugh at my meagre visitor stats ;-)
Note, I don’t have any campaigns, eCommerce or goals or anything like that set up on my site, so you won’t see much if you select those metrics.
If say you wanted to see pageviews broken down by browser, continent, operating system and operating system version, you’ll get a few more rows in the table, and you’ll see the pagination kicking in. This is using CakePHP built-in pagination with custom paginate() and paginateCount() methods in the model.
To achieve this however, I had to modify the core very slightly.
In cake/libs/controller/controller.php I changed the following in the paginate() method:
$extra = array_diff_key($defaults, compact( 'conditions', 'fields', 'order', 'limit', 'page', 'recursive' ));
$extra = array_diff_key($options, compact( 'conditions', 'recursive' ));
Note, $defaults has changed to $options and I’ve removed some of the keys that get removed from the $defaults variable to make the $extra variable.
This is because, unlike database queries for pagination, most APIs will return you both the total number of results and the result set for the selected page in one call, using an XML or JSON data structure, as opposed to when you are getting the results from the database, and you issue 2 queries, the first to get the total number of results, and the second to get the results for the selected page.
CakePHP’s Controller::paginate() method allows you to write your own paginate() and paginateCount() methods [see custom query pagination] but it doesn’t send the fields, order, limit and page options to your custom paginateCount() method… unless you make this change above.
So, by sending all the information to the custom paginateCount() method in the analytic model, I can issue the call to the API once, store the results and return the number of rows, then in the paginate() method, I can just return the result that I stored previously.
Not sure whether this would cock anything up for anyone, but it seems pretty harmless to me, maybe someone reading this could comment on it if I am wrong?
So, now that’s out the way, let’s have a look under the hood at those 3 datasources I mentioned.
Firstly there’s a REST source, which is a simple base datasource for interacting with REST APIs. It uses CakePHP’s HttpSocket class to issue requests using the appropriate HTTP verb according the the CRUD operation and returns the response converted to an array – currently just handles XML responses, but if you have a look at it, you can see how easy it could be extended to handle JSON or other formats.
On top of that is a Gdata datasource. This is intended to be able to be used as a base datasource for all Gdata APIs, of which there are 18. It handles authentication with the Google web service. Please note I haven’t yet had the opportunity to test this with any other Gdata API, but the theory is sound… I think ;-)
Finally, there is the actual Google Analytics datasource. This sits in a gdata directory inside the models/datasources directory in the plugin. The intention is to simulate the concept in CakePHP core where there is a base dbo source datasource for interacting with databases, then several drivers for specific databases. In this way I can write more gdata datasources, stick them in this gdata directory, and have them build on the base gdata datasource mentioned in the previous paragraph. It is achieved in the config file by setting the datasource key to gdata and the driver key to analytics.
The analytics datasource just has a read() method which constructs the http request to send to Google based on the $queryData parameter passed in the datasource read() method by Cake. This is typically an array containing the keys for things like conditions, page, limit, order etc etc.
I realised that the metrics and dimensions parameters that the Google Analytics API expects map quite neatly to SQL fields and group parameters that you might have in your SQL queries, and are supported by CakePHP Model::find() method, so they are passed in in those keys.
It also supports sorting the result set by any of the metrics or dimensions, in ascending or descending order. One thing I haven’t done yet is the filtering parameter that Google Analytics API supports, but that will be dead easy to add if you need it in your app.
As I said earlier, the model, controller and view in the plugin contain code mainly for the demo, apart from in the model constructor, there’s Matt Curry’s tip for loading datasources from plugins. So if you just want to get some GA data in your app, you can just use the datasources.
So, if you want to try it out on your own Google Analytics account, just:
- Download the code form my github account and save it in a /app/plugings/gdata/
- Make the change to /cake/libs/controller/controller.php as described above
- Add your Google Analytics email, password and profile id* to /app/plugins/gdata/config/gdata_config.php
- Go to http://www.example.com/gdata/analytics
* You can find your profile id by logging in to Google Analytics and clicking the edit link at the end of the table row containing the profile you want to access the data of. The id parameter in the querystring is the profile id you need to add to the config file – mine is a 7-digit integer. Note it is not the UA-XXXXX-X string.
Hope you like it.