seo friendly photo gallery using the history api

this past june, i spoke at smx advanced in seattle, washington on vanessa fox’s panel the crazy, complicated technical issues that completely sabotage the best seo efforts. this was my first big speaking gig and i was excited to discuss why web sites today can start mirroring functionality native applications offer on the web through various standard browser supported javascript apis.

Tom Conte on the History API at SMX Seattle 2013

history api + ajax

as an example of what this experience would look like, i touched upon a photo gallery relaunch a client was going through. in order for the relaunch to be successful, the following criteria had to be met:

  • user experience: native-like: fast, seamless, responsive
  • crawlability: unique urls for each gallery image
  • relevancy: a single title, caption, and image per url
  • accessibility: works in the most basic of browsers

most photo galleries today rely on a fragment identifier (#) to update the page’s content but that method isn’t the most reliable in regard to accessibility.

instead, the history api can update the browser’s history stack with an entirely different url based on any action. in addition, asynchronous technology can update the page’s content that syncs with the url change in order to provide a fast and seamless experience scrolling through each picture.

as a result of taking into consideration basic on-page seo in combination with the technologies discussed, the photo gallery is 100% accessible to both users and search engines.

function supports_history_api() {
	return !!(window.history && history.pushstate);
}
 
function swapphoto(href) {
	// save an instance of the xmlhttprequest object and open a connection to the html templates
        var req = new xmlhttprequest();
	req.open("get","http://www.cometton.com/demo/history-api/gallery/" + href.split("/").pop(),false);
	req.send(null);
 
        // check server response code and insert the new html
	if (req.status == 200) {
    	        document.getelementbyid("gallery").innerhtml = req.responsetext;
		document.getelementsbytagname('title')[0].innerhtml =   document.getelementbyid("title").innerhtml;
		var caption = document.getelementsbytagname("figcaption");
		var text = caption[0].firstchild;
		document.getelementbyid("description").setattribute("content",text.nodevalue);
 
		setuphistoryclicks();
 
		return true;
  }
 
  return false;
}
 
function getlink(link) {
        // update the url in the browser with the url each next/previous link points to
	link.onclick = function () { 
		if (swapphoto(link.href)) {
	    	     history.pushstate(null, null, link.href);
		return false;
		}
	}
}
 
function setuphistoryclicks() {
        // get the html for the next and previous buttons
	getlink(document.getelementbyid("photonext"));
	getlink(document.getelementbyid("photoprev"));
}
 
window.onload = function() {
	if (!supports_history_api()) { return; }
		setuphistoryclicks();
 
    // use the previous url in the history stack when pressing the "back" button
    window.addeventlistener("popstate", function() {
      swapphoto(location.pathname);
    }, false);
}

check out a working example using the javascript above, download a copy of my presentation, or view my presentation from the session below.

addendum

although our goals are the same, michael cottam (raven 03/29/13) writes how to build search-friendly photo galleries with a different approach on how to obtain them. in the end, the amount of resources available will dictate the direction you can go in.

Leave a Reply

Your email address will not be published. Required fields are marked *