On a recent Gatorade project, we built out individual profile pages for new Gatorade Players of the Year. With 600+ winners each year, content curation requires scalability. So we built a nifty form for the winners to use themselves.
Winners upload two photos, from either their computer or their social channels, along with some information about their athletic background.
From a development perspective, uploading an image directly from a user's computer is a lot more straightforward than leveraging social channels. However, many users have photos in Facebook and Instagram, and if we can simplify the upload process from manually finding the image, saving it, then uploading it (tedious and requires some page hopping), to login and click on your picture (doesn't leave the page), by all means we should.
We need to connect winners to their social photos on demand. Winners shouldn't have to login more than once, and should always get the appropriate permissions for photo access. How do we do this in a Web form?
This post focuses on Facebook; an Instagram follow up is forthcoming.
- Facebook provides a Javascript SDK.
- Our project's front-end codebase uses RequireJS modules, so integrating with Facebook's RequireJS Quick Start was a breeze.
- We used a dedicated
fb-setup.js
module definition for wrapping theFB
Javascript global with our own functionality. I recommend this approach, as it's often necessary to fill in the gaps specific to your application.
- Detect if on Winners Form page
- Wait for page load
- Conditionally
requirejs
the packaged page module when on the Winners form.- Package includes
fb-setup.js
, which depends on the SDK. - Facebook JS SDK is asynchronously loaded as a detected dependency.
- Upon SDK load,
fb-setup.js
& all dependents execute.
- Package includes
First, we setup a promise with new Q.defer()
. This deferred will resolve with the first successful login auth response from Facebook, and its promise will power a useful FB.loginOnce(callback)
custom method.
The Deferred object allows the application to detect login status from multiple sources:
- Existing login state upon page+SDK load, or
- Login state change upon successful Login Dialog flow.
Thus, in our application code, it's a simple call to FB.loginOnce
for anything that requires the user to be logged in. The fb-setup.js
+ RequireJS structure allows social integration to be streamlined for both the developers and users.
fb-setup
calls FB.init
then FB.getAuthStatus
with a custom callback. FB.getAuthStatus
doesn't check for permissions, so if a user is logged in we make call with FB.api('/me/permissions')
and compare against our scope
, as suggested in the docs. scope
includes "extended permissions".
If the user is logged in and has all the necessary permissions, the Deferred is resolve
'd (with the FB.getAuthStatus
response) and will immediately execute FB.loginOnce
callbacks.
A returning user will automagically log in, and will have nigh* immediate access to their photos in our app. Sweet!
*Small load time for third-party Facebook SDK + perms check.
If a returning user is logged out of Facebook, or if it's the user's first visit, they'll have to login.
When a user clicks on a Facebook upload field, FB.loginOnce
will prompt them to login via a pop-up Oauth Dialog. They will be asked for the scope
'd permissions in the dialog, then will return to the application. At this point, they should be connected to their profile and the app can display their albums.
Once again, subsequent FB.loginOnce()
will immediately execute provided callbacks.
A new user will start the login process on demand, and will only be prompted once before getting to pick their photos.
Developers have less headache with the async nature of Facebook, and users have less hassle getting to their data.
For some projects you won't even need Facebook's provided SDK, but then you must familiarize yourself with the internals of the Graph API and various Dialogs. The SDK can also easily embed Social Plugins.