jQuery: Making AJAX Applications Crawlable

If you want a fast and responsive web app, then you are definitely using jQuery (or any other javascript libray) and ajax calls to keep the size of the page small and transfer only the data the user requested.

The problem that came along with this approach is that search engines can’t interact with your page the way a user does, and so, there is no way for a search engine to make the ajax call and get the content back from the server. Spiders just aren’t browsers and users! (Learn more about it here)

Google quickly suggested a solution by using the fragment part of the url and map it (“pretty” URL) to an “ugly” one.
e.g.
georgekosmidis.com?param1=value1#!fragment-part-with-instructions
maps to
georgekosmidis.com/?param1=value1&_escaped_fragment_=fragment-part-with-instructions
and vice versa

So your site uses commands after #! for client side code and google visits your site replacing #! with _escaped_fragment_, and expects to see content without any ajax calls. What that usually means is more work for the developer… You can find some tips on how to make your life easier with html snapshots here.

Since there is no way to avoid the extra work for the mapping of pretty and ungly URLs I will concentrate on the client-side work that needs to be done:

There are two plugins that can help

  • HashChange Event by Ben Alman
  • HashHandle by me

* Since Ben stopped(?) supporting HashChange, as from jQuery version 1.9 HashChange stopped working (jQuery removed $.browser support). I forked Ben’s last version and corrected this, so you can find both plugins here: https://github.com/georgekosmidis

The usage is quite simple:

<html>
 <head>
  <!-- jQuery and plugins -->
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
  <script src="jquery.hashhandle.min.js"></script>
  <script src="jquery.hashchange.min.js"></script>
  <!-- Convert ugly to pretty URL. Engines wan't follow, this is just in case a user visits with _escaped_fragment_ -->
  <script>$.fn.HashHandle('convertURL');</script>
  <script>
          $(document).ready(function () {
           //Handle all tags with HashHandle class
           // Binds an onclick event and reads href to add it to hash fragment
           $(".HashHandle").HashHandle('add');
          });
  </script>
  </head>
  <body>
   <!-- test urls -->
   <a href='#!filter=somefilter' class='HashHandle'>Change filtering</a>
   <a href='#!sort=somesorting' class='HashHandle'>Change sorting</a>
   <a href='#!'>Reset</a>
   <div id='table-that-needs-filtering-and-sorting'>...</div>

   <!-- script to handle hashchange event -->
   <script>
    //hash change event
    $(window).hashchange(function (e) {
     //get filter from http://..../?whatever#!filter=somefilter&sort=somesorting
     var filter = $.fn.HashHandle("hash").filter;

     //get filter from http://..../?whatever#!filter=somefilter&sort=somesorting
     var sort= $.fn.HashHandle("hash").sort;

     if(filter != undefined || sort != undefined){
      //retrieve data from server and show them
      $.get("/GET_DATA_FOR_DIV?filter=" + filter + "&sort="+sort, function (data) {
       $("#table-that-needs-filtering-and-sorting").html(data);
      });
     }
    });
    //trigger hash change on load
    $(window).hashchange();
   </script>
  </body>
</html>

These are all methods available:

convertURL : Mapping simulation, from _escaped_fragment_ format to #! format, actually redirects
             e.g.
             &lt;head>...<script>$.fn.HashHandle('convertURL');</script>...</head>
             Redirects from http://.../?param1=value1&_escaped_fragment_=k1=v1&k2=v2 to http://.../?param1=value1#!k1=v1&k2=v2
 hash      : Returns a collection of fragment keys in url fragment
             e.g.
             For url http://.../?param1=value1#!k1=v1&k2=v2 get p1 with
             var k1 =  $.fn.HashHandle("hash").k1;
 add(k,v)  : Adds key/value to fragment, or changes existing key
             e.g.
             $.fn.HashHandle("add", "k1", "v1") will change url to
             http://...#!k1=v1
 add       : Binds an onlick event to the object and adds key/value fragment based on href attribute
             e.g.
             <a href='#!k2=v2'>...</a>
             $("a").HashHandle("add");
             Will convert url http://...#!k1=v1 to http://...#!k1=v1&k2=v2
 remove    : Removes a key
             e.g.
             $.fn.HashHandle("remove", "k1");
             Will convert url http://...#!k1=v1 to http://...
 clear     : Clears fragment
             e.g.
             $.fn.HashHandle("clear");
             Will convert url http://...#!k1=v1&k2=v2 to http://...

You can find both plugins (jquery-hashhandle, jquery-hashchange) here: https://github.com/georgekosmidis/

Advertisements

2 thoughts on “jQuery: Making AJAX Applications Crawlable

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s