electronic brain surgery since 2001

Tagging splitbrain

You may have noticed the new block in the footer/sidebar called “Tagged at del.icio.us”. This post is about how it works.

The popular bookmarking service del.icio.us released a new feature called Tagometer. It's a JavaScript widget to display the tags used at del.icio.us to describe a bookmark. The cool thing about it is that it uses a special URL to pull the needed data as a JSON feed. This makes it possible to use the data without the need for JavaScript. Luckily my site is powered by DokuWiki, and all needed things for doing HTTP requests and a JSON to PHP parser are already available.

Before I explain how I integrated it into my template, I want to tell my reasons for not using the JavaScript widget: JavaScript is not executed by search engine spiders, so eg. Google wouldn't see those highly relevant keywords on my pages. The same is true for other automated services which may look for the rel="tag" microformat. So the advantage of parsing the JSON feed on server side is to make the data more visible and more flexible to use. In theory I could even use the tags in the meta keywords, though I'm not doing it, yet.

So how does it work? The whole magic happens in two functions. The first one will fetch the data and prints a tag cloud. It also takes care of caching to avoid refetching the data on each request. The cache time is hardcoded to two hours currently. It looks like this:

function _print_delicious_tags(){
    global $ID;
    $url   = wl($ID,'',true);
    # check cache
    $cache = getCacheName($url,'.delicious');
    if(@filemtime($cache) > (time()-(60*60*2))){
        echo io_readfile($cache,false);
    # fetch JSON feed
    $md5   = md5($url);
    $feed = 'http://badges.del.icio.us/feeds/json/url/data?hash='.$md5;
    $HTTP = new DokuHTTPClient();
    $HTTP->timeout = 10;
    $data = $HTTP->get($feed);
    if(!$data) return;
    # parse JSON
    $data = $JSON->decode($data);
    # output HTML
    echo '<b>T</b>agged at del.icio.us:<br />';
    if(COUNT($data) == 0){
        $url   = rawurlencode($url);
        $title = rawurlencode(p_get_first_heading($ID));
        echo 'No tags, yet. Why don\'t you <a href="http://del.icio.us/post/?url=',
             $url,'&amp;title=',$title,'">bookmark it</a>?';
        # build cloud
        $tags = $data[0]['top_tags'];
        foreach($tags as $tag => $sz){
            echo '<a href="http://del.icio.us/tag/'.rawurlencode($tag).'" ',
                 'rel="tag" class="cld'.$sz.'">'.hsc($tag).'</a> ';
        echo '<br /><b>B</b>ookmarks: ',
             '<a href="http://del.icio.us/url/',$md5,'">',
             ((int) $data[0]['total_posts']),'</a>';
    # store cache
    $html = ob_get_contents();
        echo $html;

As you can see most code is used for pretty printing and checking the cache. The magic is done through the HTTPClient and the JSON class already included in DokuWiki.

To build a weighted tag cloud, the second function is needed. I wrote about this function in my wiki a while ago, here is the code:

function _cloud_weight(&$tags,$min,$max,$levels){
    // calculate tresholds
    $tresholds = array();
    for($i=0; $i<=$levels; $i++){
        $tresholds[$i] = pow($max - $min + 1, $i/$levels) + $min;
    // assign weights
    foreach($tags as $tag => $cnt){
        foreach($tresholds as $tresh => $val){
            if($cnt <= $val){
                $tags[$tag] = $tresh;
            $tags[$tag] = $levels;

So all that's missing is you bookmarking my pages at del.icio.us to tag them :-)

tags, delicious, php, json, api
Similar posts: