User Timings - Web Tracking (ga.js)

This document provides a comprehensive guide on how to use the _trackTiming method.

Introduction

Studies have shown that reducing the time a page takes to load improves the overall user experience of a site. Google Analytics has a number of powerful reports that automatically track page load time. But what if you want to track the time it takes for a particular resource to load?

For example, does loading a popular JavaScript library take too long, diminishing the site experience for certain users?

User timings allow you to answer this question by providing a native way to track a period of time in Google Analytics.

To see a working example check out the User Timings sample code.

Setting Up User Timings

To collect user timing data, you'll need to use the _trackTiming method, which sends time data to Google Analytics.

_gaq.push([‘_trackTiming’, category, variable, time, opt_label, opt_sample]);

Where the parameters represent:

Parameter Value Required Summary
category string yes A string for categorizing all user timing variables into logical groups for easier reporting purposes. For example you might use value of jQuery if you were tracking the time it took to load that particular JavaScript library.
variable string yes A string to indicate the name of the action of the resource being tracked. For example you might use the value of JavaScript Load if you wanted to track the time it took to load the jQuery JavaScript library. Note that same variables can be used across multiple categories to track timings for an event common to these categories such as Javascript Load and Page Ready Time, etc.
time number yes The number of milliseconds in elapsed time to report to Google Analytics. If the jQuery library took 20 milliseconds to load, then you would send the value of 20.
opt_label string no A string that can be used to add flexibility in visualizing user timings in the reports. Labels can also be used to focus on different sub experiments for the same category and variable combination. For example if we loaded jQuery from the Google Content Delivery Network, we would use the value of Google CDN.
opt_sampleRate number no A number to manually override the percent of visitors whose timing hits get sent to Google Analytics. The default is set at the same number as general site speed data collection and is based as a percentage of visitors. So if you wanted to track _trackTiming hits for 100% of visitors, you would use the value 100. Note that each hit counts against the general 500 hits per session limit.

Back to Top

Tracking Time Spent

When you use the _trackTiming method, you specify the amount of milliseconds spent in the time parameter. So it’s up to you, the developer, to write code to capture this period of time. The easiest way to do this is to create a timestamp at the beginning of a period of time and create another timestamp at the end of the period. Then you can take the difference between both timestamps to get time spent.

Here’s a trivial example:

var startTime = new Date().getTime();

setTimeout(myCallback, 200);

function myCallback(event) {

  var endTime = new Date().getTime();
  var timeSpent = endTime - startTime;

  _gaq.push(['_trackTiming', 'Test', 'callback_timeout', timeSpent, 'animation']);
}

The starting timestamp is retrieved by creating a new Date object and getting the time in milliseconds. Next, the setTimeout function is used to call the myCallback function in 200 milliseconds. Once the callback function is executed, the endTime timestamp is retrieved by creating a new Date object. Then the difference of the end and start times is calculated to get time spent. Finally time spent is sent to Google Analytics.

This example is trivial, but illustrates the concept of how to track time. Lets look at a more realistic example.

Back to Top

Tracking Time Spent Loading a JavaScript Resource

Today, many sites include 3rd party JavaScript libraries or request data through JSON objects. While your site might load these resources quickly at home, the same resources might load very slowly for users in other countries. These slow loading resources can degrade the site experience for international users.

The site speed user timing feature can help you collect and report how long these resources take to load.

Here’s a simple example demonstrating how to track the time spent of a function that asynchronously loads JavaScript resources:

var startTime;

function loadJs(url, callback) {
  var js = document.createElement('script');
  js.async = true;
  js.src = url;
  var s = document.getElementsByTagName('script')[0];

  js.onload = callback;
  startTime = new Date().getTime();

  s.parentNode.insertBefore(js, s);
}

function myCallback(event) {
  var endTime = new Date().getTime();
  var timeSpent = endTime - startTime;
  _gaq.push(['_trackTiming', 'jQuery', 'Load Library', timeSpent, 'Google CDN']);

  // Library has loaded. Now you can use it.
};

Notice that this example is very similar to the previous example.

In this example, loadJs is a utility function that loads JavaScript resources by dynamically creating a script element and attaching it to the browser’s DOM. The function accepts two parameters: a URL as a string, and a callback function that will be executed once the script has loaded.

Inside loadJs, a beginning timestamp is stored in startTime. Once the resource has been loaded, the callback function is executed. In the callback function, the end timestamp is retrieved and used to calculate the time it took to load the JavaScript resource. This time spent is sent to Google Analytics using the _trackTiming method.

So by calling:

