I was browsing through Jonathan Snook's blog earlier this morning when I noticed something at the bottom of his posts; a link for users to bookmark his posts on del.icio.us with a count of saves. I love stats and rather than going to sleep I decided to investigate this and roll it out on my blog.
At first I went straight to the del.icio.us API page but I quickly found out that the API is mainly user-centered and requires authentication to get data back. A dozen or so searches later I found del.icio.us JSON feeds. With their URL feed all you need to do is craft a request with the MD5 hash of a page URL and in return you get useful information such as top tags and number of saves. The del.icio.us JSON URL page has a brief code example that helps get the point across.
My plan was to incorporate this at the end of each post, so I would need a way to grab the URL of the current page and create an MD5 hash of it. First off, getting the URL. With PHP that's fairly easy with the server variables array (_SERVER). If you're using WordPress, there's also a template tag you can use to grab the permalink URL. For compatibility reasons I'll use the straight-up PHP method.
Getting the current page's URL and creating an MD5 hash of it:
<?php echo md5("http://"._SERVER["HTTP_HOST"]._SERVER["REQUEST_URI"]);?>
Okay so now we just need to feed that to del.icio.us and give it a callback function name we can use to process the data that del.icio.us returns.
<script type="text/javascript" src="http://badges.del.icio.us/feeds/json/url/data?hash=<?php echo md5("http://"._SERVER["HTTP_HOST"]._SERVER["REQUEST_URI"]);?>&callback=displayCount"></script>
I gave that a callback name of displayCount. The point of a callback is to call a function once the request has been made. So if we ask del.icio.us for some data about a particular URL it will return the data and then call our function, which will process that data in some intelligible way.
<script type="text/javascript">
function displayCount(data) {
var e = document.getElementById('url-count');
if(data[0]){
e.innerHTML = data[0].total_posts;
} else{
e.innerHTML = 0;
}
}
</script>
We're almost done. We found a way to retrieve the relevant data we need and process it. Now it just needs to be displayed. As in the JavaScript snippet above, the content will appear within an element with an id of url-count. Here is that implemented in its most basic form:
<span id="url-count">(loading)</span> people have saved this post on del.icio.us.
As recommended in a previous del.icio.us example, I display (loading) text until the JavaScript is able to process the number of bookmark saves. This adds a bit in the way of usability and lets the user know the status of the request. The JavaScript code then later adjusts the HTML value for that element id (url-count in this case). You could even get creative and put up a spinner.gif variant within there.
Putting it all together
When you're ready to implement this, place each of the three pieces in the following order within your code: HTML (the part with the url-count span/div), JavaScript displayCount() function, and finally the JavaScript polling del.icio.us.
How this is currently implemented on my site.
For finishing touches, just coax the designer inside of you to throw on some CSS styles and push it live.
Issues
Performance-wise, this will add another HTTP request which you want to try to avoid in general. Maybe later on I will explore methods of caching this data, or in the meantime you can explore WEDJE to get rid of the issue when the page load will halt until the JS is done doing its thing.
Update: Now I'm interested in implementing this server-side. Oh and I forgot about the "1 people have saved this" condition, I'll have to add on to this later.
Update 2: Here's a server-side method with PHP.
<pre>function getCount(){
hash = md5("http://"._SERVER["HTTP_HOST"]._SERVER["REQUEST_URI"]);
url = "http://badges.del.icio.us/feeds/json/url/data?hash=".hash;
ch = curl_init();
timeout = 5;
curl_setopt(ch, CURLOPT_URL, url);
curl_setopt(ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt(ch, CURLOPT_CONNECTTIMEOUT, timeout);
data = curl_exec(ch);
curl_close(ch);
preg_match("/\\total_posts\:([0-9]+)/",data,saves);
if(saves[1] == 0){
echo "No one has";
} elseif(saves[1] == 1){
echo "1 person has";
} else {
echo saves[1]." people have";
}
}</pre>