Home  >  

Overview of embedding SWFs into Facebook Canvas

Author photo
AddThis Social Bookmark Button
Following the first article where we introduced the basic usage of Flash with PHP and Facebook, this article will discuss the correct embedding of swfs into the Facebook canvas. There are a lot of ways of to do this and each one has its pros and cons. We will discuss this in in detail in this article. Every step will be accompanied by a sample where we'll demonstrate the pros and cons.
series badge
Find the rest of this series on the series page.

So, what types of embedding of swfs are there?

We have three and those are:

- With the <fb:swf> tag

- With the standard swfobject

- Inside an <iframe>

Embedding with the <fb:swf> tag

We already used this method in the previous article. It's the standard default method provided by Facebook. I had my own difficulties until I figured out how this tag exactly works. First of all, the tag can only be used if the render mode for the Facebook application is set to "FBML". So, the code structure necessary for the embed tag is:
 

<fb:swf swfsrc='mySWFLocation'  width='500' height='500'/>;
This is the simplest way for you to display the SWF in the FB canvas. However, there are traps that can cost us time and headaches. We must always provide the full address to the SWF, not the relative. This line of code will not work:
 

<fb:swf swfsrc='myFolder/mySWF.swf'  width='500' height='500'/>

This will not work because Facebook will render this code, but it will not find the movie. The address must be absolute:
 

<fb:swf swfsrc='http://www.myserver.com/myFolder/mySWF.swf'  width='500' height='500'/>

Now this will work. Facebook will render the tag inside the canvas and look up on your server for the swf. We must remember that Facebook acts just like a proxy in those cases. When a user requests the application, it pings the facebook server, then, facebook servers ping our server for assets like images or in our case, swfs.
There are some neat things to note about the method of embedding that made my life much easier. For example, there are the parameters that start with fb_sig_. They are passed by default to the swf and are immediately available with this method in ActionScript 3.0:
 

//get the params passed by facebook
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;

This way we have all the parameters that facebook passed to the swf.
 

fb_local_connection: _id49ae4b831c8291303193840
fb_sig_locale: en_US
swf_id: swf_49ae4b831f18b9865076447
fb_sig_app_id: 42704349238
fb_sig_time: 1236159363.1169
fb_sig_in_new_facebook: 1
fb_sig_ss: vy_kB5e3QqapaQRJ9sTc5A__
fb_sig: e3fab97d07f3a0bbe5369631d6d3a707
fb_fbjs_connection: _id_49ae4b831c7e68874314587
fb_sig_session_key: 2.WrdyViOPghfriiVUZ3yUtg__.3600.1236164400-1110516263
fb_sig_user: 1110516263
string_table: http://static.ak.fbcdn.net/js_strings.php/t85844/en_US
fb_sig_profile_update_time: 1236147566
fb_sig_expires: 1236164400
fb_sig_added: 1
fb_sig_api_key: 2b6378f4f5b55953f0c87d1eac40e4a1

We should now take a look at how this works to get a feeling for it.
Use the same Facebook application that was previously defined so you don't need to create a new one.
Open Flash CS3 with and save the new document as figTest.fla. The size of the document is not important here.
Place a dynamic text field on the stage and name it user_id.
article2_img1.png
Place this code on the first frame of your ActionScript layer:
 

//get the params passed by facebook
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;

user_id.text = params['fb_fig_user'];

The result should look like this:
article2_img2.png
  • There are some common notes for the <fb:swf> tag (with kind permission from this blog).
  • Currently, Facebook requires Flash version 9.0.0 for all tags.
  • Make sure that the flashvars parameter is all lowercase. Some sources of embedded links capitalize the V, which does not work on Facebook.
  • Currently, Facebook wraps the resultant Flash object in a
    tag, so despite the fact that the embed/object tag is not block-level, consecutive tags will appear one above the other instead of side-by-side.
  • To verify that your Flash object was loaded from a Facebook page, do the following. For security, this technique does not embed your secret key in your Flash app:
  • Get all the parameters whose names start with fb_sig_. (Do not include the fb_sig parameter itself.) In Flex use Application.application.parameters to do this.
  • Strip the fb_sig_ prefix from each, and make sure the keys are lowercase.
  • Create a string of the form param1=value1param2=value2param3=value3, etc., sorted by the names (not the values) of the parameters. Note: Do not use ampersands between the parameters.
  • Pass this string to your server, where your secret key is stored.
  • On your server, append your application secret key to the string that was passed in. The following is returned: param1=value1param2=value2param3=value3myappsecret
  • On your server, create an MD5 hash of this string.
  • Return the MD5 hash from your server to your Flash object.
  • In your Flash object, compare the returned hash with the fb_sig parameter that was passed in. If they are equal, then your Flash object was loaded by Facebook. (Or by someone who stole your secret key.)
