Thursday, December 13, 2007

Some important things to know about Facebook

I recently built a facebook widget out of one of our applications and I had a hard time getting started. Suffice it to say that Facebook's documentation is pretty limited for total newbies.

If you're new to facebook, you'll find the "getting started!" documentation more than frustrating: it's disingenuous. It promises an easy start-up - just read a tutorial, check out an example, and you're on your way! If only it were so easy.

The problem is that no one at Facebook ever stops to explain how Facebook actually works. For instance, there's a part of setting up an application where it asks for some default FBML, in case "setProfile" hasn't been called. What does this mean? Why would I call setProfile? What's the deal with that?

Maybe this comes naturally to most people, and so Facebook didn't feel the need to put it up there. I know I'm not the brightest developer to ever grace the web, but I'm not the worst either, so I figured it was worth a post outlining the things I didn't understand. On to said post.

The Two Main Parts
As far as I understand it, there are two main parts to any facebook application: a part of the application that can be embedded in the user's profile, and the actual application's page. These two things are totally separate. They can be related to each other, but don't really have to be.

Your Application Page
You'll need to host your application and all of it's data on your own web-server. Facebook has a service to allow you store data about a user on their server, but it's only in beta, and they still won't host your page or it's assets. Your application can be written in just about any language, though all of the Facebook supported example applications are written in PHP. When you get your application up on your own web-server, you can set your application page link under the "Callback URL" field in the application settings on Facebook. Why this isn't called "Application URL" or "Hosted Application URL" or "YOUR URL" or anything more intuitive than "Callback", I can't tell you.

Your application can either produce normal HTML output or custom Facebook-enabled HTML - called "FBML". If you use HTML, your application will be loaded in an iframe. If you use FBML, it'll be loaded directly into the facebook chrome on your facebook application page. You'll need to specify either FBML or iframe in your application settings to make this work.

Facebook's set of FBML tags is fairly well documented. Using their set of tags allows you to make some pretty good applications rather easily. Put these or your own HTML into your page, load it on your browser, and set it as the application callback url. Now when users hit, they'll see your page loaded into the facebook chrome, but only on that application page. This page and this set of code has more or less nothing to do with adding the application to their profile, which is probably what you really want to do.

Adding your application to the user's Profile
As I said before, the user profile part of the application is more or less completely separate from the rest of your application. This is the part I really had trouble with. Nowhere that I could find in the Facebook documentation to they explain the relationship (or lack thereof) between your application, your application page, and the application that's viewable in a user's profile. Here's what I learned through a long week of dusty php:

User profiles are comprised of FBML tags. By adding an application to Facebook, you earn the ability to add FBML to a user's profile. Any FBML you add will be limited to your application's space in the Facebook profile page. FBML is added using Facebook's "profile.setFBML()" method.

For example, if you want to add a Flash application to the user's profile, you'd need to define the FBML tag associated with your flash app (the fbml:swf object) and then add it to the user's profile. I do this in my application using Facebook's php library. The code looks like this:

//set the flash fbml so that the widget shows up in the profile
$user = $facebook->require_login();
$fbml.= '< imgstyle="border-width:3px; border-color:white;" swfsrc="[Your Swf's External URL goes here]" width="300" height="500">';

$facebook->api_client->profile_setFBML($fbml, $user);

This adds the fbml for the swf directly to the user's profile, meaning that the user will now see your application as part of their profile page.

If the user has added their profile but this code hasn't executed, Facebook gives you the option of providing default fbml in your application settings. This default FBML will only be displayed if your application hasn't added a single line of FBML to the profile; as soon as you add anything, even if it's non-visual, the default FBML will go away.

Adding Custom Data Parameters to User Profiles
The last difficult thing I learned was about how to add custom variables to a user's profile. My application needs to store three short string values per user. I could've made and housed my own database to house this data, but that seems like a lot of work for just a few variables.

Though Facebook doesn't yet offer an easy way to do this directly, you can store variables into the non-visual fb:js-string tag, like this:

$fbml = '<fb:js-string var="VariableName">variable value</fb:js-string>';
$facebook->api_client->profile_setFBML($fbml, $user);

