Check out "Do you speak JavaScript?" - my latest video course on advanced JavaScript.
Language APIs, Popular Concepts, Design Patterns, Advanced Techniques In the Browser

Deep linking in flash with AS3

Many people will say that Flash is not SEO friendly. Actually that's not 100% true. Flash is just a tool that shows your data. Exactly the same as the HTML. In this article I'll show you how to use ActionScript3 and JavaScript together to make your flash sites SEO friendly and provide a different URL for each of your pages.

First of all, it is a good practice to make alternative HTML pages of your site. It's true that the spiders can't read the dynamic data in flash, but you can still point them to the correct place. Just add simple tag links into the main page of the site. Place them in the div that will be filled with the flash embed tags. Then you will be sure that Google or Yahoo will reach your information.A finished working version of the example could be found here. As you can see we have a simple flash site with main menu and content area. The buttons on the top change the site's content with a specific page. That's pretty simple, but it's good enough for our test. The most interesting part is that while changing the pages in flash we are also changing the URL of our browser. For example the home page is located at "#/home", the portfolio page at "#/portfolio" and so on. If you copy some of the generated urls (for example http://krasimirtsonev.com/files/deeplinking/#/portfolio) and paste it in a new empty tab/window you will see that the flash is pointed to the exact page, i.e. the portfolio page. The other interesting thing is that the "back" and "forward" buttons of our browser are also working. In other words you can simply change the site's page from there. And at the end our small flash site has it's own pages with different urls and it is really similar to a html based site. So, how to do deep linking in flash? We can split the process in two parts. The Javascript part will be responsible for all the events that occur in the browser. The ActionScript part will be responsible for the events in the flash. First of all let's see our html page:

<html><head>	<title>Deep linking in Flash with AS3</title></head><body>	<div id="animation"></div>	<script type="text/javascript">var dl = new DeepLinkingClass();
    var swf = new FlashObject("./swf/flash.swf", "animationSwf", "500", "350", "9", "#999999");
    window.onload = function () {
      swf.addVariable("page", dl.getPath());
      swf.write("animation");
      dl.flashObj = document.getElementById("animationSwf");
    }
    
    function updateAddress(address) {
      dl.setPath(address);
    }	</script></body></html>

We used FlashObject to embed the flash into the HTML. As you can see we have to provide the div tag, content of which will be replaced with the / tag.

<div id="animation"></div>

Then we created an object of the class DeepLinkingClass (I'll explain the source of it later). That class is responsible for the browser's url, getting or setting.

var dl = new DeepLinkingClass();

After that we just created the FlashObject object and forced it to display the flash. Before calling of the "write" method we passed one very important variable to our swf. It's the current page's address, which is provided by our DeepLinkingClass object.

swf.addVariable("page", dl.getPath());

After the filling of the html we had to set something important too. That's the "flashObj" property. We will use this property to access the flash dynamically from our javascript code.

dl.flashObj = document.getElementById("animationSwf");

And at the end you can see a function that will be called from the ActionScript and will update the browser's url.

function updateAddress(address) {	dl.setPath(address);}

Here is the code of the DeepLinkingClass:

DeepLinkingClass = {};
    DeepLinkingClass = function () {
      deepLinkingObj = this;
      this.location = location;
      this.hash = location.search || location.hash;
      this.loop();
    }
    DeepLinkingClass.prototype = {
      getPath: function () {
        if (this.hash.indexOf("#") < 0) {
          return "";
        } else {
          if (this.hash.charAt(this.hash.length - 1) == "/") {
            return this.hash.slice(2, this.hash.length - 1);
          } else {
            return this.hash.slice(2);
          }
        }
      },
      setPath: function (path) {
        if (this.location) {
          this.hash = path;
          top.location = path;
        }
      },
      loop: function () {
        if (this.hash != (top.location.search || top.location.hash) && this.flashObj) {
          this.hash = (top.location.search || top.location.hash);
          this.flashObj.changePage(this.getPath());
        }
        setTimeout("loop()", 200);
      }
    }
    var deepLinkingObj;
    
    function loop() {
      if (deepLinkingObj) {
        deepLinkingObj.loop();
      }
    }

The class has three methods:getPath() - gets the current browser's address. Not the whole url, but the part that we need.setPath() - changes the browser's address. We have to pass values like "#/home" or "#/aboutus"loop() - this method is called repeatedly. We used it to check if the address is changed and if is then we updated the flash's content. Without this function the "back" and "forward" buttons of the browser will not work.That was the Javascript part. Here is the code from the flash:

package lib.document {
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.external.ExternalInterface;
    public class App extends MovieClip {
      // movie clip that contains all the pages	
      private
      var _pages: MovieClip;
      // movie clip that contains the menu buttons	
      private
      var _menu: MovieClip;
      // current page	
      private
      var _currentPage: String;
  
      function App() {
        ExternalInterface.addCallback("changePage", changePage);
        // getting initial page	
        _currentPage = loaderInfo.parameters.page || "home";
        // constructing the pages	
        _pages = new Pages();
        _pages.gotoAndStop(1);
        _pages.y = 70;
        addChild(_pages);
        // constructing the menu		
        _menu = new Menu();
        _menu.y = _menu.x = 22;
        _menu.b1.addEventListener(MouseEvent.CLICK, onMenuButton1Clicked);
        _menu.b2.addEventListener(MouseEvent.CLICK, onMenuButton2Clicked);
        _menu.b3.addEventListener(MouseEvent.CLICK, onMenuButton3Clicked);
        _menu.b4.addEventListener(MouseEvent.CLICK, onMenuButton4Clicked);
        addChild(_menu);
        showPage(_currentPage);
      }
      // change the current page	
      function showPage(address: String): void {
        _pages.gotoAndStop(address);
        ExternalInterface.call("updateAddress", "#/" + address);
      }
      // update the page (called from the javascript)
      public
      function changePage(address: String): void {
        showPage(address);
      }
      // menu events	
      private
      function onMenuButton1Clicked(e: Event): void {
        showPage("home");
      }
      private
      function onMenuButton2Clicked(e: Event): void {
        showPage("aboutus");
      }
      private
      function onMenuButton3Clicked(e: Event): void {
        showPage("portfolio");
      }
      private
      function onMenuButton4Clicked(e: Event): void {
        showPage("contacts");
      }
    }
  }

The initial state of the flash is set here:

_currentPage = loaderInfo.parameters.page || "home";

If there is no page passed then the home page is displayed. And we simply used ExternalInterface to call the updateAddress function every time when we clicked on some of the buttons. Check out the example here or download the source files from here.I strongly recommend the usage of SWFAddress. It has some really helpful additional features.