Deep Linking in Flash and AJAX Applications

A couple of weeks ago, Jon Udell made a post entitled "Web-friendly rich Internet apps, continued" in which he asks the questions "can rich Internet apps be web-friendly?" He mentions MXNA, and specifically, the experimental MXNA Category Click Feed Report which combines Flash and JavaScript/AJAX techniques to make the page more dynamic, interactive, and responsive.

But Jon wanted more out of the experience. From his post:

If I link to the aggregator, it defaults to the Macromedia category and to Kevin Lynch’s blog. You can navigate to the Technology category, and thence to my blog, but there are no URLs exposed for these, so I can’t link from here to there. In this case it’s not a Flash issue, it’s a DHTML issue. But the principle is exactly the same. Toolkits and frameworks for building rich Internet apps ought to make support for deep linking a no-brainer for developers. It should be the rule, not the exception.

That sounded like a good idea to us, so we did it. Although the Category Click Feed Report initially defaults to one weblog (currently set to mine), you can navigate to other feeds, and bookmark or link directly to that feed’s report. For example, check out John Udell’s report. Or Kevin’s. Or Mike Chambers’. Notice how the state of both the Flash and the JavaScript portion of the application are captured.

The Category Click Feed Report uses two techniques for deep linking. The first technique is based on Kevin’s RIA deep linking example in which he dynamically appends anchor names to the URL in the location bar which describe the sate of the application. Click on some different feeds in the right-hand column, and you’ll notice the URL getting updated with information the application needs to recreate the current state. This technique works well, primarily because it allows users to copy the URL right out of the location bar in order to preserve the state of the application, which is what we are generally used to doing. However, there are two disadvantages:

  1. Anchors don’t work like query string parameters. If you change the IDs in the URL in the location bar and press return, the app won’t update which means if you are already looking at one person’s report, and you try to paste in the URL for someone else’s report, nothing will happen. The reason is that the browser is simply trying to jump to a named anchor on the page, which it does not find, so it does nothing. There may be a way to capture this event in JavaScript so you can tell your application to react accordingly, however, which is something I need to look into.
  2. There are cross-browser issues. The dynamic anchor technique works pretty well across all browsers except Safari. When you have multiple tabs open in Safari, a little loading animation will play on the right side of the tab when a page is loading. Safari starts playing that animation in response to the href property of the location JavaScript object being changed, even if you are just appending anchor names and not loading anything from the server (which I would consider a bug). The result is that although the page is being updated without reloading the entire document, it looks to the user like the entire page is being refreshed. What’s worse is that the code in Safari that stops that animation from playing seems to run in response to a page fully loading, which in this case never happens, so the animation never stops. That makes the page feel like it’s "hung" or broken in some way which I personally find pretty annoying.

The second technique I used for deep linking has to do with the "Link to this report" link below the chart. This uses a technique similar to what Google Maps uses to let you link to a specific map state (they may have opted for this approach due to the issues mentioned above). Notice how the URL in the location bar never changes as you use Google Maps since the entire page is not refreshing, which means that it doesn’t give you any query string parameters to capture the state of the app. Instead, the "Link to this page" link in the upper right-hand corner changes, capturing the information needed to redraw the map in its current state.

Mouse over the "Link to this report" link below the chart in the Category Click Feed Report and note the query string parameters. Then click on another feed, mouse over the link again, and you will see that it seamlessly updated with the information necessary to link directly to that report. This technique uses query string parameters rather than anchors and is therefore technically more reliable, however the disadvantage is that it requires users to learn a new paradigm for capturing the state of an application. Rather than just copying the URL out of the location bar and sending it to a friend, thunately, it is not possible to combine these techniques by dynamically updating query string parameters in the location bar because the only portion of a URL in the browser’s location bar that you can dynamically change using JavaScript without causing the entire page to refresh is the anchor portion.

Ultimately, I think the dynamic link technique is the better way to go even though it is currently less intuitive to users. My pediction is that this will change (partially thanks to Google), and users will soon know to look for special links to use to capture the state of an application rather than relying on the location bar. Using dynamic links is actually safer since you can be sure that the links you are sending around or posting on your site for the world to click on don’t contain session informtion that can either compromise your account on the site you are linking to, or cause the link to be invalid after the session has timed out.

I’d like to get some feedback on how I’ve incorporated deep linking into the Category Click Feed Report, and eventually, I’ll release all the code along with a tutorial. In the meantime, check out Kevin’s tutorial on the dynamic anchor technique, and feel free to view (and steal) my ource code. It is all easily accessible and readable.

5 Responses to Deep Linking in Flash and AJAX Applications

  1. I use this same technique in my applications. It also integrates we’ll with the technique I use for enabling the back button.One thing we’ve also implemented is a bookmark feature that works in IE on windows. IE has a method that you can pass a name and a url and it promtes the user to add the bookmark. Its another way to hide the “deep link” address.

  2. Danilo says:

    A potential work around for the first disadvantage would be to use setInterval (or recursive setTimeout) to call a function that continually looks for changes to the URL compared to the last known state URL. If it is now different, then make the necessary state changes in the application.

  3. pj says:

    Yes, I’ve been concerned about this. How can Google spider a rich app? Once you get away from hyperlinks, your analytics software is now useless.

  4. Adam Solove says:

    I have implemented deep linking in my ajax wiki application using anchors. Onload, javascript checks location.href for an anchor and then calls the existing ajax methods to add and remove the appropriate content.

  5. tcs says:

    I just made a fairly large flash site and wanted to be able to send people to any section within it.So i used php to catch appended variables and dynamically write to the FlashVars tag when it renders out the page. The swf then catches the Vars from the tag and a custom function redirects the content mc to the appropriate navigation.Of course there are a couple of issue here too. The address will stay the same in the address bar because the html isnt being reloaded, so if a user moves around, they cant then save a new link. But at least it will allow for linking to certain content from other sites etc.Another option is to have a duplicate html file for every section you want to have a traditional link to, with the FlashVars in each holding the redirect variables. Then the html will reload and provide a new link, and the swf will be cached so it will just restart without downloading again, and catch the variables.