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
http://www.glennjones.net/javascript/prototype_ajax.js
http://www.glennjones.net/javascript/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 version='1.0' encoding='UTF-8' standalone='yes'?> <rsp stat="ok"> <url>http://www.glennjones.net/Post/804/UnobtrusiveJavaScriptandAjax.htm</url> <id>link_100</id> <target>http://www.glennjones.net/</target> <label>Unobtrusive JavaScript and Ajax</label> </rsp>
Unsuccessful addClick call returns
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> <rsp stat="fail"> <err code="100" msg="Request not complete" /> </rsp>
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 version='1.0' encoding='UTF-8' standalone='yes'?> <rsp stat="ok"> <link percent="9" count="1" label="Unobtrusive JavaScript and Ajax">link_0</link> <link percent="18" count="2" label="High quality dynamically resized images with .net">link_18</link> <link percent="9" count="1" label="Home">Menu1</link> <link percent="9" count="1" label="Archive">Menu33</link> <link percent="36" count="4" label="Links">Menu34</link> <link percent="9" count="1" label="About">Menu37</link> <link percent="9" count="1" label="Technology">Menu40</link> </rsp>
Unsuccessful getClicks call returns
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> <rsp stat="fail"> <err code="100" msg="Request not complete" /> </rsp>
Example API link
http://www.glennjones.net/api/addClick.aspx?
id=menu37
&label=about
&url=http://www.glennjones.net/home/
&target=http://www.glennjones.net/about/
http://www.glennjones.net/api/getClicks.aspx?
url=http://www.glennjones.net/home/
Comments
1
René
Hi,
I am currently browsing the web, looking for a way to indeed record outgoing links, basically the links my page's visitors go to after leaving my domain. But it seems as if there are a lot of onclick solutions out there. But what do you do if visitors of your site are keyboard only computer users? Since I am blind, for example, I never click on anything, but do it all using my keyboard. I also often just enter new URLs in the "Open URL" box of my browser instead of looking for them and hitting enter on them on a page. Can one track those too somehow?
Best Regards,
René
Posted 15 January 2006 20:40
2
Paul
Hi Glenn,
I'm trying to know:
1) How to make the structure of the datbase SQL (using MySQL, PHP.)
Is it possible to have a copy of the datbase sql which you use ?
Or at least, the structure of the datbase ? That would help me…
Thank you
Paul
Posted 19 February 2006 14:17
3
Glenn
Peter you have found a floor in the code. The recordClick(e) function defines the IMG as the source element for the mousedown event on hyperlinked images.
I have changed the code so that it tests the tagName property of the event source. The label for an image is now taken from the alt attribute. Thanks for pointing out the issue, as I coded it against my blog which has no image based hyperlinks; I had not spotted this. test - http://www.glennjones.net/development/linktest.htm
Posted 07 January 2006 23:12
4
Dave
Having some trouble with using your code.
In Firefox, upon prssing 'Ctrl-X', I get the error:.
.
Error: linknode.getAttribute is not a function.
Source File: http://localhost:9595/linktracker.js.
Line: 144.
In my Javascript Console.
Any ideas?
Posted 16 February 2006 21:44
5
Glenn
@ M.Phillipe The Ajax Linker Tracker does not use third party GPL licensed code and I have not given it a GPL license. I am happy for anyone to use this code. I am sorry, but I do not understand the issue you are trying to put forward.
Posted 13 February 2006 19:53
6
Paul
hello Glenn,
I trying to make api the with PHP code..
Two questions, if you want.. well:
- How it is possible to identify the return of the base starting from the URL? URL = id?
- a diagram of the base, possible??
Thank you
Paul
Posted 16 February 2006 14:19
7
Chris
Very interesting article, as part of some usability analysis we are conducting I'm pondering using this technique to track a user's interaction with a form, so we can identify fields which they take time over and different behaviour patterns.
Posted 11 January 2006 19:55
8
Steven Woods
This is outstanding work, something extremely useful.
Posted 20 December 2005 20:48
9
eric scheid
Another benefit of tracking clicks this way is that it tracks which particular link is clicked, not just the URL which is the target of the link. (This tracking is done by recording the 'id' attribute, so of course you need distinct id's for each link.)
This blog isn't a good example of this benefit, but consider a newspaper site with multiple links on a page to the same stories: they often have a breaking news side bar, next story in section link, popular stories across all sections sidebar, recent stories in this category sidebar, and related stories links at the end of this story.
I've seen a couple of newspaper sites use slightly different URLs for each instance of the link ... and this annoys me because it breaks "visited link" styling.
Posted 31 December 2005 04:50
10
Glenn
Christian, thanks for the comment. I have had a very positive response to the Ajax Link Tracker. At the moment I am building a web stats widget using JSON and on-demand JavaScript. Once I have finished this demo and article I will publish the .net code and SQL Server script. This may take a while.
Posted 05 January 2006 10:32
11
Glenn
Dave Could you tell me which page you got this error on. This error on linknode.getAttribute would suggest a problem with the returned XML.
Posted 19 February 2006 15:49
12
Tom W. Most
@Peter: A proper HTTP redirect shouldn't have that problem (it's JavaScript and meta refresh redirects that do that).
Posted 03 January 2006 02:50
13
Tom W. Most
I too fail to see the point of a separate XMLHttp request. If you must use JavaScript to make sure that only real people are tracked, wouldn't it be simpler to rewrite the link with JavaScript (i.e., to go through a redirect)? Or, this technique could be combined with a static redirect solution, adding, a js_enabled=true note to the URL (tracking the difference between JavaScript enabled clicks and those without might be interesting).
Posted 31 December 2005 09:46
14
harry
I am a little confused about why AJAX was employed here. What is the benefit?
Link tracking has been done forever on the server-side using redirect URLs. So I don't see why that part of it needs to be, or is made better, by using ajax.
The display of the information here is what I think is the innovations, but I fail to see what benefit displaying it via ajax has. Since you have all of the data already at load time, you could just spit it out when the page displays and then show/hide the data with the ctrl-x key command. Why make Ajaz calls at all for this?
Posted 20 December 2005 19:01
15
Paul
Hello,
Initially, cheer!
beautiful demonstration of ajax!
It is possible to plan to record the click mouse on a page (for example, with the co-ordinates of the clicks on the page.).
In addition, does there exist in donwloding the code in asp for the server to record like you do ?
Thank you.
Paul
Posted 09 January 2006 19:40
16
Glenn
As I have clearly stated that the Ajax Link Tracker Code is free to use. I see no benefits in placing it under LPG. The Prototype.js license does not force the user to license their code in any way (much better license than LGP). As an individual I have the right to decide how and what I share with others. I hope other benefit from the information and code on this site, but I will not be bullied into how I license things. Not everyone thinks that LPG is a good thing.
Posted 14 February 2006 13:55
17
Nick
I have just download the scripts from your website. If it will works then it'll become very good application using AJAX.
Posted 05 June 2006 20:16
18
Glenn
Paul - I have place the SQL Scripts for the table and two stored procedures into a zip file. The table could not be simpler. It contains five columns, the id column which is a unique identifier and four columns to store the link click through data. These are sURL, sLabel, sLinkID and sTarget.
With the MapSurface version I have add a DateTime stamp which helps you pull the results on a date range.
Posted 19 February 2006 15:38
19
Paul
I am sorry Paul I don't understand your question. If you could explain a little more.
Posted 16 February 2006 14:40
20
daved
Great project! Look forward to a combination of Glenn's original scripts along with Pierre's PHP database idea to also track ASP pages!
Posted 14 March 2006 10:21
21
Ed
Great article Glenn.
I just wanted to throw this up there as I was having a bit of a problem with it.
The div's kept showing up at the bottom of the page so I needed to add this bit of code:
eltDiv.style.position = 'absolute';
This needs to be added in the "function displayClickThroughs( originalRequest )" right below "eltDiv.style.top = itop + "px";"
Thanks
Posted 06 March 2006 14:54
22
Paul
Hi Glenn,
Great.
i will look for.
Thanks
Paul
Posted 11 January 2006 10:20
23
Gilles
Hi Chris,
There is a code Ajax that did it.
Not very nice design, but working :
http://www.robrohan.com/projects/neuromancer/demo/snoop/
with neuromancer kit AJAX
record form, check box etc...
Gilles
Posted 12 January 2006 17:29
24
Lsv
Very impressive use of AJAX.
Posted 03 January 2006 12:26
25
rabby
Hello,
what do You think about my shorter and easier solution which tracks mouse clicks over links, too?
Please have a look at my short tutorial and tell me if there are known bugs within the js...
Thanks
Posted 28 June 2007 00:17
26
Envador
Hi Glenn,
GREAT work. The MapSurface dashboard looks awesome and bound for success. I wish you the best on that project.
If you don't object, I will to develop a backend with .aspx and .mdb as the database. I figure using an .mdb as the backend will keep this great utility portable. Everyone can work with .mdb files with standard installations, but might not necessarily have a Microsoft SQL Server ready to go.
I don't know what I would need to do with licensing, but it'll be free to download. As I have never licensed anything, is there a GPL/LPG etc license you would prefer it under?
Thanks again, and best of luck to you.
Posted 22 March 2006 08:14
27
Daniel F
To all those still scratching their heads, read eric's comment. It hits the nail squarely on the head. This is all about measuring what catches the users eyes. It's all well and good to say "our B sized rubber widgets are the most popular", but is that because there is a need for them, or because they have prominent eyeball space on your site? This kind of tracking is invaluable. Thanks Glenn!
Posted 05 January 2006 13:01
28
Ed
Whoops. Just realized another way to do this would be to read the code a little better and to apply the position:absolute into the .linklabel style in your CSS....sorry about that!
Posted 06 March 2006 15:00
29
Pierre
Hi Glenn and all
Excellent work. I really like it! I've written a PHP/MySQL backend. You can download it from:
http://ekstreme.com/phplabs/ajax-link-tracker.php . My code is released under the GPL.
Cheers,
Pierre
Posted 28 February 2006 21:01
30
Peter Bowyer
One problem I'm encountering - if the click is on a hyperlinked image then it's not recorded. Has anyone developed a solution for this?
Posted 07 January 2006 20:21
31
Phillipe
For two things:
1 - You are using the code Prototype.js, right?
2 - why ask ideas and of the assistance on code which won't be in LPG? not very just, not ??
Posted 14 February 2006 10:44
32
Yehuda
A very nice work Glenn and really useful for people who have the possibility to implement it in applications. It will surely help webmasters to get reliable information on user behaviour by excluding non-user clients like spiders or other bots. One point: after pressing Ctrl+x, the information about links will rest until new reload of the site (WIN2000, IE6) overlaying the links and making some of them unreadable.
Posted 20 March 2006 17:59
33
Jeff Croft
Not to speak for the author, but one reason I think this Ajax method is nice is that it pretty much ensures the clicks you are tracking are fro "real" visitors. The requirement of Javascript and the mousedown event ensures that they only people who can trigger the tracking mechanism are real live people using regular browser. This excludes things like bots, crawlers, and spam engines. It may exclude some non-Javascript or non-mouse-using individuals, too -- but overall, I think this would provide a more accurate view of what real people are really doing on your site than server logs and such.
As for the Ajax call to the database for display -- it's only a minor bandwidth savings, but doing this does make the filesize a bit smaller. In other words, you only bring in the statistic data for those who want it. Other people don't waste bandwidth on it. Like I said, it's a minor savings -- but a savings nonetheless.
Posted 21 December 2005 07:25
34
Envador
Hi Glenn,
I've put the backend for the Ajax Link Tracker online at http://www.envador.com/asp-ajax-LinkTracker/ -- It's written in .asp with an .mdb datafile so most people running a standard installation of Windows and IIS will be able to run it.
Thanks again for your great article!
Posted 26 March 2006 21:17
35
Glenn Jones
Pierre. It’s great someone has released PHP/MySQL backend. While working on MapSurface I have not had the time to extract the asp.net code into a form I could distribute. I am sure a PHP/MySQL version will be of greater use to the community.
The MapSurface version of link tracking has a one ot two important enhancements sometime in the future it would be good to do an “Ajax Link Tracker 2” post. At the moment I have my work cut out trying to keep up with the interest in MapSuface. I would love to here about of any future developments.
Posted 28 February 2006 23:50
36
Pierre
Glenn
Well your Link Tracker was too good to ignore. Since finishing it yesterday, it has already given me interesting results (not data, but actual usable information) on my website. I suggest everyone should try it :)
If you want to coordinate future work, please contact me via http://ekstreme.com/contact.php . I have a couple of ideas, and I'm sure you have many more.
Pierre
Posted 01 March 2006 18:59
37
Gilles
Hi,
Nice ajax code.
As it is a beeen said,
It will be nice , if we could get the aspx or asp code ....
Thank you
Gilles
Posted 10 January 2006 17:35
38
Daimon
Glenn,
This is an excellent application! Your interface work is incredible. I'm not sure if you are familiar with Visual Sciences (analytics tool) but your interface is as good. And I think highly of the front end folks at VS.
Keep up the good work. You have my support. If you need some web real estate let me know.
Posted 21 April 2006 01:58
39
Kim Debroye
I encountered two problems with the "Ajax Link Tracker 1.0 + PHP/MYSQL Backend" but I found a solution for both of them.
First of all, if you get a 'permission denied' error, you have to open 'linktracker.js' and find the lines with
apiurl = "http://ekstreme.com/tracker/
You'll find two urls. Replace them by your own url or relative path to the target file.
The second problem was a bit harder... I always got an 'object required' error. This time it had something to do with the PHP code.
To fix this problem, open 'getclick.php' and go to line 44.
Now replace
$ResultsA[$i]++;
with
if(array_key_exists($row['LinkID'], $ResultsA))
{
$ResultsA[$i]++;
}
else
{
$ResultsA[$i] = 1;
}
That should fix your problems.
Hope I could help some of you with this...
Posted 17 May 2006 22:03
40
Glenn
Harry, you are right, you can use server-side redirects for link tracking. I was interested in exploring the direct measurement of a user’s interaction with a page. As people start to build more complex Ajax driven interfaces like “del.icio.us Director” we need techniques to explore a user’s interaction beyond logs and server-side events. The idea I have put forward could be expanded to record all sorts of client side interactions. I also wanted to build something that was unobtrusive and did not add lots of additional code directly into the HTML or change the backend application. It is part of a number of experimental interfaces I am building.
Posted 21 December 2005 11:52
41
Peter Bowyer
Thanks Tom for clearing that up!
Posted 03 January 2006 16:49
42
Janusz
Glenn,
Excellent job!
One question>
Has the tracking any impact on the loading of the target page? When the visitor's click is captured then you need to make a server request to a tracking server, so the page which is unloading must wait before this request finishes, otherwise the click is not reported. Am I right or how do you make sure that the page does not unload quicker than the request to the tracking server?
Thanks,
Janusz
Posted 30 May 2006 17:27
43
Glenn
Chris thats a really interesting idea you could add focus or blur events to form items and record the time it takes for people if complete each element. The same technique would be really useful for forms that people do not complete. You could record each interaction with the form and find the most common point at which people give up. Well worth some investigation.
Posted 11 January 2006 21:40
44
Charlie
I've had something similar running on my blog for a few weeks, I track outgoing links in my sidebar in pretty much the same way - but without the fancy-shamncy ctrl-X stuff, I just have a view I run on the server to keep an eye on whats been clicked. I created it more to see if I could rather than becasue I really wanted to track my outbound links. My implementation uses Javascript in pretty much the same way as yours, but the backend is old skool asp using the CPAINT ajax toolkit. Nice work though, It's inspired me to take another look at mine, and prehaps do some better reporting.
Posted 22 December 2005 10:55
45
M.Phillipe
Hello,
I don't understand , how people can use GPL code, and working later on for them !!!
You can NOT make GPL code in your work !!!
Thank you.
Posted 12 February 2006 11:11
46
Paul
Hello Glenn,
What about the aspx 's code ?
cancel ? Just to know if we have to
work on it or not ...
Thank you
Paul
Posted 19 January 2006 19:23
47
Gareth
Excellent. A cleverly simple app. Will have to have a go at implementing with a PHP back end.
Posted 21 December 2005 23:10
48
Adam
This Link tracker is excellent apart from a bug I have found. Clicks are being logged with undefined when bold text in a link is clicked.
I.e. if you had this html..
<a>This text is <b>bold</b></a>
Clicking on any text not in the bold tag works fine, but when the word ‘bold’ is clicked an undefined link is logged. Any chance the javascript could be changed to accommodate this?
For me this is quite a big issue as I have implemented your link logging on our Google Search Appliance were most of the links have some bold text in them.
Posted 12 December 2007 13:34
49
Kim
I'm using the PHP/MySQL version of this project and I always get an error 'object required' on line 149, char3...
Could anyone tell me how I should fix this?
Posted 17 May 2006 21:05
50
Glenn
Chris there are ethical questions about using the detail tracking techniques we are talking about. Gareth Rushgrove wrote a nice article “Ajax and Privacy” about this issue. Like most technology it can be used for bad and good. It’s not the technology, but the use it’s put to.
I personal I think if your aim is to improve usability and not targeting individuals you do not need to directly flag all your tracking actions. That said, I do think that a clear and honest privacy policy statement is needed.
Posted 13 January 2006 08:30
51
Chris
Exactly what I was planning to use it on, and unlike many other ways of tracking how a user interacts with a form, AJAX allows you to see exactly at which field a user drops out.
Prototype almost complete! I'll hopefully post some examples once refined.
My only concern is that of privacy, what do you reckon to tracking a user in this way? Should we implement an anonymous version of this, or keep track of the user's session id in our AJAX calls so that we can reconstruct their entire journey through the form?
The data itself would be used to bring to attention problem areas of our forms, and other usability concerns so that we can ultimately improve user experience.
Posted 12 January 2006 15:30
52
Mike
So far I like it. It's working nicely. Is there a way to secure the tracking data though? Right now anyone can come to the web site and press Ctrl-X and see where my traffic is going. I know it's not likely that some random person would find this out but it's out there none-the-less.
Posted 26 June 2007 17:19
53
Christian Rémillard
Impressive work! That is exactly what i was looking for to track the user behavior on our Web site. Would it be possible to publish the server side scrips along with the js? Would be greately appreciate!
Posted 04 January 2006 18:37
54
Phillipe
Ok, sorry.
Within this framework,
I understand your point of view.
I present my excuse of this misunderstanding.
Phillipe
Posted 15 February 2006 13:08
55
Glenn
Paul and Gilles will publish the aspx code. I just want to finish the next post which I am working on at the moment.
Posted 10 January 2006 19:24
56
Peter Bowyer
Nice work!
Two advantages I see with this over a redirect, is that:
1. it provides the 'real' URL in the link, so people can see where it's pointing or copy the URL for an email etc without it looking weird.
2. Please correct me if I'm wrong, but a redirect would mess up the back button's behaviour (2 clicks back required to get from one page to the previous)?
As usual, if I'm missing something let me know!
Posted 01 January 2006 21:32
Comment Guidelines
All comments are moderated. Please keep comments relevant. Abusive, inappropriate and anonymous posts may be edited and/or removed.