Facebook integration for viral games

When doing games intended for viral distribution on the web, integrating with Facebook can be a bit cumbersome. The API seems to be primarily meant for used on a site embedded on a Facebook page, and whats worse, with a viral game you will not have control over the embedding page.

Here are a few tricks that will help you overcome those issues. However, there are still a few limitations:

  • Sending invites directly to a friend will not work, since loading the friend selection selection dialog will not be possible unless the embedding page is hosted on the canvas URL
  • It relies on use of ExternalInterface, and hence will not work if allowScriptAccess is set to “never”. The majority of gaming portals do allow external script access, but Kongregate doesn’t and very recently Newgrounds seems to have changed it so they don’t. Mindjolt does allow external script access, but asked me to remove the Facebook functionality.

Also, this is not a complete guide. You probably need decent knowledge of integrating Facebook with Flash to make much sense of it, but hopefully it could give you some ideas if you are struggling with how to get around the various issues involved with accessing the API when you have an application not hosted by yourself.

First of all, unless you plan to only have your swf only on sites that does allow script access you need to check if ExternalInterface works, and if it doesn’t disable your Facebook functionality. One would think that using ExternalInterface.available would let you know that, but it doesn’t tell you if the security sandbox will actually let you use ExternalInterface.

So instead I use the following code:

if (ExternalInterface.call("Date"))


hasScriptAccess = true;


If ExternalInterface is available you can include the JS API in the embedding page and add the “fb-root” div. Also, I use a JS function to open the login pop-up. I use the following function to add the necessary JS to the embedding page :

private function addFBJS():void


const script_js:XML =



function () {

var body = document.getElementsByTagName('body')[0];

var head = document.getElementsByTagName('head')[0];

var fbDiv = document.createElement('div');

fbDiv.setAttribute('id', 'fb-root');

body.insertBefore(fbDiv, body.firstChild);

var fbScript = document.createElement('script');

fbScript.setAttribute('async', '');

fbScript.setAttribute('type' ,'text/javascript');

fbScript.setAttribute('src', 'http://connect.facebook.net/en_US/all.js');


var fbWinScript = document.createElement('script');

fbWinScript.setAttribute('type' , 'text/javascript');

fbWinScript.text = "var fbWin = null; function fbWinIsClosed(){ return (fbWin == null || fbWin.closed); } function openLogin(url) { if (fbWinIsClosed()) { fbWin = window.open(url, 'fbwin', 'toolbar=0,menubar=0,resizable=1,width=800,height=480'); }}";







Just make sure to call that function before accessing the API.

One issue that turned out to be problematic was that when using Chrome I kept getting lots of warnings about x-domain access. To solve that you need to make sure that it uses the Flash protocol, instead of the default “fragments”.

I call the following function to handle browser detection and set the protocols as required. I have tested on IE, FF, Chrome and Opera. You might have to switch protocol on Safari as well, but I have not tested it and don’t know what will be used as default. Actual browser detection code is from http://www.quirksmode.org/js/detect.html

private function setXD():void


const script_js:XML =



var BrowserDetect = {

init: function () {

this.browser = this.searchString(this.dataBrowser) || "An unknown browser";

this.version = this.searchVersion(navigator.userAgent)

|| this.searchVersion(navigator.appVersion)

|| "an unknown version";

this.OS = this.searchString(this.dataOS) || "an unknown OS";


searchString: function (data) {

for (var i=0;i<data.length;i++) {

var dataString = data[i].string;

var dataProp = data[i].prop;

this.versionSearchString = data[i].versionSearch || data[i].identity;

if (dataString) {

if (dataString.indexOf(data[i].subString) != -1)

return data[i].identity;


else if (dataProp)

return data[i].identity;



searchVersion: function (dataString) {

var index = dataString.indexOf(this.versionSearchString);

if (index == -1) return;

return parseFloat(dataString.substring(index+this.versionSearchString.length+1));


dataBrowser: [


string: navigator.userAgent,

subString: "Chrome",

identity: "Chrome"


{ string: navigator.userAgent,

subString: "OmniWeb",

versionSearch: "OmniWeb/",

identity: "OmniWeb"



string: navigator.vendor,

subString: "Apple",

Page 1 of 3 | Next page