Skip to content

Instantly share code, notes, and snippets.

@shrunyan
Created June 26, 2014 16:55
Show Gist options
  • Save shrunyan/121967f688ad5561cbc5 to your computer and use it in GitHub Desktop.
Save shrunyan/121967f688ad5561cbc5 to your computer and use it in GitHub Desktop.
Google analytics tracking augmentation.
jQuery(document).ready(function ($) {
/* <a> TAG TRACKER
* @Version: 0.0.2
* @Author: Stuart Runyan
* @Documentation: http://code.google.com/apis/analytics/docs/tracking/eventTrackerGuide.html
* @trackList: Add all domains that you want to track as "internal".
* Allow regular expressions
* It is not neccessary to include the domain this code resides on.
* If the active domain is include in the list there are checks to insure
* we don't double track.
* @downloadExt: Add all extensions you want to track as downloads
*
* v. 0.0.5 Support for regular expressions within tracklist
* v. 0.0.4 Actions only fire for local links
* v. 0.0.3 Use hostname property of href rather than host to exclude port number
* v. 0.0.2 Adding debug option
* v. 0.0.1 Initial sccipt build
*/
var conf = {
trackList: [
// Support base domain hostnames (localhost, tracker.local and tracker.com) with optional hostnames (m and www)
'((m|www)\.)?(tracker\.local|tracker\.com|localhost)$'
],
downloadExt: '7z|aac|arc|arj|asf|asx|avi|bin|csv|docx?|dwf|dwg|dxf|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|msi|msp|pdf|phps|png|ppt|qtm?|ra(m|r)?|rtf|sea|sit|tar|tgz|torrent|txt|wav|wma|wmv|wpd|xlsx?|xml|z|zip',
debug: false
};
/*************************************************************************/
/************************** TRACKER LOGIC ********************************/
/*************************************************************************/
var Tracker = {
localhost: window.location.hostname,
isDownload: new RegExp("\\.(" + conf.downloadExt + ")$", "i"),
isInternal: false,
isExternal: false,
isLocal: false,
getType: {
download: function () {
/* Download Tracker
*/
if (Tracker.isDownload.test(Tracker.url)) {
return Tracker.gaPush("Downloads", Tracker.url.split('.').pop().toUpperCase(), Tracker.url, undefined, undefined);
}
},
action: function () {
/* Javascript Interaction Tracker
* Local Links that have a hash character
*/
if (Tracker.isLocal && Tracker.urlHash.indexOf('#') != -1) {
return Tracker.gaPush('Action', Tracker.urlHash, Tracker.url, undefined, undefined);
}
},
mail: function () {
/* Mail Tracker
*/
if (Tracker.urlProtocol == 'mailto:') {
return Tracker.gaPush('E-Mail', event.type, Tracker.urlPath, undefined, undefined);
}
},
phone: function () {
/* Phone Tracker
*/
if (Tracker.urlProtocol == 'tel:') {
return Tracker.gaPush('Phone', event.type, Tracker.urlPath, undefined, undefined);
}
},
internal: function () {
/* Internal Link Tracker
*/
if (Tracker.isInternal) {
return Tracker.gaPush('Internal Domain', Tracker.urlHostname, Tracker.url, undefined, undefined);
}
},
external: function () {
/* External Link Tracker
*/
if (Tracker.isExternal) {
return Tracker.gaPush('External Domain', Tracker.urlHostname, Tracker.url, undefined, undefined);
}
}
},
getLocation: function () {
var s = conf.trackList.length,
// Create a regular expression from tracklist
re = new RegExp(conf.trackList.join("|"), "i");
// Set inital value
this.isExternal = false;
this.isInternal = false;
this.isLocal = false;
// Link is not mailto: or tel: protocol
if (this.urlProtocol.indexOf('http') != -1) {
// Is Local?
// Link is localhost
if (Tracker.urlHostname == this.localhost) {
return this.isLocal = true;
}
// Is Internal?
// Link is not localhost and must qualify against the @trackList
for (var i = 0; i < s; i++) {
if (re.test(Tracker.urlHostname)) {
return this.isInternal = true;
}
}
// Is External?
// Link is not localhost and not in track list(implied above)
return this.isExternal = true;
}
},
gaPush: function (c,a,l,v,b) {
/* Push Data to Google Analytics
*
* Category: string *
* Action: string *
* Label: string
* Value: integer
* Boolean: default(false) **** Does setting this to undefined change this value?
*
* Options can be null!!!
*/
if (conf.debug) {
console.log(c,a,l,v,b);
}
ga('send','event',c,a,l,v,b);
},
init: function (elem) {
// Create <a> element to access url values
// http://stackoverflow.com/a/736970
var a = document.createElement("a");
a.href = elem;
// IE drops the hostname property for dynamically generated relative urls.
// If the hostname property is empty, generate a new anchor from an absolute url.
a = a.hostname ? a : function(l) {
// IE6 insists on returning relative urls for anchors (href) with relative paths, but
// returns an absolute url for images (src). Generate an image, setting the src property
// to the (relative) href, then set the href to the (absolute) src value, and return the
// resulting anchor.
var i = document.createElement("img");
i.src = l.href;
l.href = i.src;
i.src = null;
return l;
}(a);
// Capture link values
this.url = a.href;
this.urlProtocol = a.protocol;
this.urlHost = a.host.toLowerCase();
this.urlHostname = a.hostname.toLowerCase();
this.urlPath = a.pathname;
this.urlHash = a.hash;
this.urlQuery = a.search;
// Check if external or internal?
this.getLocation();
// Cycle through link types and check for matches
// http://stackoverflow.com/a/921808
for (var key in this.getType) {
if (this.getType.hasOwnProperty(key)) {
this.getType[key]();
}
}
}
}; //End Tracker
/*
* Object.keys Polyfill
*/
if (!Object.keys) {
Object.keys = function (obj) {
var keys = [],
k;
for (k in obj) {
if (Object.prototype.hasOwnProperty.call(obj, k)) {
keys.push(k);
}
}
return keys;
};
}
/*
* Document EventListener
*/
$(document.body).click(function (event) {
if (conf.debug) {
console.log('--------------------');
console.log(event);
event.preventDefault();
}
/*
* Event Delegation
* http://www.learningjquery.com/2009/09/working-with-events-part-3-more-event-delegation-with-jquery#javascript-6
*/
var elem = event.target;
while(elem.nodeName != "A" && elem.parentNode) {
elem = elem.parentNode;
}
if (elem.nodeName == "A") {
Tracker.init(elem);
// TODO: Wait for Tracker to finish
/* - Must have href attribute
* - Must not have a target attribute, or target must be _self
* - How to handle the case where other events may be preventing the clickthrough?
*/
/*
if (!conf.debug) {
setTimeout(function() {
window.location = event.target.href;
}, 100);
}
*/
}
});
}); // End on Ready
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment