An Introduction to FBML
On May 24th, 2007 Facebook released the Facebook platform. This is the complement to their previous API, based around the Facebook Query Language (FQL). Where FQL allows you do create applications from Facebook data, the Facebook platform, via Facebook Markup Langage (FBML), allows you to embed your application in the Facebook. Finally, Facebook has entered the world of widgets.
Lucky for us Facebook actually has a "widget strategy." MySpace's "widget strategy" isn't really a strategy at all; rather, it's a consequence of the fact that they basically allow people to enter anything they want into their profiles. A "MySpace widget" works just as well on MySpace as it does anywhere else. The Facebook platform, however, gives you access to the jewel of the Facebook universe: the social graph.
On the one hand this means that a Facebook widget really only works on the Facebook (at least until some other website supports FBML). On the other hand this means that you can create much richer applications by exploiting information about your users' relationships. Since the mini-feed informs your friends whenever you install an application you also get an excellent viral way to spread your application and your brand. But to do that you need to understand FBML.
Your Data as FBML
One of the most important concepts associated with Web 2.0 is the independence of data and presentation. You see this in things like XML/XSLT and HTML/CSS. Let's say you have a database-backed web application. Most of the time you're going to be surfacing this data as HTML. You have other options, of course. Maybe your reader wants his data in an RSS feed. The underlying data is the same but the format in which it is presented is different.
For those still in a SAT mindset we get the following analogy: HTML is to a browser as RSS is to a feed reader, and RSS is to a feed reader as FBML is to Facebook. Graphically the relationship is this:
HTML User <------> Browser <------> Server RSS User <------> Feed reader <------> Server FBML User <------> Facebook <------> Server
The Nuts and Bolts of FBML
FBML isn't quite HTML and isn't quite proprietary. The closest analog I can think of is ColdFusion, ironically the language in which MySpace is written. FBML consists of a subset of HTML (no script tags, for example) and a set of proprietary extensions.
These extensions act like HTML tags and can be divided into two broad classes: markup tags and procedural tags. Markup tags include UI elements and are generally directly translated into HTML. The fb:header tag, for example, produces the HTML for a Facebook-style header.
Other tags like fb:if-can-see have a programmatic component. In this case the content between the tags is rendered only if the current user has permission to do whatever is specified in the tag's attributed. For example
You're allowed to see 12345's profile, chum! No profile for you!
This would display "You're allowed to see my profile, chum!" if the current user could see user 12345's profile and display "No profile for you!" otherwise.
Some tags are more complicated, like fb:switch. fb:switch evaluates each of the fb: tags inside and returns the first one which does not evaluate to an empty string, e.g.,
You can't see either the photo or the profile pic
This would display the photo with pid 12345 if it could, otherwise it would try to display the profile picture of user 54321. If neither of these can be displayed (e.g., the privacy settings are such that you're not allowed to see them) then it will display the content in fb:default.
If you want to play around with FBML without installing and configuring your own application you can use Facebook's FBML test console.
Integrating With Facebook
FBML itself isn't so complicated, but integrating your existing application with the Facebook Platform can be a pain, especially since the whole process isn't very well documented. The first thing you need to do is install the Developer Application, which allows you to manage the applications you create.
Each application has a unique API key which doesn't ever change. When you create an application you also get a secret which you should never share — it's the only way the Facebook knows that an application is the application it claims to be.
So, to create a new application go to the Developer application, click on My Applications and then Apply for another key. Here you enter the name of your application. After agreeing to the Terms of Service click submit and you'll be redirected back to the My Application page. Once there click on "Edit settings" for your new application.
I'll wait until you get to the "Edit Settings" page. The key part here is to understand the Callback (URL) field. If you enter as the callback URL http://mydomain.com/myapp/ then all requests directed to http://facebook.com/myapp will go to http://mydomain.com/myapp. The callback URL serves as the base URL from which all requests are made. If you ask Facebook for foo.php it will try to fetch the FBML from http://mydomain.com/myapp/foo.php, interpret it, and display the results.
One could write an application which consists solely of static FBML pages if they wanted, but it would be pretty boring. To aide integration Facebook provides both Java and PHP client libraries. We'll focus on the PHP5 library.
The client library includes an example application called "Footprints" which is very instructive. The library provides a Facebook object, initialized with your API key and secret, which helps control the flow of the application.
$api_key = 'YOUR API KEY'; $secret = 'YOUR SECRET'; $facebook = new Facebook($api_key, $secret);
Facebook allows several points of integration and the $facebook object is the glue which allows you to push data to each of those integration points.
An important fact to note is that the Facebook platform contains both push and pull APIs. All user-specific data follows a push model. That is, if you want to publish data on a users profile, send a message, make a request, publish an item on a user's mini-feed, etc., you must push the request. All other data is fetched from your server by the Facebook when users access URLs like http://apps.facebook.com/myapp/do_something.php.
Here is the procedure by which users install an application, giving that application permission to push data to their profile, mini-feed, etc.
User visits http://apps.facebook.com/myapp/ and Facebook requests http://mydomain.com/myapp/
The application requests the user install the application by invoking $facebook->require_login() if the application plans to push user-specific data.
The user/application go through the authentication process. After the end of the authentication process (presuming the user follows through) the application is given the user's Facebook uid and a session key via a POST request. These are required to push user-specific data.
The application can now push data to a user's profile or mini-feed, make application-related requests on their behalf, etc.
The Nuts and Bolts of the Facebook Object
The Facebook object contains all the methods you'll need to interact with the Facebook platform. After a user has authenticated you'll probably be interested in the following:
- Redirects to the given URL. This is required because the the headers have already been sent by the time the Facebook requests data from your application.
- $facebook->require_login() and $facebook->require_add()
- Requires the user to login to your application or install it, respectively.
- $facebook->get_login_url() and $facebook->get_add_url()
- Returns the URL for your application's login or install page, respectively.
- $facebook->api_client->feed_publishStoryToUser($title, $body, ...)
- Publishes a feed item for the currently authenticated user.
- Returns the friends of the currently authenticated user.
- Returns the friends of the currently authenticated user who also have the application installed.
- Returns the specified groups (all by default) for the specified user (the current user by default).
- $facebook->api_client->profile_setFBML($markup, $uid=null)
- Sets the profile box FBML for the specified users (defaults to the current user).
This list is by no means comprehensive, but these are the highlights. There are also functions which deal with photos, notifications, and events. There's no real documentation for these functions outside of the library source, although there is a one-to-one correspondence with methods in the api_client and the methods listed in the sidebar of the developer documentation. This is definitely the least document part of the Facebook platform.
AJAX and other miscellany
In addition Facebook supports Flash and iframes on canvas pages. This means you could, in theory, embed your page directly into the Facebook.
From the above you should understand the basics of how Facebook interacts with an application. The Facebook expects your application to output FBML which it then transforms into a page for your user. In addition you can use the Facebook object to get information about the current user, such as their friends, groups, photos, and notifications.
But the above only touches the important parts. A lot of the platform remains undocumented and the best way to learn more is to just dive in. Here are some helpful resources.
- Developers Documentation
- Anatomy of a Facebook Application
- Step-by-step Guide to Creating an Application
- Developer FAQ
- Platform Wiki
- PHP5 Client Library, including a sample Facebook application.
There are some totally undocumented aspects of FBML. One that sticks out, using my ColdFusion analogy above, is the fb:query tag. You can see the stub on the FBML documentation at the wiki.
One oddity with the current platform is the way it integrates FBML and FQL. You can issue FQL queries directly via the Facebook object. This effectively doubles the latency of your application since the Facebook first issues a request to your application which then in turn might issue several FQL queries back to the Facebook before returning the finalized FBML. My suspicion is that FBML either at point contained or will contain the ability to execute FQL directly on the Facebook and iterate through the resultset.
Cheers, and happy coding!