Category Archive for Tutorials

Google Analytics and Flex using ExternalInterface

A big issue for people creating flash sites is getting the site to work well with Google Analytics. “The page doesn’t refresh. How can I track the clicks?”

Well, it is actually very easy. If you look at the trace script Google Analytics gives you to add to your HTML code you can find a call to a method that actually records the event. This method is simple to call using JavaScript.

I have solved it like this in my latest Flex App (which is a public site). NOTE: This is for the new trace code version.

1. Paste the Google Analytics trace code as usual just before the </BODY> tag.
Check your Google Analytics account for the correct code.

2. See to it that your embedded flash works with ExternalInterface.
This can be a bit tricky, but in my experience the things that do the trick are to change allowScriptAccess to always and inside the Flex App call a custom JavaScript function on creationComplete like so: ExternalInterface.call(’initFlash’). In my html this initFlash function creates a variable reference to the embedded flash. This sort of “creates the connection” between them. I’m not sure why this is so, but for me it works, so I’m happy with that. If there is a need I would be glad to create a more thorough tutorial on the use of ExternalInterface. Just let me know.

3. Create a custom JavaScript that passes the URL you want to register to the Google Analytics script.
This is not necessary, but I have found it easier to work with, as you don’t need to edit you call from inside of Flex if something changes in the Google code or such.

function trackURL(url)
  1. {
  2.     pageTracker._trackPageview(url);
  3. }

4. Call your custom javascript from within Flex.
I created a static class for this. (I love static classes). I named it Analytics.as and placed it in the root source folder in the Flex App. It looks like this. All it does really is call the JavaScript using ExternalInterface, but putting it within a static class lets you call it from anywhere in your application without having to pass on references to this or that object or function.

package
  1. {
  2.    public class Analytics
  3.    {
  4.       import flash.external.ExternalInterface;
  5.  
  6.       public static function track(url:String) : void
  7.       {
  8.          ExternalInterface.call("trackURL", url);
  9.       }
  10.    }
  11. }

And anywhere in your app write:

  1. Analytics.track('/path_to_tha_page_you_want_to_track/');

(NOTE: You have to start your path with a slash).

There you go. It now should track the URL:s you want and give you nice statistics.

  • Share/Bookmark

AMFPHP and Flex

Being a LAMP (Linux Apache MySQL PHP) guy as well as a Flex developer it didn’t take me long to discover AMFPHP. If you haven’t heard of it I can tell you in short it’s a framework for sending and receiving data between Actionscript and PHP, without having to use an XML layer or similar in between, so to speak. It’s really neat, because lets say you extract an array of rows from your MySQL database, then you can just pass the entire array back to Actionscript and it will be received as an Actionscript array in the other end.

Would you like to try it? This is how to do it:

1. Download the latest AMFPHP package from www.amfphp.org

2. Unpack and (preferably) place the folder called amfphp in the document root on your web server.

3. By default the AMFPHP gateway is set to converting all UTF-8 data to Latin 1. Big NO NO for “international” developers like me, so you should open the gateway.php file in the amfphp folder for editing and change the following line (it should be around line 127):

  1. $gateway->setCharsetHandler("utf8_decode", "ISO-8859-1", "ISO-8859-1");

to

  1. $gateway->setCharsetHandler("iconv","UTF-8","UTF-8");

If you don’t do this all UTF-8 special characters from the database will be distorted on arriving at the Flex application.

4. Now create a simple PHP class file, call it HelloWorld.php, and place it in the /amfphp/services folder. You should use a commenting pattern like that of PHPDoc. Here is a simple HelloWorld example:

/**
  1.  * A simple amfphp service.
  2.  */
  3. class HelloWorld
  4. {
  5.  /**
  6.   * A simple HelloWorld function
  7.   * @returns A string containing the phrase 'Hello World!'
  8.   */
  9.  function SayHello()
  10.  {
  11.   return "Hello World!";
  12.  }
  13.  
  14.  /**
  15.   * A simple HelloWorld function that bounces back the given string
  16.   * @returns A string containing the supplied string
  17.   */
  18.  function SayWhat($string)
  19.  {
  20.   return $string;
  21.  }
  22. }

In this class I’ve put two functions; one that returns the string ‘Hello World!’ and another that returns whatever string you send to it. Okay, so let’s get on with the show…

5. Now you can test your service by browsing to the browser folder. It should have a URL similar to this: yourserver.com/amfphp/browser. In the service browser you can test whether your class is working as it should.

6. Flex
To simplify things I’ve created a small class for the implementation of this in Flex. There is a number of ways of doing this, but I’ve chosen the one way that I am most comfortable with.

For ease of use, create an actionscript document in your Flex Projects root directory called AMFPHP.as and past the following code into the file:

package {
  1.  import flash.net.NetConnection;
  2.  import flash.net.Responder;
  3.  
  4.  public class AMFPHP
  5.  {
  6.   private static var gateway:String = "http://www.yourserver.com/amfphp/gateway.php";
  7.   private static var connection:NetConnection = new NetConnection;
  8.   connection.connect(gateway);
  9.  
  10.   public function AMFPHP() : void
  11.   {
  12.    // Static class
  13.   }
  14.  
  15.   public static function send(serviceFunction:String, resultHandler:Function, faultHandler:Function, … args:*) : void
  16.   {
  17.    trace("AMFPHP("+serviceFunction+")");
  18.    // Create responder
  19.    var responder:Responder = new Responder(resultHandler, faultHandler);
  20.    // Create an array that will temporarily store all the arguments
  21.    var collectArgs:Array = new Array;
  22.    // Add the fixed arguments
  23.    collectArgs.push(serviceFunction);
  24.    collectArgs.push(responder);
  25.    // Loop through the optional arguments and add them too
  26.    for (var i:uint=0; i<args.length; i++)
  27.    {
  28.     collectArgs.push(args[i]);
  29.    }
  30.    // Create a reference to the function we will call
  31.    var callFunction:Function = connection.call;
  32.    // Call the function using the arguments
  33.    callFunction.apply(connection,collectArgs);
  34.   }
  35.  }
  36. }

The only thing you have to change here is the URL to the gateway.php file on your server at line 7 in the file.

7. Usage

To use this in your code you will need three things:

• Calling the service using the static AMFPHP.send() function
• A function that handles the result coming from amfphp
• A function that handles errors

This is the first HelloWorld example (without the argument). The first argument for the send() function is a string describing the path to the function, with this structure: [directory.]class.function, within the services folder. A directory is not necessary, but can be convenient if you have packages of many classes.

private function helloWorld() : void
  1. {
  2.  AMFPHP.send("HelloWorld.SayHello",onResult,onFault);
  3. }
  4.  
  5. private function onResult(result:String) : void
  6. {
  7.  trace(result);
  8. }
  9.  
  10. private function onFault(result:Object) : void
  11. {
  12.  trace(String(result.description));
  13. }

Easy huh!?

And the example with the argument is pretty much the same, but with an argument added to the end of the function call. Like this:

private function helloWorld() : void
  1. {
  2.  AMFPHP.send("HelloWorld.SayWhat", onResult, onFault, "Hello to you!");
  3. }
  4.  
  5. private function onResult(result:String) : void
  6. {
  7.  trace(result);
  8. }
  9.  
  10. private function onFault(result:Object) : void
  11. {
  12.  trace(String(result.description));
  13. }

Note that I changed the path to the function from HelloWorld.SayHello to HelloWorld.SayWhat to use the other function in the class.

Well, that’s it. Hope it was of some use. Good luck!

  • Share/Bookmark