Grails, SEO, SWFObject and Flex : Progressive Enhancement – Layering SWF on top of GSPs

I’ve been busy figuring out how Grails can help search engine rankings of Flex / Flash applications. In this post, I will show how the SWFObject library can be used with Grails layouts to enable a SEO technique called Progressive Enhancement ( thanks Ted! ).

Progressive Enhancement is a technique that allows the same content to be shown to different users, regardless of the ways in which the content is viewed. The idea is that the same content should appear on a Flash player page and one that is plain HTML and indexed by the Google searchbots.

I outlined the search engine problems with SWF files in a previous post. Starting with this post, I will focus on the technical aspects of solving this problem.

The first step in making our Flex RIAs fully searchable is to be able to front-end our GSP pages with an actual SWF file. While this is possible with the standard flash html wrapper, SWFObject makes the job much easier because it reduces the amount of code needed into a few lines.

To include the library, download the component and copy the swfobject.js file into your Grails applications’ web-app/js file.

Next, we need to modify our view pages so that they contain a reference to the actual SWF file. My solution involves using Grails’ integrated sitemesh layouts and the jsecurity plugin, so in

grails-app\views\layouts\main.gsp

I changed the following lines after <g:layoutHead/>

<g:layoutHead />
        <g:javascript library="application" />
        <g:javascript src="swfobject.js"/>

        <jsec:isNotLoggedIn>
            <script type="text/javascript">
                var flashvars = {};
                var params = {};
                var attributes = {};
                swfobject.embedSWF("${createLinkTo(dir:'swf', file:'uberflash.swf')}", "main", "100%", "100%", "9.0.0", false, flashvars, params, attributes);
            </script>
        </jsec:isNotLoggedIn>

    </head>

And that’s it! Anytime you navigate to a Grails page, you will see the flash content. If you view the source of the page, you will see that the content generated by Grails also appears on the same page. Essentially, you are simply overlaying your Flex SWF on top of your GSP page.

If you don’t have flash installed, you will see the standard grails GSP page, or if you have set up content negotiation, you could even use this technique to show pages to mobile devices differently.

I have a file under /web-app/swf/uberflash.swf that contains my flash content and is deep-linking enabled, this file will display different content based on the URL of the site. Depending on your implementation, you might want to add the above code to individual views or view templates ( via install-templates ). This will allow you more granular control, such as showing an admin SWF for edit pages and a view SWF for show and list pages.

Note that for administration purposes, we obviously want to show the underlying GSP pages. I get around this problem by only showing the swf file to the users who are not logged in. If an user is logged in ( or if needed, has the right permissions ), then I show the background page, which allows me to edit, delete and change GSP pages. If I need to enable previewing of this content, I could add a preview param and show the flash content to administrators.

Note that you could have the SWF compile dynamically using the Flex plugin for Grails, or compile during your build process using Maven that I outlined in this post.

And that’s it! This is how you backend Flex swf apps with Grails content.

There are a few other techniques that I have uncovered in my exploration of SEO, and they are forthcoming in future posts, including:

  • Deep linking within Flex applications
  • Passing data from Grails to Flex using REST services
  • Serving static page front ends in Grails
  • Making human readable and optimized URL mappings
  • Grails scripts for sitemap building
  • Allowing Flex and Flash to talk and pass data to each other

Stay tuned.

Leave a comment