Showing Off bit.ly Clicks of Your Posts With jQuery

written by aext on July 29, 2010 in Javascript with 15 comments

While showing off number of retweets you get on a post is very common, showing number of clicks -that is relatively higher- can be a very interesting measure of how popular your post is. Since, sharing your short URL is not limited to Twitter but also it can be shared anywhere like Facebook, email and others..

bit.ly -the most common URL shortener- provides a simple RESTfull API to lookup short URL’s and their clicks count.. bit.ly has recently released version 3 which added simpler, more efficient methods to query multiple URL’s in one request that we are going to apply in this tutorial.

You can check the demo first here:

First, Place HTML link for each post

Next to each post, add anchor tag with class "bitly-clicks" that links to "http://twitter.com", so It would degrade gracefully to a Twitter link when Javascript is disabled.

Assuming that you like separation of concerns, we will store post URL in "rel" attribute and post title in “title” attribute!

<a class="bitly-clicks" href="http://twitter.com"
   rel="http://www.moretechtips.net/2010/07/quite-delicious-button-jquery-plugin.html"
   title="Quite Delicious Button - A jQuery Plugin">
   Retweet
</a>

Second, including jQuery

Include jQuery javascript file once in your page at <head> section or by the end of the page

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

* Note that this code was also tested to run with jQuery v1.3.2, you can just replace the jQuery URL with “http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js”

Finally, Include This script

Code is placed in a function that will be called when document is ready. Code sequence is divided into 6 steps and defined in internal functions.

  1. Looping links with class “bitly-clicks” to collect all URL’s in “urls” array then make AJAX call to bit.ly lookup method and pass the array as a parameter.
  2. When lookup call is loaded; we save the returned JSON results in “lookup” array that will contain the short URL’s.
  3. Collect short URL’s from “lookup” array then make AJAX call to bit.ly clicks method and pass these short URL’s as a parameter.
  4. When clicks call is loaded; we loop the returned JSON results to find global clicks count for each URL in the lookup array.
  5. For each anchor we loop the “lookup” array to get the corresponding short URL and clicks count and pass these info to “createAnchor” function. If one or more of the URL’s we got have never been shortened on bit.ly; then lookup call would not return their short URL. So, for each one of these URL’s we make AJAX call to bit.ly shorten method. And when call returns the short URL we pass it to “createAnchor”.
  6. Finally, we point anchor “href” to tweet-this link and add the clicks count after the anchor inside a link to bit.ly stats page of the short link.

* Note, that bit.ly API methods like lookup and clicks can handle up to 15 urls -which is good enough in most cases.

*Code starts by defining a bit.ly login and API key for this demo. You can replace with your credentials after registering on bit.ly.

* If you are looking for a complete solution to show clicks count of your posts; you may check my jQuery plugin “bit.ly Button“.

// When DOM is fully loaded
$(document).ready( getBitlyClicks);

function getBitlyClicks(){
   // your bit.ly login and API key
   var bitly_login = 'bitlydemo', bitly_key = 'R_bb2bf1337e8440debd525ec84242a9a5';
   // init urls array
   var urls = [];   
   // init lookup table that will hold short links and clicks count
   var lookup = [];
   // Get all links with class "bitly-clicks"
   var tags = $('a.bitly-clicks');

   // 1: Collect urls and lookup them
   var lookupCall = function() {
      tags.each(function(){
         // URL is saved in rel attribute of each A link
         var url = $(this).attr('rel');
         // Add URL to array if not there
         if( $.inArray(url, urls)==-1) urls[urls.length]= url;
      });

      // 2: Call bit.ly lookup once for all URLS
      $.ajax({url:'http://api.bit.ly/v3/lookup'
         ,data:{ url:urls, login:bitly_login, apiKey:bitly_key, format:'json' }
         ,dataType:'jsonp'
         ,traditional:true
         ,success:lookupCalled
      });
   };

   // 2: Lookup info is loaded
   var lookupCalled = function(json){
      // Error : exit
      if(json.status_code!=200) return;
      // save lookup JSON in lookup array
      lookup = json.data.lookup;
      // Lookup done: get clicks info
      clickCall();
   };

   // 3: Call bit.ly clicks for all urls
   var clickCall = function(){
      // collect short urls in this array
      var shortUrls = [];
      for(var i=0, c=lookup.length; i<c; i++) {
         // if short_url is returned only
         if(lookup[i].short_url) shortUrls[shortUrls.length] = lookup[i].short_url;
      };
      // Call bit.ly clicks
      $.ajax({url:'http://api.bit.ly/v3/clicks'
         ,data:{shortUrl:shortUrls, login:bitly_login, apiKey:bitly_key, format:'json'}
         ,dataType:'jsonp'
         ,traditional:true
         ,success:clickCalled
      });   
   };

   // 4: Clicks info is loaded
   var clickCalled = function(json){
      // Error : exit
      if(json.status_code!=200) return;

      // Get clicks results
      var clks = json.data.clicks;
      // Loop lookup array to set clicks count for each url
      for(var i=0, L=lookup.length; i<L; i++) {
         // if short_url is not returned skip
         if(!lookup[i].short_url) continue;
         (function() {
          for(var j=0, c=clks.length; j<c; j++) {
               // found clicks info for this short url
               if(lookup[i].short_url == clks[j].short_url) {
                  lookup[i].clicks = clks[j].global_clicks;
                  return;
               }
            }
       })();
      };

      //next step for each anchor
      tags.each(initAnchor);
   };

   // 5: Find clicks info for each anchor or call shorten one by one
   var initAnchor = function() {
      // this anchor
      var a = $(this);
      // this anchor url
      var url = a.attr('rel');
      // find lookup/clicks info for this url
      for (var i=0, c=lookup.length; i<c; i++) {
         if(lookup[i].url == url && lookup[i].short_url) {
            //found info for this existing url : create button
            createAnchor(a,lookup[i]);
            return;
         }
      };

      // not found! need to shorten it first by extra call to the API
      $.ajax({url:'http://api.bit.ly/v3/shorten'
         ,data:{longUrl:url, login:bitly_login, apiKey:bitly_key, format:'json'}
         ,dataType:'jsonp'
         ,success:function(json){
            // Error : exit
            if(json.status_code!=200) return;
            // call createAnchor and pass short_url in object as expected
            createAnchor(a, {short_url:json.data.url} );
         }
      });
   };

   // 6: Create anchor
   var createAnchor = function(a,info){
      if(!info.clicks>0) info.clicks=0;
      // tweet text made of post title and short url
      var tweet = a.attr('title') +' '+ info.short_url;
      // encode tweet text to be used as parameter in tweet-this link
      var tweet_url = 'http://twitter.com/?status='+ encodeURIComponent(tweet);

      // add number of clicks after the anchor and links to bit.ly stats page
      a.after(' <a class="bitly-clicks-count" href="'+info.short_url+'+">('+ info.clicks +' clicks)</a>');
      // Set anchor href to the tweet-this link
      a.attr('href',tweet_url);
   };

   // Call step #1 to start the sequence
   lookupCall();
}

Remember to share this tutorial if you like it!