Speed up Google Analytics using simple PHP Script

Update:  Thanks to the wonder idea by Carl Mercier, the script is now available as a WordPress pluging. Please try Local Analytics.

Google Analytics is one of the best web traffic analysis service available. The best thing about Google Analytics is that it is FREE, while most  of the similar services requires a premium membership for such detailed reports. Microsoft announced starting their own Web Analytics service codenamed

Back to our topic. Recently I came across an article in JonLee.ca on speeding Up Google Analytics by hosting urchin.js it locally. Google support says that it is allowed, though not recommended, to host urchin.js locally. Google recommends directly linking to the file hosted on their server, because it will ensure that your users are downloading the latest version of the file.

A work around to this proposed by the above site and many other blogs is to setup a cron job to automatically update the file at regular intervals. But most of the sites does not provide any information on how to do that. Also not all webhosts support crontab. When a gzip enabled browser requests for the file, Google compresses the file before sending theirby reducing the file size from 21KB to 6KB. If your server is not configured to automatically compress all Javascript files, then this can increase the file download time.

Hence I have created a simple php script that will automatically download the script from Google Server at regular intervals and provides your users with latest version of urchin.js. The script also supports Gzip compression by default, though it can be turned off by changing $useGzip to false.
Here is the script:

< ?php

// Remote file to download
$remoteFile = 'http://www.google-analytics.com/urchin.js';
// Local File name. Must be made writable
$localFile = "local-urchin.js";
// Time to cache in hours
$cacheTime = 24;
// Connection time out
$connTimeout = 10;
// Use Gzip compression
$useGzip = true;

if($useGzip){
     ob_start('ob_gzhandler');
}

if(file_exists($localFile) && (time() - ($cacheTime * 3600) < filemtime($localFile))){
     readfile($localFile);
}else{
     $url = parse_url($remoteFile);
     $host = $url['host'];
     $path = isset($url['path']) ? $url['path'] : '/';

     if (isset($url['query'])) {
          $path .= '?' . $url['query'];
     } 

     $port = isset($url['port']) ? $url['port'] : '80';

     $fp = @fsockopen($host, '80', $errno, $errstr, $connTimeout ); 

     if(!$fp){
          // On connection failure return the cached file (if it exist)
          if(file_exists($localFile)){
               readfile($localFile);
          }
     }else{
          // Send the header information
          $header = "GET $path HTTP/1.0\r\n";
          $header .= "Host: $host\r\n";
          $header .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6\r\n";
          $header .= "Accept: */*\r\n";
          $header .= "Accept-Language: en-us,en;q=0.5\r\n";
          $header .= "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n";
          $header .= "Keep-Alive: 300\r\n";
          $header .= "Connection: keep-alive\r\n";
          $header .= "Referer: http://$host\r\n\r\n";

          fputs($fp, $header);

          $response = '';
          // Get the response from the remote server
          while($line = fread($fp, 4096)){
               $response .= $line;
          } 

          // Close the connection
          fclose( $fp );

          // Remove the headers
          $pos = strpos($response, "\r\n\r\n");
          $response = substr($response, $pos + 4);

          // Return the processed response
          echo $response;

          // Save the response to the local file
          if(!file_exists($localFile)){
               // Try to create the file, if doesn't exist
               fopen($localFile, 'w');
          }
          if(is_writable($localFile)) {
               if($fp = fopen($localFile, 'w')){
                    fwrite($fp, $response);
                    fclose($fp);
               }
          }
     }
}

?>

 Installing the Script

Installing the script is extremely simple. Save the above code in a php file, say analytics.php or download it from here. Edit your Google Analytics code and change http://www.google-analytics.com/urchin.js to your new file path, say http://www.yourdomain.com/analytics.php.

Now your code will be something like this


Use this code instead of your original Google Analytics code.

After uploading analytics.php to the server, directly access the file using your web browser. This will create a local copy of urchin.js, named local-urchin.js, on your server. Make sure that local-urchin.js is writable (chmod to 777).

Important: If your server is using the zlib compression for compressing javascript files, then turn off gzip compression by changing line no. 11 to :

$useGzip = true;

Advantages of using the script

  • Your webpage loads faster, since your user’s browser can use the existing connection with your web server to download the file and doesn’t need to create a new connection to google’s server.
  • Sometimes, though very rarely, google servers become overloaded and your page load time will be affected drastically.
  • Some ad blockers are now blocking Google Analytics too. This script will be a work around to that too.
  • Unlike other methods, the file is compressed before sending to gzip enabled browsers.

By Joyce

I am a co-founder and director of Ennexa Technologies. To know more about me, visit my about page. You can find a list of websites maintained by our company at the links page.

15 comments

  1. This is an amazing idea! I think I’ll have to do that for all my sites. If somebody could turn that into a WordPress plugin, it would make our life a bit easier!

    Thanks for the code, Joyce.

    1. Man nice stuff, this is very useful!
      I agree, a WordPress plugin would be useful. I’d be happy to make it if you let me steal your code!

      1. Hope you can steal it 😉

        Ideally, the plugin would allow me to enter my Analytics key and would automatically insert the required Javascript code somewhere in my WP pages, saving me from editing my theme.

        There’s about a million WP/Analytics plugins so I guess you should be able to re-use an existing one without reinventing the wheel!

  2. Thanks for the appreciation. 😀
    @Carl – That is a good idea. After reading ur comment I have started creating one. It is almost 90% complete and has more configurable options.

    @Jon – If u want to use the code feel free to use the code anyway you want. No need to steal it, its yours 😉

  3. I love your site. I found your blog via Google while searching for honeywell home security systems and your post regarding nnial 2007 – salvatore iaconesi – del.icio.us poetry looks very interesting to me. It really looks very nice. The articles provided are long enough to provide great content but not so long as to be totally engrossing, if you know what I mean.

  4. Wow! This is brilliant! Google should be in contact with you to implement this solution as an official one!

    My load times for my site are now in the 0.xx instead of the x.xx thanks to this script!

    1. @Ric: My guess is all you need to do is point the script at the new tracking file:

      $remoteFile = ‘http://www.google-analytics.com/ga.js’;

      Thanks, Joyce!

  5. Considering that Google Analytics is made to calculate the amount of hits to your website I think they’re well able to calculate their server usage. For this reason I don’t think their servers overload for calling a JS file.

    This script makes the visitor wait while the php downloads the file (no content is displayed during this time). The users probably already have Google’s js script cached, why would they need to download it again? The only reason this script is good is if the users have an ad blocker to block Google Analytics’ url.

  6. Pat: it only downloads the file if it’s out of date. Otherwise it serves a cached copy. As for client side caching, once you gzip it and perhaps merge with existing scripts, you get a negligible download and at worst 1 extra request

    Joyce: the updating of the script is better done with a cron job

Comments are closed.