Skip to the content...

Welcome to the David Walsh Blog. I'm a MooTools, Dojo, jQuery, CSS, and PHP Web Developer located in Madison, Wisconsin, United States. Please contact me if I can make your experience on my website better.

AJAX For Evil: Spyjax with jQuery

52 Responses »

Last year I wrote a popular post titled AJAX For Evil: Spyjax when I described a technique called "Spyjax":

Spyjax, as I know it, is taking information from the user’s computer for your own use — specifically their browsing habits. By using CSS and JavaScript, I can inject anchor links into the page and tell whether you’ve been to the link’s URL. How? Quite easy actually.

I've taken the time to demonstrate this technique using jQuery.

The CSS

a.checkme			{ color:#00ff00; }
a.checkme:visited	{ color:#ff0000; }

The most important part of the CSS is the difference in ":link" and ":visited" color; the method by which we can tell if a site has been visited is by its link color being the ":visited" color.

The jQuery JavaScript

//when the page is ready
$(document).ready(function() {
	//the list of domains to check and an array which will store hits
	var domains = ['davidwalsh.name','css-tricks.com','scriptandstyle.com','cnn.com','digg.com'];
	var visited = [];
	//for every domain...
	$.each(domains,function() {
		//inject a link into page
		var a = $('').attr({
			href: 'http://' + this,
			'class': 'checkme'
		}).appendTo(document.body);
		//check the color of the link
		if($(a).css('color') == '#ff0000' || $(a).css('color') == 'rgb(255, 0, 0)') { //either format of color
			$(a).addClass('highlight');
			visited.push(this);
		}
		//remove from the page -- no longer need the links
		a.remove();
	});
	if(visited.length) {
		//save via ajax!  shady!
		//display items on the page based on "hits"
	}
});

We start by injecting a bunch of hidden links into the page (unbeknownst to the user). For each link we've injected into the page, our jQuery JavaScript grabs the link color -- if the link's color matches the designated ":visited" link color we set via CSS, we've found a site the user's been to. Of course we can do anything we want with that information, including saving it via AJAX. Why? Well, if we know a user has been to Digg.com, maybe we show the Digg "share" icon instead of the Reddit icon.

The MooTools JavaScript

var domains = ['davidwalsh.name','css-tricks.com','scriptandstyle.com','cnn.com','digg.com'];
var visited = [];
domains.each(function(url) {
	var anchor = new Element('a', {
		href: 'http://' + url,
		'class': 'checkme',
		html: url
	}).inject(document.body);
	if(anchor.getStyle('color') == '#ff0000') {
		visited.push(url);
	}
	anchor.dispose();
});

The above code accomplishes the same task using MooTools as outlined in my previous Spyjax post.

What are your thoughts on Spyjax? Harmless? Major privacy violation? You tell me!

Discussion

  1. michael warkentin
    November 18, 2009 @ 9:08 am

    It seems like it should be possible to do something like this, shouldn’t it?

    Var visited_links = $$(‘a:visited’)

  2. anton
    November 18, 2009 @ 9:11 am

    This will only work if a user explicitly allows for his or her browser history to be recorded. I, for one, only store it for as long as the browser is opened. And since it can be controlled, it is not a security risk. But I like the idea, since not everyone erases browsing history, I can finally deny a user access to my site if he visits nasty social networks, mwahahaha :)

  3. anton
    November 18, 2009 @ 9:12 am

    @Michael Warkentin: That will only tell if user visited sites that you have links to on your page. If you want to check a specific site without linking to it, spyjax to the rescue!

  4. November 18, 2009 @ 9:21 am

    There are already sites out there using this technique. E.g. http://www.didyouwatchporn.com

    I’m amazed how easy this is…I think I’ll try to set up something similiar using Prototype.

  5. anton
    November 18, 2009 @ 9:23 am

    @David: as expected, it fails to detect the fact that I watch porn regularly: http://www.didyouwatchporn.com/imgs/splash_no.jpg

  6. November 18, 2009 @ 9:23 am

    @David: Hahahaaha. That’s awesome!

  7. November 18, 2009 @ 9:42 am

    yeah, i wrote a mini API for this a while back – http://fragged.org/dev/vanillaspy.php (vanilla js), i have a mootools one also.

    anyway, this has a test case for some targeted advertising under test advisement ‘isPokerPlayer’.

  8. thomas
    November 18, 2009 @ 10:30 am

    There’s a website dedicated to this privacy issue, and they also offer some solutions worth checking through: http://whattheinternetknowsaboutyou.com/docs/solutions.html

    I make great use of the history in my web browser, some sites aren’t “worthy” a bookmark, so I decided to use and install LinkStatus extension (https://addons.mozilla.org/en-US/firefox/addon/12312) for Firefox 3.5 – works like a charm imho.

  9. November 18, 2009 @ 2:13 pm

    I’ve always thought this use of css and javascript was pretty interesting. I figure that advertisers can’t use the information directly but a single-site, like a person hosting a wordpress blog, could have a plugin to show related posts based on the history of the visitor.

  10. November 18, 2009 @ 5:21 pm

    Did you get the idea here: http://whattheinternetknowsaboutyou.com ?
    With your examlpe, i see it can be used for useful things, so thx for sharing!

  11. November 18, 2009 @ 6:00 pm

    Very nice and pretty easy.
    Thx for the jQuery code!

  12. November 18, 2009 @ 6:29 pm

    I can’t get over how funny that porn thing is. Hilarious.

  13. November 18, 2009 @ 6:42 pm

    Hilarious it is…you can even create links to send to your friends and if they visit the site using your link, you get an email detailing what sites they visited :D

  14. November 19, 2009 @ 3:19 am

    I must say that spyjax which is used with j query is a wonderful combination for development. I like that.

  15. November 19, 2009 @ 4:46 am

    Wonderful idea. When used for good it has lots of potential!

  16. November 19, 2009 @ 7:39 am

    Haha, the list of websites I have been before clicking on the Advanced Test is outdated :))

    ” davidwalsh.name, php.net, yahoo.com, google.com, gmail.com, imdb.com, jquery.com, youtube.com, facebook.com”

    First, I think anyone of us are using these websites in a daily manner and second, is inaccurate, I didn’t visit at least 50% of these websites before coming on davidwalsh.

  17. marek stasikowski
    November 19, 2009 @ 11:04 am

    I was once writing something similar, but taking ranges of url’s in the same domain into account. This could be useful to eg. see what profiles has somebody been looking at at social websites. In the script, I declared the url as follows: “http://somesocialsite/users/%id”, and replaced the %id within a loop, to cover a full range of users. In the time being, I displayed a funny Youtube video on my site, so the victim wouldn’t leave before I’m finished scanning.

  18. November 19, 2009 @ 4:18 pm

    Would this be intrusion? I mean, anyone could use this technique and know what banks’ website you visit, who provides you your email account and so on…

    I’m actually surprised that this seems to be working and that there isn’t much “told” about it.

    In the other hand… I find it pretty cool! *evil grin* That can help in customizing the display of links and such nice little tweaks FOR the user (and not in order to profit FROM the user)…

  19. ben
    November 20, 2009 @ 12:15 am

    Wow!! This is very cool, but massive potential for misuse! Guess I’ll clear my history before I visit this site any more ;)

  20. November 20, 2009 @ 12:25 am

    @Ben: Actually, the plugins in Firefox LinkStatus (https://addons.mozilla.org/en-US/firefox/addon/12312) works fine, if you disable visited links’ CSS.

    Thanks for that plugin Thomas.

  21. ben
    November 20, 2009 @ 12:33 am

    @Nickolas Simard: Ah cool!

    Still, that doesn’t distinguish between good and evil sites.

    Do you think this could mean the end of the visited link style?!

    Once this gets into the wrong hands, the cons of keeping the visited link functionality will definitely outweight the pros.

  22. November 20, 2009 @ 5:26 am

    Yeah… I feel that…major privacy violation must be an issue for Spyjax

  23. November 24, 2009 @ 5:04 pm

    We made a service that is available for free to track your visitors’ histories. Check it out over at http://360voltage.com/historian/

  24. November 25, 2009 @ 5:55 am

    As promised I did the same using Prototype:
    http://davidbehler.de/projects/proto.spy

  25. daniel oliveira
    November 27, 2009 @ 7:30 am

    That porn stuff is great!!! ROFL

  26. November 28, 2009 @ 8:31 pm

    I like your idea about Digg. I don’t want to distract people and/or send them off to Digg if they are not already Digg users. OK, maybe I’m selfish but I have bills to pay.

  27. elq
    December 3, 2009 @ 1:03 pm

    What I find interesting is how inaccurate it is. Anybody know why? like I went to Facebook FROM the spyjax page, then came back to the spyjax page (FORward) from Facebook..still showing I’ve not been to Facebook. Even David’s prototype solution..it’ shows I’ve been to facebook but not that I was HERE! Any way to increase the accuracy a little?

  28. December 3, 2009 @ 1:14 pm

    Could be that you are not saving your browsing history? Because this “trick” relies upon you saving your history.

Be Heard!

Share your thoughts with fellow developers of all skill levels! I want to hear from you!

Name*:
Email*:
Website:  
Wrap your code with <code> tags, f00!