loadJs(‘//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js’, callback);

Will asynchronously load the jQuery library from the Google Content Delivery network, and once complete, execute the callback function, that in turns sends the load time of the resource to Google Analytics.

Back to Top

Working With Multiple User Timings

Say you wanted to load multiple JavaScript resources using the code above. Because the startTime variable is global, every time you track the start of a period of time, the startTime variable will be overwritten, generating the wrong time spent.

So as a best practice, you need to maintain a unique instance of the start and end time for every resource you want to track.

Also notice that the category and variable parameters to _trackTiming are hard coded. So if you use loadJs to load multiple resources, you will not be able to distinguish each resource in the Google Analytics reports.

Both problems can be solved by storing the timing and _trackTiming parameters in a JavaScript object.

Creating a JavaScript object to store user timings.

Here’s a simple JavaScript object that can be used to store the user timing data for each resource being tracked:

function TrackTiming(category, variable, opt_label) {
  this.category = category;
  this.variable = variable;
  this.label = opt_label ? opt_label : undefined;
  this.startTime;
  this.endTime;
  return this;
}

TrackTiming.prototype.startTime = function() {
  this.startTime = new Date().getTime();
  return this;
}

TrackTiming.prototype.endTime = function() {
  this.endTime = new Date().getTime();
  return this;
}

TrackTiming.prototype.send = function() {
  var timeSpent = this.endTime - this.startTime;
  window._gaq.push(['_trackTiming', this.category, this.variable, timeSpent, this.label]);
  return this;
}

We can now use this object to make loadJs work for multiple requests.

Sending stored user timings

Now that we have a way to store timing data for each resource we want to track, here is how to update loadJs to use it:

var tt = new TrackTiming('jQuery', 'Load Library', 'Google CDN');

loadJs(‘//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js’, myCallback, tt);

function loadJs(url, callback, tt) {
  var js = document.createElement('script');
  js.async = true;
  js.src = url;
  js.onload = callback;
  var s = document.getElementsByTagName('script')[0];

  tt.startTime();
  js.tt = tt;

  s.parentNode.insertBefore(js, s);
}

function myCallback(event) {
  var e = event || window.event;
  var target = e.target ? e.target : e.srcElement;

  target.tt.endTime().send();

  // Library has loaded. Now you can use it.
}

The code above starts by creating a new TrackTiming object where the category, variable, and optional label are passed into the constructor. The TrackTiming object is then passed as a parameter to the loadJs function.

Inside loadJs, the startTime method is called to get and store the beginning timestamp.

In the previous example, the callback function could easily access the startTime variable because it was global. Now that startTime is part of the TrackTiming object, we need a way to pass this object from the loadJs function to the callback function.

To solve this problem one strategy is to add the TrackTiming object as a property to the script element. Since the callback function is executed from the script onload method, the callback is passed an event object as a parameter. This event object can then be used to retrieve the original script object that fired the event, and that script object can be in turn used to access our TrackTiming object.

Once we can access our original TrackTiming object, the script can then end the time and send the data.

See a live demo of this example on our samples site.

This pattern of adding the TrackTiming object as a property to the object being tracked, tends to work well to track other asynchronous loading mechanisms like using the XMLHttpRequest object.

Back to Top

Tracking XMLHttpRequests

Another common way to asynchronously load webpage resources is to use the XMLHttpRequest object. The time it takes to load these resources can also be tracked using both the _trackTiming method and TimeTracker object.

Here’s an example that loads the file of quotes from the server.

var url = ‘//myhost.com/quotes.txt’;
var tt = new TrackTime('xhr demo', 'load quotes');

makeXhrRequest(url, myCallback, tt);

function makeXhrRequest(url, callback, tt) {
  if (window.XMLHttpRequest) {
    var xhr = new window.XMLHttpRequest;
    xhr.open('GET', url, true);
    xhr.onreadystatechange = callback;

    tt.startTime();
    xhr.tt = tt;

    xhr.send();
  }
}

function myCallback(event) {
  var e = event || window.event;
  var target = e.target ? e.target : e.srcElement;

  if (target.readyState == 4) {
    if (target.status == 200) {

      target.tt.endTime().send();

      // Do something with the resource.
    }
  }
}

This example looks really similar to the loadJs example. See the live demo here.

Back to Top

Avoid Sending Bad Data

In the examples above, to get the time spent, the code subtracts the end time from the start time. This generally works well as long as the start time is less than the end time. But it can become an issue if the time in the browser changes. If the user changes their machine time after the start time is set, bad data can be sent to Google Analytics. A big problem with sending one large bad value, is that it will skew your average and total metrics.

So it’s generally a best practice to make sure the time spent is greater than 0 and less than some period of time, before you send the data onto Google Analytics. We can modify the TimeTracker send method above, to perform this check:

TrackTiming.prototype.send = function() {
  var timeSpent = this.endTime - this.startTime;

  var hourInMillis = 1000 * 60 * 60;

  if (0 < timeSpent && timeSpent < hourInMillis) {
    window._gaq.push(['_trackTiming', this.category, this.variable, timeSpent, this.label]);
  }

   return this;
}

Overriding The Sample Rate and Debugging

The _trackTiming method only sends data to Google Analytics at the same rate for all site speed metrics collected by Google Analytics. By default this is set to 1% of all visitors.

For sites with a large amount of traffic the default should be fine. But for sites with less traffic, you can increase the sample rate by setting the optional sample rate parameter. For example:

_gaq.push(['_trackTiming', 'jQuery', 'Load Library', timeSpent, 'Google CDN', 50]);

Will collect _trackTiming data from 50% of visitors.

Alternatively, you can set the _setSiteSpeedSampleRate method to set the sample rate for all site speed timings including the _trackTiming method. So for example:

_gaq.push([‘_setSiteSpeedSampleRate’, 50]);

Will also collect _trackTiming data from 50% of visitors.

Typically when you test and verify a Google Analytics implementation you have very little traffic to the site you are testing. So it’s typically useful to increase the sample rate to 100% while testing.

Back to Top

Tracking Other Time Events

While all the example above focus on using the _trackTiming method to track how long it takes to load resources, this method can also be used to track general durations of time. For example you could track:

  • The time a visitor spends watching a video.
  • The time it takes to complete a level in a game.
  • The time a visitor spends reading a section of a website.

In each of these cases you can reuse the same TimeTracker JavaScript object presented above to simplify collecting and sending the time spent data to Google Analytics.