« Back to Index

Comments on Analytics code…

View original Gist on GitHub

Comments.md

The original source code is shown at the bottom of this page.

My comments were as follows…

##Original JavaScript code:

//-----------------------------------------------------------------------------
if (typeof define !== 'function') { var define = require('amdefine')(module)}//node.js magic
//-----------------------------------------------------------------------------
define(function(require){ //BEGIN AMD
//-----------------------------------------------------------------------------
/**
 @classdesc The Analytic Client provides an API for applications to submit
   events for collation and later analysis.
  
  	This version makes some assumptions based on its intended usage.
  	>=IE9 support only, requires native JSON and XMLHttpRequest or XDomainRequest.

	@param {object} config This contains the followin attributes:
		server : string : the address of the events server
		product : string : uniquely identifies product
		probability : number : 0 == never, 1.0 == always trigger non critical events
 @class
*/
//-----------------------------------------------------------------------------
function AC(config)
{
	this.events = []; //this is where we store events until we send them
	this.s = config.server;
	this.p = config.product;
	this.tprob = config.probability
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
AC.EN_IP 	= 1; //adds user IP address to event server side
AC.EN_GEOIP = 2; //adds user Location based on IP to event server side
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/**
	Add an event to the internal queue.

	@param {number} eventId The id of the event
	@param {Object} eventData The payload data of the event
	@param {array}	enrich (optional) An array of possible enrichments
*/
//-----------------------------------------------------------------------------
AC.prototype.addEvent = function(eventId,eventData,enrich)
{
	this.events.push(
	{
		p : this.p,
		id : eventId,
		ts : (new Date().getTime()),
		data : eventData,
		enrich : enrich
	});
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/**
	Add an event to the internal queue.

	@param {number} eventId The id of the event
	@param {Object} eventData The payload data of the event
	@param {array}	enrich (optional) An array of possible enrichments
	@param {function} callback This will be fired after event has
	 been added to queue if present
*/
//-----------------------------------------------------------------------------
AC.prototype.addSendEvent = function(eventId,eventData,enrich,callback)
{
	this.addEvent(eventId,eventData,enrich);
	this.sendEvents(callback);
};
//-----------------------------------------------------------------------------
/**
	Create the payload required for the special Page Load event.
	This event is automatically triggered whenever the user loads a new
	page, it contains detail about their navigation along with performance
	timings.

	@return {Object} The created Page Load payload.
*/
//-----------------------------------------------------------------------------
AC.prototype.createPLData = function()
{
	return {		
		url : window.location.pathname,
		referrer : document.referrer
	};
};
//-----------------------------------------------------------------------------
/**
	This will send all events currently stored in the client to the 
	server endpoint.

	@param {function} callback Fired upon completion of sending messages.
*/
//-----------------------------------------------------------------------------
AC.prototype.sendEvents = function(callback)
{
	var events = this.events;
	this.events = [];
	var xmlhttp = null;

	if(typeof XDomainRequest != "undefined")
	{
		xmlhttp = new XDomainRequest();
		xmlhttp.open("POST",this.s);
	}
	else
	{
		xmlhttp = new XMLHttpRequest();		
		xmlhttp.open("POST",this.s, true);
		xmlhttp.setRequestHeader("Content-type", 'application/json');
	}

	xmlhttp.onreadystatechange = function()
	{
		if(xmlhttp.readyState == 4)
		{
			if(callback)
	    	{
	    		callback(xmlhttp.status);
	    	}
		}
	}
		
	try
	{
		xmlhttp.send(JSON.stringify({events:events}));
	}catch(e)
	{
		console.log("caught:"+e);
	}
};
//-----------------------------------------------------------------------------
/**
	When the page has completed loading we create an instance 
	of the client and submit the special page load event.
 */
//-----------------------------------------------------------------------------
AC.prototype.load = function()
{
	var self = this;

	if(Math.random() < self.tprob)
	{
		if(typeof window.performance === 'object')
		{
			self.addEvent("PL",self.createPLData());
			
			//If called on pageload this will not populate performance data properly
			// as the first tick is taken into consideration, thus need to get it on second tick.
			setTimeout(function()
			{
				var data = window.performance.timing;
				data.url = window.location.pathname;
				
				self.addSendEvent("PT", data);
			},0);
		}
		else
		{
			self.addSendEvent("PL",self.createPLData());
		}
	}
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
return {AC:AC};}); //END AMD