Omniture Tracking in Flash, Flex and AIR Applications

If you are developing Enterprise level applications chances are you are either used Omniture or you will be asked to integrate with Omniture tracking services. This post is not really about the specifics of Omniture tracking, but rather about the implementation methods for Flash, Flex, and AIR (with Flex). Usually, Omniture tracking events are sent using JavaScript on a web page. An HTML page would include the Omniture JavaScript library and events in your web application would call methods in the libary.

When creating RIA with Flex or Flash you have a couple of options. Ominture provides a proprietary ActionScript library, called ActionSource, for easy integration. ActionSource is a Flash MXP component library that transmits analytic data to Omniture without relying on calling JavaScript methods. This implementation is best for situation when your have a Flash file that can not call JavaScript. Brightcove has a good article describing this type of implemenation. Integrating Omniture services with Flex does not require the ActionSource library.

Flex has the ability to write and call JavaScript directly. With Flex, you can use the ExternalInterface call to call JavaScript functions on the page. So a typical call might look like this:

[as]
ExternalInterface.call(“trackOmniture”, omnitureType);
[/as]

Where the value for the omnitureType represents the information you want to transmit to Omniture for analysis and “trackOmniture” is the name of a JavaScript method on the HTML embed page for the Flex application that calls Omniture methods in the included JS library from Oniture for HTML integration. Just setup your account information and other parameters in the Omniture JS library like you normally would for tracking Omniture in HTML-based applications.

Adobe AIR introdocues some new challenges and new solutions for Omniture tracking. An AIR application does not run in a web browser, its a desktop application that can make HTTP requests. Using ExternalInterface calls to an embed HTML page is not an option in this scenario. Now, you can create an entire AIR application with just HTML and JavaScript. However, in our implemenation we want to use Flex in AIR to create the application.

Lets talk a little bit about the new AIR security model introduced with Beta 3. According to Adobe :

One of the main threats facing HTML applications, whether desktop or web, are injection attacks which result in malicious code execution. Code is usually injected via a few common vectors such as via URL handling (“javascript:” and other dangerous schemes), eval() and assigning external HTML content to DOM elements such as innerHTML and outerHTML.

As a result of the security vulnerability AIR now uses two kinds of sandboxes, one is called the Application sandbox wich allows full access to AIR API’s but disables the JavaScript parser after the initial load to prevent exposure of the API to possibly harmful JavaScript calls (like eval()). The other sandbox is the “Non-application” sandbox. This is where you can execute JavaScript like you would in a browser, but it does not have direct access to the AIR system API’s and therefore can’t raise havoc on your application. Now to talk between the two sandboxes you need to use Adobe’s new SandboxBridge mechanism which can expose methods in both the parentSandboxBridge (the application sandbox) and the childSandboxBridge (the non-application sandbox location). So what does this mean for handling Omniture tracking in AIR?

Well, the Omniture JavaScript file is pulled from a separate domain and contains JavaScript deemed a security risk. This means that Omniture needs to run in the non-application sandbox, but the application reporting calls need to be made in the application sandbox.

This makes for an interesting implementation. Adobe does offer a good example of scripting between content in different domains. In this method, the main HTML content is loaded into the initial window of the application security sandbox, while the content from another domain is loaded into a <iframe> that specifies the content is placed in a non-application security sandbox.

Our application is built Flex within an AIR project, so we need to change the example from Adobe just a little bit to fit our specific implementation since they are building an AIR application with HTML. We are going to create an MXML file that loads an HTML page from a directory within our application called “omniture”. We do this using an HTMLLoader that loads our main HTML content (track.html). We use the instance of the HTMLoader to call a method within the loaded HTML window called “track”. Loading HTML into an HTMLLoader control will execute the HTML code on that page. So this page contains basic HTML and JavaScript that does not have a security risk. This loaded HTML page is not displayed inside our application the HTMLLoader is used merely to load and execute the HTML code, and also serve as a way to reference the JS methods of the loaded content.

[as]
private var html:HTMLLoader; // omniture tracker
/**
* @private
* Create an HTML object to handle Omniture tracking within
* the application.
**/
private function createHTMLTracker():void
{
html = new HTMLLoader();
//html.addEventListener(Event.COMPLETE, onHTMLLoadComplete);
html.load(new URLRequest(“omniture/tracking.html”));
}

/**
*Tracks Ominture events by callint a JavaScript function within the page
*loaded into an HTML control.
*@private
**/
private function omnitureHandler(omnitureType):void
{
if(omnitureType != null){
try{
html.window.track(omnitureType);
} catch(e:Error){trace(e.message);}
}
}
[/as]

The track.html page also loads another HTML page into an <iframe> tag and establishses our SandboxBridge between the track.html page and the loaded HTML page. This second HTML paged (ui.html) loaded into the iframe includes our Omniture JavaScript library. The ui.html page can contain the JS library because we specify in the properties of the iframe that the content be placed in a non-application security sandbox. Our project includes a sub-directory called “omniture” that has two HTML pages, the tracking.html and the ui.html page. It also includes one more file, the AIRAliases.js file, which allows us to use AIR shortcuts within the tracking.html file. Below is the code for the tracking.html page this page does stray too far away from the example provided by Adobe, just notice the iframe tag settings for loading pages from a sub-directory within your AIR project.

    track.html

[as]

// include the AIRAlias.js file to access AIR short cuts, like air.trace

// create an object that will be used to expose AIR functionality
// (developer functions) to the browser sandbox
var Exposed = {};

// expose the trace method
Exposed.trace = function(str) {
air.trace(str); // this trace shows up in debugger
}

function doLoad() {
// place Exposed on the parentSandboxBridge property of the browser sandbox (iframe)
var frame = document.getElementById(‘child’).contentWindow.parentSandboxBridge = Exposed;

// get the functions exposed from the Browser Sandbox
window.track = document.getElementById(‘child’).contentWindow.childSandboxBridge.trackPage;
}

[/as]

The ui.html page is loaded within the iframe, who sets it to load the content in the non-application security box (sandboxRoot=”http://localhost/omniture/&#8221;). The ui.html page uses JS to include the Omniture library (my_omniture_endpoint is specific to each client for Omniture tracking):

<script src=”http://my_omniture_endpoint/omniunih.js&#8221; type=”text/javascript”/>

The page also establishes our Omniture suite name:

var s_account = “mysuitename”;

The method track is exposed to the track.html window; this is in turn called from our MXML application, passing in Omniture tracking information. The ui.html page makes all the necessary calls to Omniture within the track method. Everything is secure and AIR is happy. Below is the ui.html code, I commented out the client specific information.

    ui.html

[as]

var s_account = “”; // your omniture suite name

// developer function implemented in the browser sandbox
function track(pagename)
{
// Call your Omniture JS library methods here…..

// trace out the return in the parent
parentSandboxBridge.trace(“tracked: ” + pagename);

}

function doLoad()
{
// expose this function for the application sandbox by writing to the childSandboxBridge property of the window
childSandboxBridge = {‘trackPage’: track};
}

[/as]

With this implementation method you can perform Omniture tracking from inside your AIR applications just like you would if they were web-based applications or Flex applications using ExternalInterface calls. The added benefit of including the Omniture JS library dynamically within the ui.html window is that the application always gets the latest version of the JS library. We could have taken the entire JS library and wrote it to a local .js file within our project. We could have also rewritten the JS library to exclude the extensive use of “eval()” and run it within the application security sandbox. However, I think this implementation allows the most flexibility. The new AIR security model doesn’t prevent us from running JavaScript; it just requires us to take some extra steps to work with content from other domains, all while being secure.

– Mister

3 Comments

  1. Hi Michael ,
    I am aslo trying to access remote javascript using flex-AIR app.
    I am getting the content in my iframe, but when I click on any link within loaded content through JavaScript, it simply does not work.
    I am clueless.
    Could you share your code or tell me the possible issue?
    Would appriciate your help.

    Thanks

Comments are closed.