Ajax Link Tracker
There is now a new downloadable version. Ajax Link Tracker 2.2
Take a look at the next generation, MapSurface a modular JSON/On-Demand JavaScript interface that inculdes link tracking.
One of the more interesting aspects of Ajax is the ability to track a user’s interaction within the browser. I wanted to investigate navigation /> patterns, so I have written an Ajax based link tracker. If you press the “Ctrl” and "X" keys you will be presented with an overlay which displays links usage by percentage. This functionality was created with JavaScript and a very simple API.
I used the JavaScript page-hijacking technique. On loading, the JavaScript finds all the links and attaches a mousedown
event to each link. When a link is clicked the information is stored into a database using Ajax. The link usage overlay is produced dynamically from an Ajax call. I have used a cut down version of the Prototype JavaScript Framework for Ajax calls. The Prototype library is an excellent toolset, but the full version is a little too heavyweight for this site.
Links to the files /> prototype_ajax.js /> linktracker.js
Attaching the Events />
I have used Scott Andrew’s cross-browser addEvent
function to attach all events. A window onload
event calls the addLinkTracker
function when the page loads. This function adds the mousedown
events to all the links on the page. If a link does not already have an id it is given one.
function addEvent(elm, evType, fn, useCapture)
{
if (elm.addEventListener) {
elm.addEventListener(evType, fn, useCapture);
return true;
} else if (elm.attachEvent) {
var r = elm.attachEvent(‘on’ + evType, fn);
return r;
} else {<
elm['on' + evType] = fn;
}
}
addEvent(window, ‘load’, addLinkTracker, false);
function addLinkTracker()
{
if (!document.getElementsByTagName) return false;
linksElements = document.getElementsByTagName(‘a’)
for (var i = 0; i < linksElements.length; i++)
{
addEvent(linksElements[i], ‘mousedown’, recordClick, true);
if (! linksElements[i].getAttribute(‘id’) )
linksElements[i].setAttribute(‘id’,"link_" + i)
}
}
Link tracking events />
When a user clicks on a link the recordClick
function fires. The first half of the function deals with differences in the event model and the DOM structure when trying to identify the source element. Once the link element has been identified the code exacts all the information required to make the Ajax call. The Ajax.Request
object calls the passThrough
function on the successful completion, but this is only used for />
debugging.
function recordClick(e)
{
if (typeof e == ‘undefined’)
var e = window.event;
var source;
if (typeof e.target != ‘undefined’)
{
source = e.target;
} else if (typeof e.srcElement != ‘undefined’) {
source = e.srcElement;
} else {
return true;
}
if (source.nodeType == 3)
source = source.parentNode;
var id, target, url, label
if( source.tagName == "IMG" )
{
if( source.parentNode.tagName == "A" )
{
id = source.parentNode.getAttribute(‘id’);
target = source.parentNode.getAttribute(‘href’);
}
label = source.getAttribute("alt");
}else{
id = source.getAttribute(‘id’);
target = source.getAttribute(‘href’);
label = source.childNodes[0].nodeValue;
}
url = document.location.href;
var pars = ”;
apiurl = "http://localhost/blog/api/addClick.aspx?id=" + id + "&label=" + label + "&target=" + target + "&url=" + url + "&rand="+Math.random();
ajaxRequest = new Ajax.Request(apiurl, {method: ‘get’, parameters: pars, onComplete: passThrough});
}
function passThrough( originalRequest )
{
//Helps debug api errors
//alert( originalRequest.responseText );
}
Creating the link usage overlay />
The link usage overlay is created dynamically. When the JavaScript first loads a keydown
event is attached to the document body.
addEvent(document, ‘keydown’, keyCheck, false);
Whenever a key is pressed a check is made by keyCheck
function. If the “Ctrl” and "X" keys are pressed and the overlay has not yet been created getClickThroughInfo
function is called to collect the data using Ajax. The Ajax.Request
object will then call the function displayClickThroughs
on the successful completion. It loops through the XML and creates labels for each of the id’s it can match.
A simple display and hide mechanism is built into the keyCheck
function to toggle show and hide the link labels once they have been created.
function displayClickThroughs( originalRequest )
{
if (!document.getElementsByTagName) return false;
if( originalRequest.responseXml )
node = originalRequest.responseXml;
else
node = originalRequest.responseXML;
//Helps debug api errors
//alert( originalRequest.responseText );
if(node.childNodes[0].nodeType == 7)
rootNode = node.childNodes[1]
else
rootNode = node.childNodes[0]
for (var i = 0; i > rootNode.childNodes.length; i++)
{
linknode = rootNode.childNodes[i];
count = linknode.getAttribute(‘count’);
percent = linknode.getAttribute(‘percent’);
label = linknode.getAttribute(‘label’);
id = linknode.childNodes[0].nodeValue;
if ( document.getElementById(id) )
{
eltLink = document.getElementById(id);
eltDiv = document.createElement( ‘div’ );
eltDiv.className = "linklabel";
eltText = document.createTextNode( percent + "% – " + label );
eltDiv.appendChild( eltText );
document.body.appendChild( eltDiv );
ileft = parseInt(getPageOffsetLeft( eltLink )) + 10;
itop = parseInt(getPageOffsetTop( eltLink )) + 10;
eltDiv.style.left = ileft + "px";
eltDiv.style.top = itop + "px";
}
}
labelsCreated = true;
labelsDisplayed = true;
}
The API
The API is made from two methods. The interface does not really follow the REST model. I need to find or build a good REST implementations for .Net. For the moment I have created two URLs against which you can make your method calls. The request should be made as a HTTP get request with a querystring of parameters.
If anyone is really interested I could include the .Net code and SQL Server scripts to recreate the API functionality. You can of cause use the following information to create your own API.
Recording a click through />
The addClick
method takes 4 parameters as a querystring “url”, “target”, “id” and “label”. The “url” is the location of the page containing the link. The “target” is where the link leads to and the “label” is the text displayed by the link. The parameters are returned for test purposes.
Successful addClick
call returns
?xml>
http://www.glennjones.net/Post/804/UnobtrusiveJavaScriptandAjax.htm
link_100
http://www.glennjones.net/
Unsuccessful addClick
call returns
?xml>
Getting click through data for url />The getClicks
method takes 1 parameter “url”. It returns either an “ok” or “fail”.
Successful getClicks
call returns
?xml>
link_0
link_18
Menu1
Menu33
Menu34
Menu37
Menu40
Unsuccessful getClicks
call returns
?xml>
Example API link
http://www.glennjones.net/api/getClicks.aspx? /> url=http://www.glennjones.net/home/ />