It’s becoming more common for client’s to ask me to embed their web apps or sites into Facebook Canvas pages. If you aren’t familiar with these, it’s really just an IFrame within Facebook, which loads any URL that you provide to it.
The catch is that Facebook limits the width of the IFrame to a maximum of 810 pixels. If your site or app was developed in a responsive fashion, this usually works out well. If it wasn’t, you find yourself making various layout tweaks to make sure everything fits inside this width.
If you know in advance that your site will be used within a Facebook Canvas page, you’d be smart to follow the best practices for developing a responsive site. But you may not always have that insight, or you may need to retrofit an existing site to work with this narrowed width.
I find that the easiest approach is to create a separate stylesheet to adjust the site layout to fit within 810 pixels. Then, simply apply the stylesheet when your site is loaded within Facebook. It’s as simple as supplying a query string parameter, indicating that your site is loaded within a Facebook frame, i.e.
http://www.mysite.com/?fb=1
Complete website within a Canvas page.
If you need to embed an entire website into a Facebook Canvas page, the plot thickens a bit. While you can provide a query string parameter for the first page, what happens when the user clicks to another link. The query string parameter is dropped and the Facebook IFrame stylesheet isn’t loaded.
You could ensure that all links get the ?fb=1 parameter appended to them, but that’s tedious and sloppy.
We can leverage server-side session storage to help us out. The flowchart below will illustrate the process I used in a recent job.
And, since the site I did this for was developed in Zope, here’s a piece of sample code that about 1% of you will understand!
<tal:x condition="request/fb|nothing">
<tal:y define="dummy python: request.SESSION.set('fb', request.get('fb'))" />
</tal:x>
<link rel="stylesheet" id="fb-style" href="/assets/css/facebook-iframe.css"
tal:condition="python: request.SESSION.get('fb', request.get('fb', 0))" />
Busting out of the Facebook Canvas Page
So that’s fairly straightforward. But, what happens if your user wants to break free of the iFrame and load your website independent of Facebook?
You might think that simply supplying a link with a target of “_blank” or “_parent” would do the trick. But, we can’t forget about the session variable we put in place. It will still be active whether the site is within an iFrame or not.
While I’ve devised a plan to tackle this scenario, I have yet to implement it. So, take this as theory alone and use it only as a guide:
- On every page, use JavaScript to see if the website is being loaded in an iFrame.
If it is not in a frame, check to see if the stylesheet exists. If it does exist, reload the page with a different query string parameter.Now you’ll see why I included an ID attribute on the stylesheet link above.if (window === window.top && document.getElementById('fb-style')) { location.href = '?reset=1'; }
- If the reset query string parameter is detected, remove the fb session variable.