You can get this data back and parse your application using the profile.getFBML method and parsing the data by hand. I'm sure there's a good, easy way to do this in PHP, but the XML library included with the Facebook php 4 library by default is a pain. It doesn't recognize namespaces in XML elements (so the fb: tags screw it up) and it doesn't handle the dash in "js-string" well either. I used a few string replaces to clear these out and then parsed the data by hand, like this:

$scrubString = ereg_replace("fb:", "", $string);
$scrubString = ereg_replace("js-string", "jsstring", $scrubString);

//create a new XML object from our "scrubbed" string
$impl = new IsterXmlSimpleXMLImpl;
$sxml = $impl->load_string($scrubString);

//Get the "jsstring" members of our XML object, which is
//where our earth live specific variables are stashed.
$jss = $sxml->fbml->jsstring;

The variable "jss" now consists of an array of our js-string variables. Parsing the data is easy using a quick loop:

foreach ($jss As $result) {
$attributes = $result->attributes();
$var = $attributes['var'];
switch ($var) {
case "VariableName":
$variableName = $result->CDATA();

PHP 5 includes some native XML processing methods, so it's probably much easier - the server I was forced to host on only had PHP 4, so we had to make it work.

I hope this helps save you some time on your future facebook endeavors. Feel free to hit the comments if you have other questions about adding Flash apps to facebook and I'll answer if I can.


Hillary said...

I agree with your post. I've been searching to no end for a way to show a swf on a profile without clicking. FB promises it is possible using FB:js-string and a simple AJAX call but I haven't gotten that to work. In searching I found your article and I'm trying to work around it using your way of setting the swfsrc in an img tag. That doesn't seem to work either. Hopefully someone can post a presently working example.

Thanks for your FB insight.

Luke said...

I was able to follow along for a while there, but I am still lost as to how to add a flash object (swf) into the app. Whenever I try it it just shows up blank and wont load the image or the flash document. Can you simplify that some more? Also, I see you are using a $facebook variable, and I tried to put that in, but doesn't it take over where I use that to declare my api and secret keys? Thanks

RJ said...

@Luke: It sounds like you're getting something to the profile, right?

Off the top of my head I'd say to make sure your urls are absolute - if your swf or image are using relative paths, then it won't work. They need to be hosted on your server and referenced absolutely in your php code.

Here's how you initialize the facebook object - this is more or less right out of their example file:

include_once '../php4client/facebook.php';

$api_key = [your api key goes here];
$secret = [your secret goes here];

$facebook = new Facebook($api_key, $secret);
$user = $facebook->require_login();

$initialProfile = $facebook->api_client->profile_getFBML($user);

That should do it - let me know if you still have trouble. Feel free to email me directly - rj[dot]owen[at]effectiveui[dot]com and I'll be happy to help if I can. Thanks!

Anonymous said...

It appears that you can get a swf object to appear without a click in the profile using SWFObject.

The JS library file for this function appears to load in the FB html head.

The music applicatoin iLike appears to use this method.

Have tried to replicate it myself, but to no avail. I can put the necessary code into the profile FBML, but when I use 'onClick = SWFObect', FB rewrites the function name, and then my browser can't find it?

Bryan Green said...

So here's a question: does the code in the "Default FBML" field only apply when a user first adds the application? Or can it be changed "on the fly"?

Also-- I've never been able to get the "Default FBML" field to work in any case, and I'm not rendering profile FBML from my PHP code at all, just trying to use the default FBML field...all that is shown in the profile box is "no content to display..."


RJ said...

Hi Brian - it's been a while since I did any of this, but it's my understanding that default FBML shows the same for every user unless you make a "setFBML" call to add new code, "on the fly", to their profile.

Here's another great "getting started" link:

Bryan Green said...

Thanks, rj-- that's a great link!

Bryan Green said...

Grrr! The "Default FBML" field ain't workin' for me at all! I'm doing exactly what is mentioned in the "Marketing Ninja" blog (and elsewhere). I'm just getting "No content to display" in the profile box. Is anyone else using the "Default FBML" field with success?

... said...

fantastic post, thank you.. actually, I dare to say that this should be a standard facebook document for beginners! it sure clarifies A LOT of things that cannot be simply found in the documentation