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. |
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.
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.
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.
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.
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.
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.