Display Google analytics with php, jQuery and flot

Friday, 4 December 2009


This tutorial looks at how you can display your Google Analytics results using flot, the jQuery graphing library.

Flot will allow us to plot our results on a good looking graph without the need for flash; you can even enable and disable different sites if you are tracking multiple sites.


Unfortunately due to hosting restrictions I don't have a demo for this tutorial, but you can download the code from here



We will also be using the php analytics API class written by Chris Hope available from http://www.electrictoolbox.com. This class will allow us to easily retrieve our analytics data and will allow you to customise your results (including start date etc.)

We begin with a simple placeholder in our HTML, we then call our php script analytics.php using jQuery's getJSON method. The analytics.php script first checks to see if we have a cached version of the results (the retrieval from Google is considerably slow) and then serves the cached results. If there are no cached results it retrieves the data from Google's servers and then builds an array of data for each site. This array is then converted to JSON using php's json_encode and returned to our javascript file. Our javascript file builds an array suitable for Flot and then calls Flot's plot method.

Let's have a look at some of our code, firstly the HTML:

<h1>
My sites</h1>
<div id="placeholder" style="width:600px;height:300px;">
</div>
<p id="choices" style='display:none;'>
Show:</p>

This is simply our title and place holder for our graph and site toggler.

Our javascript file is made up of three functions:

$("document").ready(function() {
   var url = "analytics.php";
   
   $.getJSON(url, {id:  Math.random()}, function(datasets) {
      if (datasets) {
         // hard-code color indices to prevent them from shifting as
         // countries are turned on/off
         var i = 0;
         $.each(datasets, function(key, val) {
            val.color = i;
            ++i;
         });
         
         // insert checkboxes 
         var choiceContainer = $("#choices");
         $.each(datasets, function(key, val) {
            choiceContainer.append('
<input type="checkbox" name="' + key +
                              '" checked="checked" id="id' + key + '">' +
                              '<label for="id' + key + '">'
                              + val.label + '</label>');
         });
         choiceContainer.find("input").click(updateGraph);
         
         plotAccordingToChoices(datasets);
         
         $("#choices").show();
      }
      
   });
});

We begin with our document ready function. This starts by calling our analytics.php file using the getJSON function and retrieves our datasets. We loop over our datasets and assign them a colour. Next we create our checkboxes to turn sites on or off and assign the updateGraph click function to these checkboxes. Finally we call our plotAccordingToChoices function and show our choices checkboxes.

function plotAccordingToChoices(datasets) {
   var data = [];
   
   var choiceContainer = $("#choices");

   choiceContainer.find("input:checked").each(function () {
      var key = $(this).attr("name");
      if (key && datasets[key]) {
         data.push(datasets[key]);
      }
   });

   var options = {
            xaxis: {
                mode: "time"
            }
        };
   
   if (data.length > 0) {
      var plotarea = $("#placeholder");
      plotarea.css("height", "250px");
      plotarea.css("width", "500px");
      $.plot( plotarea , data, options );
   }
}

Our plotAccordingToChoices function takes in our datasets and then compares the data to the checked options to see if any are disabled otherwise they are added to the data array. Our data array is then simply passed through to Flot to plot.

function updateGraph() {
   var url = "analytics.php";

   $.getJSON(url, {id:  Math.random()}, function(datasets) {
      if (datasets) {
         var i = 0;
         $.each(datasets, function(key, val) {
            val.color = i;
            ++i;
         });      
      
         plotAccordingToChoices(datasets);
      }
   });
}

Our updateGraph function simply retrieves our data again and then calls plotAccordingToChoices. You could store this information somewhere in a global or in the DOM, if that's what you're in to.

Now let's look at the php side of things.

require_once('analytics_api.php');

$login = '-enter login here-';
$password = '-enter password here-';

$modified = @filemtime("cache.txt");

$modified = date("d-m-Y", $modified);
$current = date("d-m-Y");

if ($modified && ($current == $modified)) {
   $cache = @file_get_contents("cache.txt");
} else {
   $cache = null;
}

if (!$cache) {
   $api = new analytics_api();
   if($api->login($login, $password)) {
      $api->load_accounts();
      $accounts = $api->accounts;

      $return = array();
      
      foreach ($accounts as $accountname => $account) {
         $data = $api->data($account['tableId'], 'ga:week', 'ga:visits', 'ga:week', '2009-07-05', '', '52');
         $return[$accountname]['label'] = $accountname;
         
         foreach ($data as $week_number => $week) { 
            $return[$accountname]['data'][] = array( (strtotime("2009W".$week_number) * 1000) , $week['ga:visits'] + rand(0, 400) );
         }
      }
      
      $encoded = json_encode($return);
      
      echo $encoded;
      file_put_contents("cache.txt", $encoded);
   }
} else {
   echo $cache;
}

We begin by checking our cached file and then checking the date modified to see if the cache file is from today. If the cache file exists and it is from today we simply return the contents of that file.

Otherwise, we log in to our analytics account using the $api->login($login, $password) method. We loop over each of our accounts and retrieve the data from that account:

$data = $api->data($account['tableId'], 'ga:week', 'ga:visits', 'ga:week', '2009-07-05', '', '52');

You see here when we call the data method you can specify a whole bunch of different options, I will leave these to you to investigate. We are simply going to retrieve all weekly visit data starting from 2009-07-05 up to a maximum of 52 weeks if available.

We loop over this data and store it in the return array per account name. Then once all the data has been looped over we simply JSON encode and return.

Nice and easy.

Enjoy!
blog comments powered by Disqus