Facebook, Twitter, and other social media websites, also called the new media, are becoming a major part of our culture. Facebook alone has 175 million active users. They are a means to reach broad audiences and build enthousiasm.
This tutorial is part 2 of a series that will focus on connecting your existing web application to Facebook. In part 1 we connected your website to a Facebook app. In this post I’ll show you how to update a users status and profile. I’ll be using examples from RepresentMe a project built for the Apps For America contest. This is a standalone webapp that leverages Facebook to deliver its message to a wider audience.
Things you can update
Once you have an account linked to a Facebook uid you can send several different forms of updates:
- Status – This is short message telling what the Facebook User is doing. It is shown at the top of their profile and wall, and in their friends wall. It is the primary way that Facebook Users share information.
- Profile – A User can add a small box from each application to their profile. This is displayed to anyone who visits their profile.
- News Feed – This is similar to the status but allows you to include more formatting and a few basic html tags. Facebook has phased out the infinite sessions that this requires. At some point they may enable this again.
Publishing Status Updates
Publishing status updates from your app is a great way to let users show off what they do to their friends. RepresentMe publishes user’s votes to their status. We include a link back to the bill in question. Any of their friends will be able to see these messages and get involved too.
Step 1 – Authorize Updates
Before you can publish status updates the user must grant your application permission to publish them. This is done by including a FBML tag in your canvas template.
<fb:prompt-permission perms=”status_update”>
Grant permission for RepresentMe to update your status
<fb:prompt-permission perms=”status_update”>
This tag will generate a link in the page that will take the user through the process to approve or deny the request.
Step 2 – Initialize Facebook Object
Once your app is granted permission you can start updating the status. RepresentMe uses a script running in a cron job, more about that later. Since this is running outside Django the first thing the script needs to do is initialize the facebook object
#initialize facebook
fb = facebook.Facebook(FACEBOOK_API_KEY, FACEBOOK_SECRET_KEY)
Step 3 – Update Statuses!
Now we’ll iterate over all of our link objects. We’ll check for permission, then update their status
for link in FacebookLink.objects.all():
uid = link.facebook_id
str = 'I updated your status!'
if fb.users.hasAppPermission('status_update', uid):
fb.users.setStatus(str, False, True, uid=uid)
Step 4 – Don’t Spam
Facebook has guidelines for how often an application can update a User’s status. They limit applications to 10 updates per day. This is why our updates run as a script rather triggered directly by user actions. RepresentMe only updates Users’ statuses every 30 minutes with the last vote they placed. Rather than running the cron job every 30 minutes you can include a timestamp in your FacebookLink model to track updates. This allows updates to propagate soon after a user action, and spreads out the requests to Facebook.
# get all links that have not been updated in the past 30 minutes
delta = datetime.timedelta(0,0,0,0,30)
past_timeout = datetime.datetime.now() + delta
q = Q(feed_update_time__gt=past_timeout) | Q(feed_update_time=None)
links = FacebookLink.objects.filter(q)
Updating Profiles
Users can add a box from any application to their profile. This box can be displayed in either the wall, or the boxes tab. The differences are that the wall is more prominent, and the wall is much smaller (184x250px).
Step 1 – Set the profile content
The profile content is cached FBML or HTML and cannot contain Iframes. You should create a view or function that generates the content. RepresentMe is reusing the view handler for the Lawmakers By Zipcode widget with a template resized to fit within the wall profile. We’ll call the view using Httplib2 and set the profile content to the result.
def update_profile(fb, link):
# get zipcode from profile
profile = link.user.get_profile()
zip = profile.zipcode
# get content
conn = httplib2.Http()
url = 'http://repme.org/facebook/profile/?zip=%s' % zip
response, html = conn.request(url, 'get')
# set content for wall (profile_main) and boxes (profile)
uid = link.facebook_id
fb.profile.setFBML(uid=uid, profile_main=html, profile=html)
This example updates both profile boxes at the same time. Its optional to update both but this function will clear the cache on any box that isn't included. The user can select the box appear in either the wall or boxes tab, so its best to update the cache for both at the same time.
Step 2 - Add Section Button
Users must manually add your application to their profile. This authorization is granted using a FBML tag. Note this button will not be displayed untill you have set content in their profile
<fb:add-section-button section="profile" />
Step 3 - Adding When The User Installs You Application
The add section button only appears after you have set content for the user to add. Facebook recommends that you do not set the profile FBML until you have enough data to display. In our case RepresentMe has likely already collected that data. We'll set the profile FBML as soon as the user links their account. This way the user will immediately see the add section button.
@facebook.require_add()
def authorize(request):
...
if user.is_active:
# successful login, save facebook info!
link = FacebookLink()
link.user = user
link.facebook_id = request.facebook.uid
link.facebook_session = request.facebook.session_key
link.save()
# update their profile fbml so its ready,
# incase they add the app to the profile right away
fb = facebook.Facebook(FACEBOOK_API_KEY, FACEBOOK_SECRET_KEY)
update_profile(link, fb)
Step 4 - Script To Keep Profile Up To Date
Your application should keep the profile FBML cache up to date. RepresentMe uses a simple script in a cron job.
# get all links - this should only run every 30 mins
fb = facebook.Facebook(FACEBOOK_API_KEY, FACEBOOK_SECRET_KEY)
for link in FacebookLink.objects.all():
update_profile(fb, link)