Making SEO Friendly Ajax Easy

Posted on June 18th, 2011 in category: Tutorials

In many cases when you’re using AJAX to make your site more user friendly you will loose some really important bits such as search engine optimization, bookmarking and support for users without JavaScript or with JavaScript disabled. In this short tutorial I will show you how to use AJAX on your site and keep it all. And best of all, with the right plugins, it isn’t very hard at all.

We will use jQuery and two plugins to jQuery, these plugins are jQuery Hashchange and jQuery Metadata. jQuery Metadata allows you to add metadata inside your elements class attribute and jQuery Hashchange will trigger an event when the location hash is changed. More information about the plugins on can be found here:

Step 1. Add the necessary scripts.

Start by downloading and adding the necessary scripts to your project. Download or add jQuery from a CDN and then download the two plugins from the URLs above and just reference them in your page header. Like this:

<script src=""></script>
<script src="/Scripts/jquery.hashchange.min.js"></script>
<script src="/Scripts/jquery.metadata.js"></script>


The src path may vary depending on where you put your scripts.

Step 2. Create the scripts.

Add a script tag to your page and add the following two functions.

$('.ajaxLink').live('click', function (event) {
    window.location = '#' + $(this).metadata().url;

In the snippet above we bind a click event to all html elements containing the ajaxLink class. The event.preventDefault(); stops the browser from redirecting to the URL in the links href tag. (this).metadata().url will load the AJAX URL from the tags metadata using the metadata plugin. We will then change the hashtag to the value in the metadata “url” parameter.

$(window).hashchange(function () {
    $.get('/Ajax.aspx?url=' + location.hash.substring(1), function (data) {

This event will trigger when the browsers hashtag is changed. When it’s changed we call our Ajax.aspx which will load the desired URL for us and return the html. We will then load the html into our target div where it should be shown.

$(document).ready(function () {

We need to trigger the hashchange event when the page load, this will load the correct page if there’s a string after the hashtag when the page is loaded for the first time. This happens when someone for example sends you a link or you bookmark the page.

Step 3. Create the container page


The container page is the page that we will load our ajax into. The aspx is quite straight forward

    <li><a href="?url=/Controls/Control1.ascx" class="ajaxLink { url : '/Controls/Control1.ascx' }">Control 1</a></li>
    <li><a href="?url=/Controls/Control2.ascx" class="ajaxLink { url : '/Controls/Control2.ascx' }">Control 2</a></li>
    <li><a href="?url=/Controls/Control3.ascx" class="ajaxLink { url : '/Controls/Control3.ascx' }">Control 3</a></li>
<div id="divAjax">
    <asp:PlaceHolder ID="placeHolderAjax" runat="server">

First we add a couple of ajax enabled links. The href attribute will contain the fallback URL for search engines and users without JavaScript enabled. Then we have the class attribute which contains the class ajaxLink which tells our script to add the click event and then we have the ajax URL in our metadata.

The divAjax div is the target div where the loaded page will be displayed. The place holder inside is used for loading the fallback URL from code behind if a regular links is loaded.

Code Behind:

We need to add some code behind to our container page as well. The code behind will handle the fallback page loads.

protected void Page_Load(object sender, EventArgs e)

private void noAjaxFallback()
    string url = Request.QueryString["url"];
    if (!string.IsNullOrEmpty(url))

In the noAjaxFallback function we check if the “url” query string parameter is set and if it is set, we load the control into our placeholder.

Step 4. Create the Ajax loader

Create a new aspx page in your project’s root and name it Ajax.aspx. This page will be called by our ajax function in the container page. It will load the control using the “url” query string parameter and add it the the page.


<%@ Page Language="C#" EnableViewState="false" AutoEventWireup="true" CodeBehind="Ajax.aspx.cs" Inherits="SEOFriendlyAJAX.AjaxLoader" %>
<form id="form1" runat="server">
    <asp:PlaceHolder ID="placeHolderPage" runat="server" />

Since this page won’t be used as a standalone page we can remove the page header and stuff from the aspx. EnableViewState should also be disabled since this page won’t need it.

The place holder will contain the control loaded in code behind.

Code Behind:

protected void Page_Load(object sender, EventArgs e)
    string url = Request.QueryString["url"];
    if (!string.IsNullOrEmpty(url))

The code behind is very alike the code behind for the container page. We load our control using the “url” parameter and adds it to our page. The page will then be rendered and the html will be returned to our ajax JavaScript function.

Step 5. Add the User Controls

Well, all the coding is done. Last thing you need to do to make this work is to add the user controls. In this example we use three different user controls. To create them add a folder to your solution root and name it Controls. Create three controls inside the folder and name them “Control1.ascx”, “Control2.ascx” and “Control3.ascx”. Add some content to them and try it out.

Downloads and Examples


Try out the finished example here: Example.


Download the source from here: Download


  • linkwheel, July 24th, 2011

    Can I only say what relief to uncover someone who basically knows exactly what theyre discussing on the internet. You certainly know how to carry an issue so that you can light to make it important. More people need to read this and also understand this area of the story. I cannot believe youre not more popular because you definitely have the gift.

  • cut the rope, July 31st, 2011

    Making SEO Friendly Ajax Easy | World Wide What? Fantastic goods from you, man. I have understand your stuff previous to and you’re just extremely fantastic. I actually like what you have acquired here, certainly like what you’re stating and the way in which you say it. You make it enjoyable and you still take care of to keep it smart. I can not wait to read much more Making SEO Friendly Ajax Easy | World Wide What? again from you. Thanks For Share .

  • Ted, September 27th, 2011

    Very nice work, i look for a workaround like yours since some days. Only one problem for me: did you know where i can find the same with PHP ?

    best regards

  • lasse, September 27th, 2011

    Since my server is running on Linux the example is actually PHP based, I’ve added the PHP code to the zip file in the download link.

    Try download the source from the link above and you should find the PHP source there as well.

  • Bacalov, January 5th, 2012

    The script is pretty good. Main problem is that the permanent link whitch are very good for search engine are not covered.

  • lasse, January 5th, 2012

    Bacalov, I admit the links themself could be more SEO friendly. You could probably write a HTTP handler and get more friendly URLs.

    There is a few tutorials out there if you search for “ friendly url”, like this one:

  • Stacee Harney, January 7th, 2012

    Nice blog here! Additionally your site so much up fast! What web host are you the use of? Can I get your associate hyperlink for your host? I want my website loaded up as fast as yours lol

  • lasse, January 7th, 2012

    Thanks Stacee!

    My blog is actually hosted on a small home server in my apartment in Stockholm, the Internet connections in Sweden are quite fast.

    I’ve also put some effort in keeping the site as lightweight and fast as possible.There is a few guidelines out there if you search for it, such as this one from Yahoo.

  • David, June 5th, 2012

    Hum. With PHP it doesn’t seem to work properly. The browser back button works but bookmarks or urls don’t redirect to the proper content – only to the default page.

    Also: Any idea on how to show one of the content-pages in the container by default? At the moment it is just blank until you click on a link.

  • lasse, June 7th, 2012

    You’re right it doesn’t work properly in PHP, I’ll look into it and get back to you.

  • Ash, June 14th, 2012

    Yo. This looks great. Although when I navigate my browser to: the content isn’t loaded from Control1.htm… So I don’t understand how bookmarking would work. Also could you explain how this is SEO friendly when the url has a # in it? I’d love to use this as a basis for my website structure but I’m worried about those bits. Cheers! Ash

  • lasse, June 14th, 2012

    Hello Ash, there’s currently a bug in the PHP version and the example, it works in ASP.NET. I’ll fix this and upload a new version and example ASAP.

    I’ll get back to you when it’s ready.

  • Ash, June 15th, 2012

    Lasse, that’s incredibly kind of you. Thank you so much. Ash

  • James White, June 29th, 2012

    Hello, I was about to post the same as above but it seems you’re already on the case 🙂 I’d love to experiment with something like this in PHP too. You’ve explained this very well, great tut!

  • lasse, July 4th, 2012

    I’ve fixed the issue with bookmarking etc. now, sorry for the wait.

  • lasse, July 4th, 2012

    Thanks James, there’s a PHP sample in the source zip if you haven’t already found it.

  • Gaurav Manandhar, July 7th, 2013

    Does this decrease page speed?

  • lasse, July 8th, 2013

    Gurav, It’s not slower than using AJAX in any other way, you should also take a look at hashbang urls as it’s supported by many search engine crawlers. Also angular.js is a nice library to make it more structured like MVC.