Let’s move on to the swfobject tag.

Embedding with the swfobject tag

Unlike <fb:swf> there is a different approach using the swfobject tag. This is the method I first used and just because I'm using the <fb:swf> tag, it does not mean that I do not recommend this method. Well, first of all we need to know that the application must use the iframe render mode in order to display the swf. In the previous sample we used the FBML render mode for our applications. In this case we are allowing "normal" HTML to be embedded into the Facebook application canvas. This means we can use the standard swfobject tag.
This is a method that similar to standard swf embedding in canvas. This requires us to download the swfobject library to use this correctly. Although the method does not pass all the parameters by default, as previously mentioned, it does give us a neat solution to pass all values we need to the swf. The method is from my opinion a lot cleaner then the methods using in the <fb:swf> tag.
Here we see the application configuration for the method:
article2_img3.png
We will not go through the parameters that are already known, we need to check all the features that the embed methods offers to us in the facebook context. So, what is going on here?
One big disadvantage I personally discovered is that you need to pass all Facebook variables manually, Facebook will not do anything by default for us. Here is how the complete PHP and HTML look like:
 

<?php

require_once('facebook/php4client/facebook.php');

$facebook = new Facebook(YOUR_API_KEY, YOUR_SECRET);

$isAppAdded = $facebook->api_client->users_isAppAdded();

if(!$isAppAdded){
 	$facebook->require_add();
}

$fb_user = $facebook->require_login();

?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
	<head>

		<title>My Application</title>
		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
		<script type="text/javascript" src="swfobject.js"></script>
		<script type="text/javascript">

			var flashvars = {user_id: <?= $uid ?>, vote_id: <?= $vote_id ?>, friends: <?= $friends ?>, profilePics: <?= $profilePics ?>};
			swfobject.embedSWF("main.swf", "flash", "600", "500", "9.0.0", "expressInstall.swf", flashvars);

		</script>
	</head>
	<body>
		<div id="flash">
			You do not have the latest Flash Player to get this.
		</div>
	</body>
</html>

We really don't need to discuss the PHP because this code is discussed in detail in the first article. What we will discuss is the HTML code below. So, what do we see there? We see this line of code:
 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

The HTML starts with the standard HTML namespace declaration. We see the opening html tag:
 

<html xmlns="http://...

There is also the head and title tag, no need to discuss that in detail. We need to discuss this line of code:
 

<script type="text/javascript" src="swfobject.js"></script>

So, here we can see that the swfobject is imported. There is the next JavaScript block of code:
 

