Deep linking in flash with AS3

Do you remember Krasimir Tsonev? He’s the author of the tween manager class and The Big Adventure.

He gave me the permission to publish an interesting post about Flash and search engine optimization.

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 <a> 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://www.emanueleferonato.com/stuff/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:


     
          Deep linking in Flash with AS3
     
     
          

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 <embed>/<object> tag.

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.

Remember to bookmark Krasimir's blog, it's full of really interesting articles like this one.

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stairs
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers