Wednesday, June 9, 2010

Facebook Simple Integration



In a previous post we looked at the Graph API as resource for reading and writing Facebook data. In this post we look at a simple Facebook integration. A Facebook integration is about tapping into, extending, and enriching (with new experiences) a user’s social graph. If a Facebook user can sign on to a non-Facebook site using Facebook credentials, and the user authorizes the site to access some of his FB data, then any content on the site can be recommended or shared with the user’s friends – to illustrate a simple scenario. The user’s social graph in this scenario has been extended. Before you start an integration you should consider the following:

  • What’s your end result? Is your end result going to be web page that is external to Facebook like TripAdvisor (with FB login button e.g.) or is it going to be an application that runs within Facebook (i.e. has the Facebook chrome around it) like the TripAdvisor Travel Map (see the application directory for more applications)? Or will it be both external and internal to FB. In this post, I’m tackling the first scenario (external), though the code can be used for the second scenario as well.


  • How are you going to render your content? Are going to use IFrames or Facebook Markup Language (FBML) ? This topic discusses the choices. I started with FBML because without any prior experience with Facebook development the documentation (by my reading) seemed to suggest to go that way. As I got into it I found that not all the FBML features are, shall we say, well-baked and I ran into lots of little problems that took time to figure out. I also used the new JavaScript API as opposed to the old one, because the docs recommended it.
Before showing the code there are a couple of things to point out.

1) If you are using FBML like fb:login-button or fb:comments don’t forget to include a namespace declaration so that the prefix “fb” is understood. They rarely mention this in the docs.

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">


2) Don’t forget to include a script reference to the FB SDK. (In this code sample below I did not load the SDK asynchronously as recommended, but that ‘s easy enough to do following the code sample here.)

<script src="https://connect.facebook.net/en_US/all.js" type="text/javascript"></script>



3) In this code sample, I use jQuery as well, so I load that too. It doesn’t matter where you load it from; the sample here loads it from the Microsoft CDN.

<script src="https://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js" type="text/javascript"></script>


4) The FBML tag for like functionality fb:like did not work. had to resort to using an iframe. Last I saw there was a bug open for it.

5) At first I used server-side handling of the FB cookie, that is checking for it and pulling out the necessary information, like tokens. I used the C# approach here. Then I would pass the cookie info from the server-side to the client-side for use in JavaScript. Then, I discovered by chance that you could get the cookie easily using FB.cookie.load() method by playing around with the FB Test Console page. I would have expected this to be called out in the JavaScript SDK page but it wasn’t. In the end, the code sample below examines the cookie but doesn’t really use its information. I guess to the credit of the JavaScript SDK they’ve designed it so you don’t have to work with the cookie for common scenarios.

6) The FB login button doesn’t have a counterpart, log out. I was expecting that. So you have to provide your own log out feature and manage the displaying and showing of it and the FB login button. When the user is logged in, don’t show the FB login but show logout.

7) The code sample below worked in Firefox 3.6.3 and Chrome 5.0.375. But alas, IE 8.0 presented several problems where the consent/authorization dialog would not go away and the page ½ functioned. I saw mentions of this behavior in the forums, but did not pursue. Hopefully it gets worked out.

8) The div with id=”fb-root” is required, but nowhere is there a hint as to why it’s needed. Looking at the all.js file it looks like it might be used for cross domain communication when dealing with older browsers. Debugging and looking at what was inside the fb-root div during various times in the page lifecyle, I never saw anything in the div but that’s probably because I’m using a “modern” browser. In fact, I looked at the FB.XD._transport variabel and confirmed I was using “postMessage” capabilities of HTML 5 – which is the latest and greatest.

Here’s the code sample, a simple HTML page. You must run this file in the context of a web site. For example, register an application and get an application ID at Facebook, host the page on a web site locally on your test server (the same domain you registered), and place this page in the web site and browse to it. I used HTTPS for all my tests.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">
<head runat="server">
<title>Facebook Integration - Test</title>
<script src="https://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="https://connect.facebook.net/en_US/all.js" type="text/javascript"></script>
<script type="text/javascript">
var fbCookie = {
accessToken: null,
signature: null,
userId: null,
secret: null
};

$(document).ready(function () {
FB.init({
appId: '107702769253652', // Fill in your correct AppID
status: true, // check login status
cookie: true, // enable cookies to allow the server to access the session
xfbml: true
});
});

FB.Event.subscribe('auth.sessionChange', function (response) {
if (response.session) {
// A user has logged in, get cookie information.
fbCookie.accessToken = FB.Cookie.load().access_token;
fbCookie.signature = FB.Cookie.load().sig;
fbCookie.userId = FB.Cookie.load().uid;
fbCookie.secret = FB.Cookie.load().secret;
$('#Login').css('display', 'none');
$('#Logout').css('display', 'inline');
} else {
// No session. Take action if needed.
}
});


function DoLogout() {
FB.logout(function (response) {
// User is now logged out
$('#Login').css('display', 'inline');
$('#Logout').css('display', 'none');
});
}

function GetDataAboutMe() {
FB.api('/me', function (response) {
$('#UserData').html("Name: " + response.name + ", gender = " + response.gender +
", birdthday = " + response.birthday + ", email = " + response.email);
});
}

function GetDataAboutFriends() {
FB.api('/me/friends', function (response) {
var sb = "";
for (var i = 0; i < response.data.length; i++) {
sb += "Friend" + i + ": " + response.data[i].name + " (" + response.data[i].id + ")<br/>";
}
$('#FriendData').html(sb);
});
}

function PostToNewsFeed() {
var body = $('#TextBox3').val();
FB.api('/me/feed/', 'post',
{
message: body,
name: "Test Post",
caption: "Test Post Caption",
description: "Test Description",
link: "http://travelmarx.blogspot.com"
}
, function (response) {
if (!response response.error) {
$('#PostResults').html("Error posting to news feed. Error: " + response.error.message);
}
else {
$('#PostResults').html("Posted to news feed successfully.");
}
});
}
</script>
<style type="text/css">
#Logout {display: none; }
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<div id="fb-root">
</div>
<h3>
Login Functionality</h3>
<fb:login-button perms="email,user_birthday,read_stream,publish_stream,read_friendlists"
id="Login">
</fb:login-button>
<input type="button" value="logout" id="Logout" onclick="DoLogout()" />
<hr />
<h3>
Like Functionality (using iframe because fb:like wasn't working)</h3>
<img src="Folder.jpg" width="100px" />
<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Ftravelmarx.blogspot.com&amp;layout=standard&amp;show_faces=true&amp;width=450&amp;action=like&amp;colorscheme=light&amp;height=80
scrolling="no" frameborder="0" style="border: none; overflow: hidden; width: 450px;
height: 80px;" allowtransparency="true"></iframe>
<hr />
<h3>
Comments</h3>
Comments about this integration site? <br />
<fb:comments>
</fb:comments>
<hr />
<h3>
Getting Graph API Data</h3>
<input type="button" id="Button1" value="Get Data About Me" onclick="GetDataAboutMe()" />
<span id="UserData"></span>
<br />
<input type="button" id="Button2" value="Get Data About Friends" onclick="GetDataAboutFriends()" />
<span id="FriendData"></span>
<br />
<fb:prompt-permission perms="read_stream,publish_stream">Would you like our application to read from and post to your News Feed?</fb:prompt-permission>
<br />
<input type="button" id="Button3" value="Post to News Feed" onclick="PostToNewsFeed()" />
<input type="text" id="TextBox3" />
<span id="PostResults"></span>
<br />
<hr />
<h3>
Activity</h3>
<fb:activity recommendations="true">
</fb:activity>
</div>
</form>
</body>
</html>

3 comments:

  1. awesome post you can find me at facebook.com/nirbhab

    ReplyDelete
  2. hi, nice entry.

    do you have any idea how I can desplay profile pictures of friends as well?

    ReplyDelete

All comments go through a moderation process. Even though it may not look like the comment was accepted, it probably was. Check back in a day if you asked a question. Thanks!