<script type="text/javascript">
var flashvars = {user_id: "someID", foo: "bar&#8220;};
 swfobject.embedSWF("main.swf", "flash", "600", "500", "9.0.0", "expressInstall.swf", flashvars);
 </script>

As we can see the flash object is defined with variables we need to pass to the swf. In this case it's the Facebook user id that was not passed by default.
The next line of code simply embeds the swf, this is something that does not need an explanation.
There is one note on using this method of passing vars to Flash when working with PHP or other server side languages. There is a problem with strings that need to be addressed. Remember those lines of code:
 

<?php

//include facebook api etc.
require_once("pathToYourFacebookLibrary/facebook/client/facebook.php");

//create new facebook instance
$facebook = new Facebook(YOUR_KEY, YOUR_SECRET);

//prompt the user to login
$fb_user = $facebook->require_login();

//check if the user has added the app
if (!$facebook->api_client->users_isAppUser()) {
 	//if not, redirect him to add it
             $facebook->redirect($facebook->get_add_url());
}

So we know that this piece of code is placed directly on top of the script. We also know that the $fb_user holds the user id. So in order to pass this to flash, we can't simply pass this:
 

var flashvars = {user_id: <?= $fb_user ?>};

This will not work because the variable needs slashes. So this way:
 

$id = "\"".$fb_user."\"";

Now this will work:
 

var flashvars = {user_id: <?= $id ?>};

This needs to be done with all variables. Unfortunately, I did not find a more elegant way to solve this problem. One solution might be to create a special function to add slashes to every variable.

Embedding with the <fb:iframe> tag

Well from my standpoint there is also the need to showcase this example. This is the technique I learned when discovered that the above methods have one drawback. The drawback is that there is no way to navigate away from page to other from inside the swf. For example, if you have index.php in you application:
article2_img4.png
and you need to navigate to a page where you need to invite your friends:
article2_img5.png
There is a problem with the security violation inside Flash. This line of code:
 

//add button listener
myButton.addEventListener(MouseEvent.CLICK, clicked);

//call this function when button is clicked
function clicked(e:MouseEvent):void{
 	
 	//navigate to new page
 	navigateToURL(newURLRequest('invite.php'), '_self');	
 
}

will not work. You will get a dialog like this:
article2_img6.png
that says the following:
 

SecurityError: Error #2137: Security sandbox violation: http://www.yourserver.com/yourApp/figTest.fla cannot navigate window _self within http://apps.facebook.com/myApp/index.php (allowScriptAccess is never). Attempted URL was invite.php.
	at global/flash.net::navigateToURL()
	at ria_fla::MainTimeline/clicked()

This is why we are talking about this (a bit awkward) embed method. Here is the syntax:
 

<fb:iframe src='http://www.myGreatServer.com/myApp/main.swf'  width='700' height='400'></fb:iframe>

At first, this looks similar to the <fb:swf> tag, but in this case it's an iframe (using the fb:iframe syntax). The content of the iframe is the swf. so, in order to showcase the small advantage that this method offers, we need to make a small application that will demonstrate that.
When looking back at the application that we previously created, we see that the button will work and we are able to navigate from page to page.
Each of those methods has it's advantages and disadvantages, sure. It is up to you to decide what type of you really need.
At the end we need to discuss the variables that are automatically passed to the swf when using the <fb:swf>:
 

fb_local_connection: _id49ae4b831c8291303193840

Still in beta, but using the <fb:fbjs-bridge/> bridge tag, we are able to establish a connection between the swf and FBJS. Here is the tag (still in beta):
 

<fb:fbjs-bridge/> 
<fb:swf swfsrc="FULL_URL_TO_MY_SWF" width="100" height="100"/> 
<script> <!-- --> </script> 

Using this AS3 code, we are able to connect from the SWF to FBJS:
 

var connection:LocalConnection = new LocalConnection(); 
var connectionName:String = LoaderInfo(this.root.loaderInfo).parameters.fb_local_connection; 
function callFBJS(methodName:String, ... parameters):void { 
 if (connectionName) { 
  connection.send(connectionName, "callFBJS", methodName, parameters); 
 } 
} 
callFBJS("document.setLocation", "http://someurl");

 

fb_sig_locale: en_US

For all you who want to create engaging multilingual applications, this is the parameter you were looking for. The default language selection by the user is contained in the parameter so we can create application that can load the desired language of the user at startup. This is pretty powerful!
 

swf_id: swf_49ae4b831f18b9865076447

This parameter can be pretty useful. As we can see it gives the swf a unique identifier. It is used and needed just because the actual html in the Facebook HTML page can contain a lot of other swfs in the page that is not your swf, like the swf for ads etc. You can use FBJS to access your swf in the HTML page using code like this:
 

FBJS:
---
function save(paramA, paramB) {
   document.getElementById('swf_id').callSWF('callAsMethod', 'methodName', paramA, paramB);
}

function grab_flash_data(flash_data){
   document.getElementById('some_id').setTextValue("test"+flash_data);
}

AS3:
---
var flash_data = new Array;
flash_data = "Sample data";
output.appendText("RETURNING: " + flash_data);
connection.send(connectionName, "callFBJS", "get_flash_data", flash_data);

Wow, this can be used for lots of cool stuff!
 

fb_sig_app_id: 42704349238

Personally, I’m not sure what I would use this parameter for but it’s nice to know that it’s out there. It is the id of the application in the actual facebook application database. I never used this in my own application, but it may be useful, for example when trying to connect to databases of other applications.
 

fb_sig_in_new_facebook: 1

This is a Boolean value indication if the user is using the new Facebook profile design. Again, I still have no real world sample of this but this can be useful for example when the application wants to know if the user has switched to the new design in order to access some features that are accessible only in the new design.
 

fb_sig_ss: vy_kB5e3QqapaQRJ9sTc5A__

This parameter contains the session secret and can be used for security reasons. With the parameter it can be checked it the swf originates exactly from the same source we assume. A lot of other security matters can be solved using the parameter so it's worth considering. We will come back at it.
 

fb_sig_user: 1110516263

This is the variable we already discussed. It contains the user id of the currend logged in user. The variable can be a little bit tricky when trying to treat it as a number. Its a lot safer to store it in strings. This way you will not need to care about ints, numbers and other number datatypes.
 

string_table: http://static.ak.fbcdn.net/js_strings.php/t85844/en_US

A reference to the Facebook default string table. It looks like this:
 

/*    HTTP Host:  static.ak.fbcdn.net                                          */
/*    Generated:  March 3rd 2009 11:58:00 PM PST                               */
/*      Machine:  10.16.139.110                                                */

// Locale: en_US
var _string_table = { "sh:loading" : "Loading..." , "sh:cancel-button" : "Cancel" , "sh:save-button" : "Save", "sh:submit-button" : "Submit", "sh:ok-button" : "Okay", "sh:confirm-button" : "Confirm", "sh:confirmation-title" : "Confirmation Required" , "sh:close-button" : "Close", "sh:download-button" : "Download", "sh:required" : "This field is required." , "sh:error-occurred" : "An error occurred." ,"sh:session-timeout":"Your session has timed out. Please login again.&#8221; , &#8220;sh:password-prompt":"Password:&#8221; , &#8220;sh:hide-link":"Hide&#8221; , &#8220;sh:show-link":"Show&#8221; , &#8220;sh:undo":"Undo&#8221; , &#8220;sh:delete":"Delete&#8221; , &#8220;sh:remove":"Remove&#8221; , &#8220;sh:ignore":"Ignore&#8221; , &#8220;sh:publish":"Publishing...&#8221; , &#8220;sh:edit":"Edit&#8221; , &#8220;sh:edit-lc":"edit&#8221; , &#8220;sh:no-thanks":"No, Thanks&#8221; , &#8220;fb:newsfeed":"News Feed&#8221; , &#8220;fb:minifeed":"Mini-Feed&#8221; , &#8220;fb:feed":"Feed&#8221; , &#8220;fb:chat":"Chat&#8221; , &#8220;dt:monthdate":"{month} {date}&#8221; , &#8220;dt:january":"January&#8221; , &#8220;dt:february":"February&#8221; , &#8220;dt:march":"March&#8221; , &#8220;dt:april":"April&#8221; , &#8220;dt:may":"May&#8221; , &#8220;dt:june":"June&#8221; , &#8220;dt:july":"July&#8221; , &#8220;dt:august":"August&#8221; , &#8220;dt:september":"September&#8221; , &#8220;dt:october":"October&#8221; , &#8220;dt:november":"November&#8221; , &#8220;dt:december":"December&#8221; , &#8220;dt:jan":"Jan&#8221; , &#8220;dt:feb":"Feb&#8221; , &#8220;dt:mar":"Mar&#8221; , &#8220;dt:apr":"Apr&#8221; , &#8220;dt:jun":"Jun&#8221; , &#8220;dt:jul":"Jul&#8221; , &#8220;dt:aug":"Aug&#8221; , &#8220;dt:sep":"Sep&#8221; , &#8220;dt:oct":"Oct&#8221; , &#8220;dt:nov":"Nov&#8221; , &#8220;dt:dec":"Dec&#8221; , &#8220;dt:monday":"Monday&#8221; , &#8220;dt:tuesday":"Tuesday&#8221; , &#8220;dt:wednesday":"Wednesday&#8221; , &#8220;dt:thursday":"Thursday&#8221; , &#8220;dt:friday":"Friday&#8221; , &#8220;dt:saturday":"Saturday&#8221; , &#8220;dt:sunday":"Sunday&#8221; , &#8220;dt:mon":"Mon&#8221; , &#8220;dt:tue":"Tue&#8221; , &#8220;dt:wed":"Wed&#8221; , &#8220;dt:thu":"Thu&#8221; , &#8220;dt:fri":"Fri&#8221; , &#8220;dt:sat":"Sat&#8221; , &#8220;dt:sun":"Sun&#8221; , &#8220;dt:today":"Today&#8221; , &#8220;dt:yesterday":"Yesterday&#8221; , &#8220;ac01":"Granting access to information is required to use applications. If you are not willing to grant access to your information, do not use this application.&#8221; , &#8220;&#133;

 

fb_sig_profile_update_time: 1236147566

This is one other interesting parameter passed to the swf. As you can see here you can check when the profile was updated. It can be used in applications that require to know when the profile was updated. For example there might be a informative application that checks if the user has updates on the profiles to run specific functions.
Conclusion: The engineers from Facebook did plenty of work in order to make our developer lives easier. We should take advantage of the parameters that Facebook has provided to us. In the next article, we will move forward and take on AMFPHP to discover how it can help us.


Continue to Part 3 of this series, Setting up AMFPHP for Flash and Facebook API

To view the entire series please visit http://www.insideria.com/series-facebook-dev.html

Read more from Mirza Hatipovic. Mirza Hatipovic's Atom feed mirzahat on Twitter

Comments

7 Comments

Ninopelo said:

This series is OUTSTANDING!!!

Please keep it going! BRILLIANT!

Maybe a dumb question: I am not getting the fb_sig_* parameters from Facebook when I visit the app URL. I can assign parameters to the tag (like this:

But when I use:

var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
user_id.text = params['fb_fig_user'];

I get nothing in the Dynamic Text field and I get 'undefined' in the trace.

My application is set to FBML. Am I missing something??

Thank you for this series! It is the only one of it's kind!!!!

Ninopelo said:

Great series!!! This is the best tutorial series out there...BRILLIANT!

I only receive these parameters from facebook when I load the app:

fb_local_connection _id49ff984e3f2158e78068734
fb_sig_api_key 8a06c5c7909346db0dc1e12ea3c162db
fb_fbjs_connection _id_49ff984e3f1be0764738840
swf_id swf_49ff984e3fa121f76968381
fb_sig_locale en_US
fb_sig_time 1241487438.2588
fb_sig_added 0
fb_sig_app_id 83848426919
fb_sig 37336e9b3f190dcb5e2106c4904d9402
string_table http://b.static.ak.fbcdn.net/js_strings.php/t86214/en_US
fb_sig_in_new_facebook 1

I do not receive any fb_fig_* parameters. Is there a reason for this?

Thanks for your help!!!

Ninopelo said:

I just figured out my problem!

I wasn't requiring login in the index.php, so I wasn't receiving the fb_sig_user and some other parameters.

Once I added:

require_once 'facebook.php';

$appapikey = 'my key';
$appsecret = 'my secret';
$facebook = new Facebook($appapikey, $appsecret);
$user_id = $facebook->require_login();

to index.php, it worked fine.

Sorry!

_polos_ said:

"To verify that your Flash object was loaded from a Facebook page"

If my flash call a php page an my server, how can I be sure that this page is called from my flash ?

Rahul said:

Was wondering if you could figure out how to implement amcharts.com in Fb? Amchart is a flash-based graphing software which i'd like to use in Fb but i'm not much of a programmer. I have tried/searched/experimented/googled/asked on the developer forum/asked on amchart forum band still not found a solution to this. Can you help??

cumagh said:

what will be the case if i'm using AS1 or AS2?

sean said:

Well, I need parts of 2 and 3....

1) I need to be able to navitage to other pages from flash...and
2) I need to pass flashvars to my swf

Is this possible?

I'm using FBML and i'm currently putting the swf in the iframe tag...but I'm not getting the results I need. If this is not possibly, is there another way to do this?

thanks
stringa

Leave a comment


Tag Cloud

Question of the Week: Dream App

If you had an unlimited budget and unlimited resources what application would you build and why would you build it?

Answer

Latest Features

Recommended for You

@InsideRIA on Twitter

Archives

  • Or, visit our complete archive.  

About This Site

Welcome to the premiere community site for all things RIA sponsored by O'Reilly Media and Adobe Systems Incorporated.