Track Firefox Extension Installation and Usage Statistics Using Google Analytics

Browser extension developers often want to know how many people have downloaded their work and are actually using them. They may also want to know how often their users interact with the extensions, like accessing options/preferences etc. Although entities behind the browsers usually do offer basic download and maybe installation statistics for extensions hosted by them, for more advanced installation and usage tracking, developers have to find a way themselves.

Tracking extension installation and usage in Google’s Chromium/Chrome browser is a trivial task. One of the reasons for this is because Chromium’s extension system is based on ordinary HTML. An extension, at its minimum, is just one html file termed ‘background page’ that the browser loads automatically at startup. The ‘background page’ may or may not try to alter the browser GUI and/or webpage content, depending on the embedded or included JavaScript code. Adding the usual Google Analytics (GA) code snippet, which asynchronously requests the actual GA tracking code (GATC) file ga.js on GA server, to the background page is all that takes to track an enabled installation of an extension. Usage data such as extension-interaction events can also be easily tracked by defining handlers that send appropriate parameters to GATC. All of these can be done exactly the same way as tracking normal webpages served by an actual web server.

Extension (or add-on, which is more often used in Mozilla context) developers for Firefox/SeaMonkey are less lucky. Although the XUL-based system is not that much different from Chromium’s HTML-based system, with the obvious exception of the markup language used, tracking Mozilla extension with the usual GATC does not seem to work. The reasons for this are probably manifold, but the fact that cookie-setting using conventional JS code is disabled in extensions almost certainly plays a part. Google Analytics depends on cookies set by GATC to track visitor activity and will no record visits from cookie-less agents, such as robots/spiders.

It is possible, however, to set cookies in Firefox/SeaMonkey extensions using Gecko-specific JavaScript code (link), with which you could probably modify GATC to work in extensions. Unfortunately, only the minified version of GATC is publicly available. Hacking on de-minified code is not such a good or attractive idea, at least for me, so we will look at another simpler and easier solution.

Google Analytics retrieves tracking data from requests made by webpages to a image file named ‘__utm.gif’ located on the GA server. The image is 1×1 pixel so that there will be no easily visible alterations to the webpage content. HTTP(S) requests for the file are created by GATC to include information about the visitors in the query string (all that comes after ‘?’ in a URL) and are all what’s required for GA to obtain tracking data. In other words, as long as requests for ‘__utm.gif’ containing proper query strings are received, GA will be able to retrieve tracking data, regardless of whether or not the requests have been sent by GATC. Based on this fact, web developers were able to implement server-side tracking (before Google published their own implementations) of visits from browsers without JavaScript capability (mostly mobile browsers) or with JavaScript disabled (NoScript mode).

It is also very easy to send tracking report by creating requests for ‘__utm.gif’ using plain JavaScript and that is how we will solve the issue of tracking Firefox extensions. Instead of writing our own code, we’ll just use a ready-made script written by Remy Sharp, originally intended for tracking the usage of bookmarklets or JavaScript includes hosted on one site by other sites. The full and minified versions of the script can be downloaded here. Let’s go over the full version quickly and see what it actually does:

/**
 * Google Analytics JS v1
 * http://code.google.com/p/google-analytics-js/
 * Copyright (c) 2009 Remy Sharp remysharp.com / MIT License
 * $Date: 2009-02-25 14:25:01 +0000 (Wed, 25 Feb 2009) $
 */
function gaTrack(urchinCode, domain, url) {

  function rand(min, max) {
      return min + Math.floor(Math.random() * (max - min));
  }

  var i=1000000000,
      utmn=rand(i,9999999999), //random request number
      cookie=rand(10000000,99999999), //random cookie number
      random=rand(i,2147483647), //number under 2147483647
      today=(new Date()).getTime(),
      win = window.location,
      img = new Image(),
      urchinUrl = 'http://www.google-analytics.com/__utm.gif?utmwv=1.3&utmn='
          +utmn+'&utmsr=-&utmsc=-&utmul=-&utmje=0&utmfl=-&utmdt=-&utmhn='
          +domain+'&utmr='+win+'&utmp='
          +url+'&utmac='
          +urchinCode+'&utmcc=__utma%3D'
          +cookie+'.'+random+'.'+today+'.'+today+'.'
          +today+'.2%3B%2B__utmb%3D'
          +cookie+'%3B%2B__utmc%3D'
          +cookie+'%3B%2B__utmz%3D'
          +cookie+'.'+today
          +'.2.2.utmccn%3D(referral)%7Cutmcsr%3D' + win.host + '%7Cutmcct%3D' + win.pathname + '%7Cutmcmd%3Dreferral%3B%2B__utmv%3D'
          +cookie+'.-%3B';

  // trigger the tracking
  img.src = urchinUrl;
}

Well, it actually does nothing more than creating an HTTP request for ‘__utm.gif’ with a query string constructed from caller-specified parameters and some random numbers. Of course, it also has to append an image element to attach the request onto. To track a loading event of any XUL file in your extension, just save the gajs.js within your extension folder, make appropriate changes to the following snippet and embed it into the XUL file:


The single absolutely required modification to the above code is the first parameter passed to gaTrack. The other two parameters only affect how statistics are organized in your GA report. Every time a user’s Firefox/SeaMonkey loads your browser overlay XUL file, which happens at browser startup if your extension is installed and enabled, GA will track a visit to ‘yoursite.com/content/overlay.xul’.

Because the gaTrack function does not really collect any info from the user, GA will only be able to retrieve data about the user from the HTTP header sent by Firefox/SeaMonkey. The function also does not support tracking events other than pageview. In other words, you will only get rather limited data regarding the users of your Firefox/SeaMonkey extension, compared to what you would normally get from GATC embedded in normal webpages or Chromium extensions. However, you can always extend gajs.js to provide more info, if you really need that info.

This entry was posted in Chromium extension, JavaScript, Mozilla extension, Web and tagged , , , , , , , , , , . Bookmark the permalink.