Implementing Custom Facebook Page Tabs for Your Users

You would think, for a massive organization with immense resources, Facebook would be able to create clear and concise documentation for their API’s. You would be wrong.

Here’s the scenario: You operate a hiring management platform where businesses can create a page and post their open positions. Now, you want to add this page from your application to the user’s Facebook Page so all of their visitors can see the available job openings. Facebook allows us to do this with custom Page Tabs.

This implementation will be specific to Python Django but the concept and general flow should be universally applicable.

 

Step 1 – Create a Facebook Page Tab app

Login to your Facebook developer account at https://developers.facebook.com and create a new Facebook App.

Once you have done this, navigate to the  Settings  tab for your app. Towards the bottom of the page, you will see an  Add Platform  button which will trigger this modal. Select  Page Tab.

In the settings for your Page Tab there will be a  Secure Page Tab URL  field which is where you will enter the URL the iFrame will load.

ex. http://www.yourdomain.com/fbpagetab

 

Step 2 – Create a Page for the iFrame to Load

This will probably be the most Django-specific section of the guide, but there are still some important bits here, so don’t tune out just yet. (Yes – I’m looking at you Rails devs).

When Facebook loads your page for the iFrame, it sends a POST request with a signed_request param that contains the ID of the page that made the request. The function below parses this param and returns a dictionary containing the ID.

def parse_signed_request(signed_request):

    l = signed_request.split('.', 2)
    encoded_sig = l[0]
    payload = l[1]

    sig = base64_url_decode(encoded_sig)
    data = json.loads(base64_url_decode(payload))

    if data.get('algorithm').upper() != 'HMAC-SHA256':
        print('Unknown algorithm')
        return None
    else:
        expected_sig = hmac.new(settings.PAGE_TAB_FACEBOOK_SECRET, msg=payload, digestmod=hashlib.sha256).digest()

    if sig != expected_sig:
        return None
    else:
        print('valid signed request received..')
        return data

Once we can parse the Facebook Page’s ID from the signed_request, we can match it to the ID that we’ll retrieve and save in Step 3.

Note: The page that Facebook loads into the iFrame must be CSRF exempt, and the X-Frame-Options header should NOT be set.

@csrf_exempt
@xframe_options_exempt
def facebook_tab(request):
    signed_request = request.POST.get('signed_request')
    if signed_request:
        data = parse_signed_request(signed_request)
        try:
            business = Business.objects.get(facebook_page_id = data['page']['id'])
        except:
            return HttpResponseRedirect('/')
        else:
            return render(request, 'mytemplate.html', {'business' : business})
    else:
        return HttpResponseRedirect('/')

 

Step 3 – Retrieve the User’s Facebook Page ID

Using your user’s Facebook page URL and the Graph API, you can get the user’s Facebook page ID and save it. We are using the unofficial Facebook-SDK library for this (found here).

def set_facebook_page_id(request):
    facebook_page_url = request.POST.get('facebook_page_url')
    if facebook_page_url:

        url = facebook_page_url+'?access_token='+settings.FB_ACCESS_TOKEN
        facebook_page_id = facebook.GraphAPI().get_object(url)
        facebook_page_id = facebook_page_id['id']
        
        ### Save facebook page ID

With the user’s Facebook page ID saved we now have all of the pieces to allow the user to add our custom Page Tab to their page.

Step 4 – Enable Your User to Add The Page Tab to Their Page

This last step is very simple, you just need to direct the user to this URL

http://www.facebook.com/dialog/pagetab?app_id=YOUR_APP_ID&next=YOUR_URL

Substitute in the app ID for your Page Tab and the Secure Page Tab URL we entered in Step 1. The user will be prompted by Facebook to add your Page Tab to their page.

I hope this guide was helpful. Feel free to leave feedback/questions in the comments. Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *