Last active
August 29, 2015 14:13
-
-
Save agilmore/f5060065d0b6ee137872 to your computer and use it in GitHub Desktop.
Simple JS library which creates Google Analytics compatible __utm[z|a|b] cookies
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(W, D, L) { | |
if (!Date.now) { | |
Date.now = function now() { | |
return new Date().getTime(); | |
}; | |
} | |
if (!String.prototype.startsWith) { | |
Object.defineProperty(String.prototype, 'startsWith', { | |
enumerable: false, | |
configurable: false, | |
writable: false, | |
value: function(searchString, position) { | |
position = position || 0; | |
return this.lastIndexOf(searchString, position) === position; | |
} | |
}); | |
} | |
if (!Array.isArray) { | |
Array.isArray = function(arg) { | |
return Object.prototype.toString.call(arg) === '[object Array]'; | |
}; | |
} | |
/** | |
* Matches referrer urls from 5 biggest search engines. | |
* @type {RegExp} | |
*/ | |
var SEARCH_ENGINE_REGEX = /^https?:\/\/(?:www\.(google)\..+q=([^&]+)|www\.(bing)\.com\/search.+q=([^&]+)|.+(yahoo).com\/search.+(?:\?p|&p)=([^&]+)|(yandex)\.ru\/yandsearch\?.+text=([^&]+)|www\.(baidu)\.com\/s\?.+wd=([^&]+))/; | |
var HOSTNAME = L.hostname; | |
if(HOSTNAME.startsWith('www.')) { | |
HOSTNAME = HOSTNAME.substring(HOSTNAME.indexOf('.') + 1); | |
} | |
/** | |
* Fetch an object containing all url parameters starting with "utm_" | |
* @returns {object} parameters | |
*/ | |
var getUTMParams = function() { | |
var codes = {}; | |
codes.length = 0; | |
if (L.search.length > 1) { | |
var i, | |
pair, | |
pairs = L.search.substr(1).split("&"); | |
for (i = 0; i < pairs.length; i++) { | |
pair = pairs[i].split("="); | |
if(pair[0].startsWith('utm_')) { | |
codes[decodeURIComponent(pair[0])] = pair.length > 1 ? decodeURIComponent(pair[1]) : ""; | |
codes.length++; | |
} | |
} | |
} | |
return codes; | |
}; | |
/** | |
* Compile acquisition data. | |
* 1) From the a current utmz cookie. | |
* 2) Referrers from a search engine. | |
* 3) utm url parameters. | |
* @returns {{campaign: null, source: string, medium: string, content: null, term: null}} | |
*/ | |
var getAcquisitionData = function() { | |
var data = { | |
'campaign': '(direct)', | |
'source': '(direct)', | |
'medium': '(none)', | |
'content': null, | |
'term': null | |
} | |
var utmz = getCookie('__utmz'); | |
if (utmz) { | |
var parts = utmz.split('.'); | |
var campaignData = parts[4].split('|'); | |
for (var i in campaignData) { | |
var pair = campaignData[i].split('='); | |
switch (pair[0]) { | |
case 'utmcsr': | |
data.source = pair[1]; | |
break; | |
case 'utmcmd': | |
data.medium = pair[1]; | |
break; | |
case 'utmccn': | |
data.campaign = pair[1]; | |
break; | |
case 'utmctr': | |
data.term = pair[1]; | |
break; | |
case 'utmcct': | |
data.content = pair[1]; | |
break; | |
} | |
} | |
} | |
if (D.referrer) { | |
var matches = SEARCH_ENGINE_REGEX.exec(D.referrer); | |
if (matches !== null && Array.isArray(matches)) { | |
data.source = matches[1] || matches[3] || matches[5] || matches[7] || matches[9] || false; | |
data.medium = '(organic)'; | |
} | |
} | |
var utmParams = getUTMParams(); | |
if ('utm_source' in utmParams) { | |
data.source = utmParams['utm_source']; | |
} | |
if ('utm_medium' in utmParams) { | |
data.medium = utmParams['utm_medium']; | |
} | |
if ('utm_campaign' in utmParams) { | |
data.campaign = utmParams['utm_campaign']; | |
} | |
if ('utm_term' in utmParams) { | |
data.term = utmParams['utm_term']; | |
} | |
if ('utm_content' in utmParams) { | |
data.content = utmParams['utm_content']; | |
} | |
return data; | |
}; | |
/** | |
* Generate a hash from a string | |
* @param {string} str Domain name to hash | |
* @returns {number} | |
*/ | |
var domainHash = function(str) { | |
var b = 1, | |
c = 0, | |
d; | |
if (str) { | |
for (b = 0, d = str.length - 1; 0 <= d; d--) { | |
c = str.charCodeAt(d); | |
b = (b << 6 & 268435455) + c + (c << 14); | |
c = b & 266338304; | |
if (c != 0) { | |
b = b ^ c >> 21; | |
} | |
} | |
} | |
return b; | |
}; | |
/** | |
* Create a date object the specified number of years/months/days and minutes in the future. | |
* @param years | |
* @param months | |
* @param days | |
* @param minutes | |
* @returns {Date} | |
*/ | |
var getFutureDate = function(years, months, days, minutes) { | |
var date = new Date(); | |
if (years > 0) { | |
date.setYear(date.getFullYear() + years); | |
} | |
if (months > 0) { | |
date.setMonth(date.getMonth() + months); | |
} | |
if (days > 0) { | |
date.setDate(date.getDate() + days); | |
} | |
if (minutes > 0) { | |
date.setMinutes(date.getMinutes() + minutes); | |
} | |
return date; | |
} | |
/** | |
* Get the value of a cookie. | |
* @param {string} name | |
* @returns {string|null} | |
*/ | |
var getCookie = function(name) { | |
return decodeURIComponent(D.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + name + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null; | |
}; | |
/** | |
* Set the value and expiry date of a cookie. | |
* @param {string} name | |
* @param {string} value | |
* @param {Date|undefined} | |
*/ | |
var setCookie = function(name, value, expire) { | |
D.cookie = name + '=' + encodeURIComponent(value) + (expire ? '; expires=' + expire.toUTCString() : '') + '; domain=.' + HOSTNAME + '; path=/'; | |
}; | |
/** | |
* Generate the value of the __utmz cookie. | |
* @param {number} domainHash | |
* @returns {string} | |
*/ | |
var buildUtmz = function(domainHash) { | |
var campaignData = []; | |
var acqData = getAcquisitionData(); | |
campaignData.push('utmcsr=' + acqData.source); | |
campaignData.push('utmccn=' + acqData.campaign); | |
campaignData.push('utmcmd=' + acqData.medium); | |
if (!!acqData.term) { | |
campaignData.push('utmctr=' + acqData.term); | |
} | |
if (!!acqData.content) { | |
campaignData.push('utmcct=' + acqData.content); | |
} | |
return [ | |
domainHash, | |
Math.floor(Date.now() / 1000), | |
1, 1, | |
campaignData.join('|') | |
].join('.'); | |
}; | |
/** | |
* Generate the value of the __utma cookie. | |
* @param {number} domainHash | |
* @returns {string} | |
*/ | |
var buildUtma = function(domainHash) { | |
return domainHash + '.0.0.0.0.0'; | |
}; | |
/** | |
* Generate the value of the __utmb cookie. | |
* @param {number} domainHash | |
* @param {number} pagesViewed | |
* @returns {string} | |
*/ | |
var buildUtmb = function(domainHash, pagesViewed) { | |
return domainHash + '.' + pagesViewed + '.0.' + Date.now(); | |
}; | |
/* | |
* UTMC | |
*/ | |
var hostnameHash = getCookie('__utmc'); | |
if (hostnameHash === null) { | |
hostnameHash = domainHash(HOSTNAME); | |
setCookie('__utmc', hostnameHash); | |
} | |
/* | |
* UTMZ | |
*/ | |
var utmz = buildUtmz(hostnameHash); | |
var expire = getFutureDate(0, 6, 0, 0); | |
setCookie('__utmz', utmz, expire); | |
/* | |
* UTMA | |
*/ | |
var utma = getCookie('__utma'); | |
if (utma === null) { | |
utma = buildUtma(hostnameHash); | |
} | |
expire = getFutureDate(2, 0, 0, 0); | |
setCookie('__utma', utma, expire); | |
/* | |
* UTMB | |
*/ | |
var utmb = getCookie('__utmb'); | |
var pagesViewed = 0; | |
if (utmb !== null) { | |
var parts = utmb.split('.'); | |
pagesViewed = parseInt(parts[1]); | |
} | |
utmb = buildUtmb(hostnameHash, ++pagesViewed); | |
expire = getFutureDate(0, 0, 0, 30); | |
setCookie('__utmb', utmb, expire); | |
})(window, document, window.location); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment