Skip to content

Instantly share code, notes, and snippets.

@baado
Created May 20, 2012 02:57
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save baado/2737233 to your computer and use it in GitHub Desktop.
Save baado/2737233 to your computer and use it in GitHub Desktop.
Tracking JavaScript file loading time with Google Analytics
// Copyright 2012 Google Inc. All Rights Reserved.
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview A nice little script demo-ing how to use the _trackTiming
* feature in Google Analytics to track the time it takes to
* load resources asynchrounously. This script defines the TrackTiming
* class to abstract all the timing logic. You can reuse this class
* in your own code to simplify tracking.
* @author api.nickm@gmail.com (Nick Mihailovski)
*/
/**
* The original source code is below.
* http://code.google.com/p/analytics-api-samples/source/browse/trunk/src/tracking/javascript/v5/user-timing/user-timing.js
*
* This source code is customized to use quickly, and added some options.
* But same to original, not work on IE 8 and below.
*/
/**
* Settings *
*
* List your JavaScript files to "_loadJsAry" array.
* ['path/to/js/file', 'JavaScript Description']
*/
var _loadJsAry = [
['js/ga.js', 'Load Google Analytics Component']
, ['js/jquery-min.js', 'Load jQuery']
, ['js/jquery-ui-min.js', 'Load jQuery']
];
/**
* If debug, up sample rate to 100%. If not debug, up sample rate to 1%.
* (google analytics default)
*/
var debug = true;
var _ga = _ga || {};
var _gaq = _gaq || [];
if (debug) {
_gaq.push(['_setSiteSpeedSampleRate', 100]);
}
var _curTrackIndex = 0;
/**
* Asynchronously loads a JavaScript resources by creating a DOM Script
* element and appending it to the page. The time it takes to load the
* script is tracking using a TrackTiming object. Just before the script
* element is added to the page, the TrackTiming timer is started. The
* entire TrackTiming object is then set as a property on the script
* object. And finally the script element is added to the DOM to force
* the browser to load the script resource.
* Added: version branch, relaying mechanism.
* @param {String} url The URL of a JavaScript resource to load
* asynchronously.
* @param {Function} callback The callback function to execute once the
* JavaScript resource has loaded.
* @param {Object} tt The TrackTiming object used to track the time the
* browser takes to load the resource.
*/
function includeJS(debug) {
var url = cacheBust(_loadJsAry[_curTrackIndex][0]);
if ("undefined" !== typeof document.documentElement.style.maxHeight) {
if (!/*@cc_on!@*/false){
var t1 = new TrackTiming('JavaScript Libraries', _loadJsAry[_curTrackIndex][1]);
if (debug) {
t1.debug();
}
if ("undefined" !== typeof _loadJsAry[_curTrackIndex][2] && true == _loadJsAry[_curTrackIndex][2]) {
loadJs(url, utCallback, t1, true);
}
} else if (document.documentMode >= 9) {
// IE8 or below.
loadJsIE(url);
} else {
//IE7, IE8 (IE7 mode)
loadJsIE(url);
}
} else {
// IE 6.0 or below.
loadJsIE(url);
}
_curTrackIndex ++;
}
/**
* Asynchronously loads a JavaScript resources by creating a DOM Script
* element and appending it to the page. The time it takes to load the
* script is tracking using a TrackTiming object. Just before the script
* element is added to the page, the TrackTiming timer is started. The
* entire TrackTiming object is then set as a property on the script
* object. And finally the script element is added to the DOM to force
* the browser to load the script resource.
* Added: async paramater.
* @param {String} url The URL of a JavaScript resource to load
* asynchronously.
* @param {Function} callback The callback function to execute once the
* JavaScript resource has loaded.
* @param {Object} tt The TrackTiming object used to track the time the
* browser takes to load the resource.
* @param {?Boolean} async Whether JavaScript Library load asynchronously
* or not. default false.
*/
function loadJs(url, callback, tt, async) {
var js = document.createElement('script');
async = async || false;
js.async = async;
js.src = url;
js.onload = callback;
js.charset = 'UTF-8';
var ss = document.getElementsByTagName('script');
var s = ss[ss.length-1];
js.time = tt.startTime();
s.parentNode.insertBefore(js, s.nextSibling);
}
/**
* loadJs() for IE 8 or below.
* But still this version do not work correctly.
*/
function loadJsIE(url) {
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200){
utCallbackIE(xmlHttp);
}
};
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}
/**
* Callback function after one JavaScript loaded. This will be executed once the JavaScript
* resource is loaded from loadJs. The event object is the onload event
* fired from the script element. So the event object is used to get a
* reference to the script object as well as the TrackTiming object. Finally
* the elapsed time is outputed to the page.
* Add: relaying mechanism. if next JavaScript exists, load it.
* @param {Object} event The onload event object that is fired once the
* script has loaded.
*/
function utCallback(event) {
var e = event || window.event;
var target = e.target ? e.target : e.srcElement;
target.time.endTime().send();
if (typeof(_loadJsAry[_curTrackIndex]) !== 'undefined') {
includeJS(debug);
}
}
function utCallbackIE(xmlHttp) {
var url;
eval(xmlHttp.responseText);
if (typeof(_loadJsAry[_curTrackIndex]) !== 'undefined') {
includeJS(debug);
}
}
/**
* Utility function to add a random number as a query parameter to the url.
* This assumes the URL doesn't have any existing query parameters or
* anchor tags.
* @param {String} url The url to add cache busting to.
*/
function cacheBust(url) {
if (url.indexOf('?') >= 0) {
return url + '&t=' + Math.round(Math.random() * 100000);
} else {
return url + '?t=' + Math.round(Math.random() * 100000);
}
}
function TrackTiming(category, variable, opt_label) {
/**
* Maximum time that can elapse for the tracker to send data to Google
* Analytics. Set to 10 minutes in milliseconds.
* @type {Number}
*/
this.MAX_TIME = 10 * 60 * 1000;
this.category = category;
this.variable = variable;
this.label = opt_label ? opt_label : undefined;
this.startTime;
this.elapsedTime;
this.isDebug = false;
return this;
}
/**
* Starts the timer.
* @return {Object} This TrackTiming instance. Useful for chaining.
*/
TrackTiming.prototype.startTime = function() {
this.startTime = new Date().getTime();
return this;
};
/**
* Ends the timer and sets the elapsed time.
* @return {Object} This TrackTiming instance. Useful for chaining.
*/
TrackTiming.prototype.endTime = function() {
this.elapsedTime = new Date().getTime() - this.startTime;
return this;
};
/**
* Enables or disables the debug option. When set, this will override the
* default sample rate to 100% and output each request to the console.
* When set to false, will send the default sample rate configured by
* calling the _setSampleRate tracking method.
* @param {?Boolean} opt_enable Enables or disables debug mode. If not present,
* debug mode will be enabled.
* @return {Object} This TrackTiming instance. Useful for chaining.
*/
TrackTiming.prototype.debug = function(opt_enable) {
this.isDebug = opt_enable == undefined ? true : opt_enable;
return this;
};
/**
* Send data to Google Analytics with the configured variable, action,
* elapsed time and label. This function performs a check to ensure that
* the elapsed time is greater than 0 and less than MAX_TIME. This check
* ensures no bad data is sent if the browser client time is off. If
* debug has been enebled, then the sample rate is overridden to 100%
* and all the tracking parameters are outputted to the console.
* @return {Object} This TrackTiming instance. Useful for chaining.
*/
TrackTiming.prototype.send = function() {
if (0 < this.elapsedTime && this.elapsedTime < this.MAX_TIME) {
var command = ['_trackTiming', this.category, this.variable,
this.elapsedTime, this.label];
if (this.isDebug) {
// Override sample rate if debug is enabled.
command.push(100);
if (window.console && window.console.log) {
console.log(command);
}
}
_gaq.push(command);
}
return this;
};
includeJS(debug);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment