Skip to content

Instantly share code, notes, and snippets.

@agilmore
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agilmore/f5060065d0b6ee137872 to your computer and use it in GitHub Desktop.
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
(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