Skip to content

Instantly share code, notes, and snippets.

@dustinlarimer
Last active August 29, 2015 14:10
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 dustinlarimer/23b1de67060a09582298 to your computer and use it in GitHub Desktop.
Save dustinlarimer/23b1de67060a09582298 to your computer and use it in GitHub Desktop.
Auto-tracker
function _go(f){/in/.test(document.readyState)?setTimeout('_go('+f+')',9):f()}
_go(function(){
var COOKIE_KEY = "COOKIE-ID",
COOKIE_EXP = undefined, // 1000*60*60*24*365,
IS_KNOWN = false;
var CurrentSession = {},
wpMeta = WP_META || {},
interval;
// WP_META exposes WP meta data for each page
var now = new Date();
var wp_created_date = (wpMeta["created"]) ? new Date(wpMeta["created"]) : undefined;
var wp_updated_date = (wpMeta["updated"]) ? new Date(wpMeta["updated"]) : undefined;
var client = new Keen({
projectId: "PROJECT_ID",
writeKey: "WRITE_KEY"
});
if (Cookies.enabled && Cookies.get(COOKIE_KEY)) {
IS_KNOWN = true;
try {
CurrentSession = JSON.parse(decodeURIComponent( Cookies.get(COOKIE_KEY) ));
} catch(e) {}
}
var DataModel = {
visitor: {
"id" : CurrentSession["id"] || uuid.v4(),
"language" : navigator.languages? navigator.languages[0] : (navigator.language || navigator.userLanguage),
"views" : parseInt(CurrentSession["views"]) || 0,
"returns" : parseInt(CurrentSession["returns"]) || 0,
"absence" : (CurrentSession["last_active"]) ? parseFloat( ((now-new Date(CurrentSession["last_active"])) / (1000*60*60)).toFixed(4) ) : null,
"is": {
"admin" : wpMeta['is_admin'] || false,
"known" : IS_KNOWN
}
},
engagement: {
"duration": {
"active" : 0,
"idle" : 0,
"total" : 0,
"historical": {
"active" : parseInt(CurrentSession["dur_hist_active"]) || 0,
"idle" : parseInt(CurrentSession["dur_hist_idle"]) || 0,
"total" : parseInt(CurrentSession["dur_hist_total"]) || 0
}
},
"scrolling": {
"max" : 0,
"ratio" : 0.00
}
},
ip_address : "${keen.ip}",
geo: {
/* populated via add-on */
},
user_agent : "${keen.user_agent}",
tech: {
// Careful!
"cookies" : Cookies.enabled,
"screen" : getScreenProperties(),
"window" : getWindowProperties()
/* populated via add-on */
},
referrer: {
"url" : document.referrer,
"origin" : CurrentSession["ref_origin"] || document.referrer,
"info": {
/* populated via add-on */
}
},
page: {
"url" : document.location.href,
"title" : document.title,
"origin" : CurrentSession["page_origin"] || document.location.href,
"type" : wpMeta["page_type"] || "unknown",
"created": {
"date" : (wp_created_date) ? wp_created_date.toISOString() : undefined,
"days_ago" : (wp_created_date) ? parseInt( (now-wp_created_date)/(1000*60*60*24) ) : undefined,
"hour_of_day" : (wp_created_date) ? wp_created_date.getHours() : undefined,
"day_of_week" : (wp_created_date) ? parseInt( 1+wp_created_date.getDay() ) : undefined,
"day_of_month" : (wp_created_date) ? wp_created_date.getDate() : undefined,
"month" : (wp_created_date) ? parseInt( 1+wp_created_date.getMonth() ) : undefined,
"year" : (wp_created_date) ? wp_created_date.getFullYear() : undefined
},
"updated": {
"date" : (wp_updated_date) ? wp_updated_date.toISOString() : undefined,
"days_ago" : (wp_updated_date) ? parseInt( (now-wp_updated_date)/(1000*60*60*24) ) : undefined,
"hour_of_day" : (wp_updated_date) ? wp_updated_date.getHours() : undefined,
"day_of_week" : (wp_updated_date) ? parseInt( 1+wp_updated_date.getDay() ) : undefined,
"day_of_month" : (wp_updated_date) ? wp_updated_date.getDate() : undefined,
"month" : (wp_updated_date) ? parseInt( 1+wp_updated_date.getMonth() ) : undefined,
"year" : (wp_updated_date) ? wp_updated_date.getFullYear() : undefined
},
"tags" : wpMeta["tags"] || [],
"categories" : wpMeta["categories"] || [],
"info": {
/* populated via add-on */
}
},
path: {
"id" : CurrentSession["path_id"] || uuid.v4(),
"edge" : (document.referrer || "unknown") + " -> " + document.location.href,
"step" : parseInt(CurrentSession["step"]) || 0,
"is": {
"arriving" : false,
"traversing" : false,
"refreshing" : false,
"returning" : false
},
},
time: {
"hour_of_day" : now.getHours(),
"day_of_week" : parseInt( 1+now.getDay() ),
"day_of_month" : now.getDate(),
"month" : parseInt( 1+now.getMonth() ),
"year" : now.getFullYear(),
},
keen: {
"timestamp": now.toISOString(),
"addons": [
{
"name" : "keen:ip_to_geo",
"input" : { "ip": "ip_address" },
"output" : "geo"
},
{
"name" : "keen:ua_parser",
"input" : { "ua_string": "user_agent" },
"output" : "tech"
},
{
"name" : "keen:url_parser",
"input" : { "url": "page.url" },
"output" : "page.info"
},
{
"name" : "keen:referrer_parser",
"input" : { "referrer_url": "referrer.url", "page_url": "page.url" },
"output" : "referrer.info"
}
]
}
};
if (document.location.origin && document.referrer.indexOf(document.location.origin) > -1) {
DataModel.path.is.traversing = true;
}
else if (DataModel["referrer"].url === DataModel.page.url) {
DataModel.path.is.refreshing = true;
}
else {
DataModel.path.is.arriving = true;
}
// Reset path.id if visitor has been idle for at least an 1 hour
if (DataModel.visitor.absence >= 1) {
DataModel.visitor.returns++;
DataModel.path.is.returning = true;
DataModel.path["id"] = uuid.v4();
DataModel.path.step = 0;
}
DataModel.visitor.views++;
DataModel.path.step++;
function getScreenProperties(){
var props = {};
if (window.screen) {
props["height"] = window.screen["height"] || null;
props["width"] = window.screen["width"] || null;
props["colorDepth"] = window.screen["colorDepth"] || null;
props["pixelDepth"] = window.screen["pixelDepth"] || null;
props["availHeight"] = window.screen["availHeight"] || null;
props["availWidth"] = window.screen["availWidth"] || null;
props.orientation = {
angle: ( window.screen.orientation ) ? window.screen.orientation["angle"] : 0,
type: ( window.innerWidth > window.innerHeight ) ? "landscape": "portrait"
};
}
return props;
}
function getWindowProperties(){
var body = document.body, html = document.documentElement;
var props = {
height: window.innerHeight,
width: window.innerWidth,
scrollable: Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight ) || null,
};
if (window.screen) {
props.ratio = {
height: (window.screen.availHeight) ? parseFloat( (window.innerHeight/window.screen.availHeight).toFixed(2) ) : null,
width: (window.screen.availWidth) ? parseFloat( (window.innerWidth/window.screen.availWidth).toFixed(2) ) : null
};
}
return props;
}
function updateModel(){
var scroll_max = DataModel.engagement["scrolling"].max,
scroll_now = getScrollOffset();
if (scroll_now > scroll_max) {
DataModel.engagement["scrolling"].max = scroll_now;
DataModel.engagement["scrolling"].ratio = parseFloat( Number( scroll_now / DataModel.tech["window"].scrollable ).toFixed(2) );
// console.log(DataModel.engagement["scrolling"]);
}
// DataModel.engagement.duration
DataModel.engagement.duration.total++;
DataModel.engagement.duration.historical.total++;
if (document.hasFocus()) {
DataModel.engagement.duration.active++;
DataModel.engagement.duration.historical.active++;
} else {
DataModel.engagement.duration.idle++;
DataModel.engagement.duration.historical.idle++;
}
updateCurrentSession();
}
function getScrollOffset(){
return (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
}
function updateCurrentSession(){
if (!Cookies.enabled) return;
if (document.hasFocus()) now = new Date();
var cookie = {
id : DataModel.visitor["id"],
views : DataModel.visitor.views,
returns : DataModel.visitor.returns,
path_id : DataModel.path["id"],
last_active : now.toISOString(),
step : DataModel.path.step,
dur_hist_total : DataModel.engagement.duration.historical.total,
dur_hist_active : DataModel.engagement.duration.historical.active,
dur_hist_idle : DataModel.engagement.duration.historical.idle,
ref_origin : DataModel["referrer"].origin,
page_origin : DataModel.page.origin
};
Cookies.expire(COOKIE_KEY).set(COOKIE_KEY, encodeURIComponent( JSON.stringify(cookie) ), { expires: COOKIE_EXP });
// console.log( JSON.parse(decodeURIComponent( Cookies.get(COOKIE_KEY) )) );
}
// yay superagent.js!
function getXHR() {
if (window.XMLHttpRequest && ('file:' != window.location.protocol || !window.ActiveXObject)) {
return new XMLHttpRequest;
} else {
try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}
}
return false;
}
function setUnloadListener(){
var attachEvent, whichEvent;
if (window.onpagehide || window.onpagehide === null) {
window.addEventListener("pagehide", handleExit, false);
}
else {
attachEvent = window.attachEvent || window.addEventListener
whichEvent = window.attachEvent ? "onbeforeunload" : "beforeunload";
attachEvent(whichEvent, handleExit);
}
}
function handleExit(e){
client.trigger("exit");
}
setUnloadListener();
updateModel();
interval = setInterval(updateModel, 1000);
client.addEvent("page-load", DataModel);
client.on("exit", function(){
var request = getXHR();
var url = client.url("/projects/"+client.projectId()+"/events/" + "visit");
if (request) {
url += "?api_key=" + client.writeKey();
url += "&data=" + encodeURIComponent( Keen.Base64.encode( JSON.stringify( DataModel ) ) );
request.open('GET', url, false); // synchronous
request.send(null);
}
});
// console.log(JSON.stringify(DataModel, null, 4));
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment