Why is the user experience for adding Facebook apps so poor?

Posted: January 12th, 2010 | Author: | Filed under: posts | Tags: , , , | No Comments »

A friend linked me to a random promotions app on Facebook the other day and it stopped me in my tracks for a moment.  Unlike most apps I’ve seen, the first screen was something very interesting – it was actually inside the application itself and was not the not the lovely “Allow Access” screen that Facebook users are accustomed to.

This made me wonder – pretty much most of the biggest Facebook apps I can think of ask for permission before letting you do anything.  I understand why Facebook is protecting profile information, but as a developer, you can configure your initial app screen so as not to require permission to access content.  The promotions app did this and we”ve set it up for our application.

So, the question is – why are so many huge Facebook app developers happy with the poor user experience of having the “Allow Access” screen being the first thing that users encounter with their application?  Why not show a screen that gives you a better idea of what the app is and then if the users actually wants to use the app, then they would request access.  Is this simply a ploy for the publishers to get more “active users” and thus boost themselves in the AppData standings?  Or are Facebook users quickly becoming numb to releasing their private information and the age of privacy is really over, as Facebook’s Zuckerberg recently claimed?

FYI – for Rails developers using Facebook, it’s pretty easy to not require the Allow Access screen on your welcome controller or whatever serves as your landing screen.  Just skip the Facebooker ensure_app_installed before_filter and don’t make calls that try to access the user’s information:

skip_before_filter :ensure_app_installed

Collaborative Team Facebook Development

Posted: January 10th, 2010 | Author: | Filed under: posts | Tags: , , , , | No Comments »

For as much as has been written regarding developing Facebook applications with Rails (which isn’t that much considering the staggering popularity of Facebook and Rails), there is even less written on developing Facebook applications in a team environment.

There are a couple of potential strategies. One of the few articles out there describes the challenges in developing apps as a team:

This sets up some challenges for a development team. First off, your application probably relies on Facebook services, meaning it can only be fully tested from within Facebook. This implies that the external Facebook server needs to be connected to your development server. Since many Rails developers run off their own development machine behind a firewall, this is potentially awkward. Similarly, the fact that the Facebook application has a single URL mapping makes it difficult for multiple developers to work on the same application without tripping over each others” work.

The author goes on to discuss the solution that their team is using, consisting of a series of Rake tasks and a staging server to facilitate testing in a team environment.

The other option, which is supported natively by Facebooker, is using an SSH tunnel from the local development workstation to an intermediary server and having the Facebook app point at that server. (This necessitates having an understanding IT team that doesn’t lose that much sleep over some open ports..) The SSH tunnel is discussed by many of the Facebooker tutorials available (here, here, and here).

We adapted the SSH tunnel strategy to our team environment. Each developer will have a development Facebook app and then will point that to their assigned port on our staging server. Then they can tunnel into the staging server from their local workstation. In this way, everyone can be testing their work independently without needing to coordinate deploys through to a staging and central test application. The below diagram illustrates this.

Ok, so we have our plan, but how to go about setting this up? In particular, the other tutorials don”t talk about what you do or do not have to do on the server side. In truth, the tunnel is fairly easy to configure and seems to be working well.

On the server side, the key is making sure that the ports you need aren”t blocked and are accessible for purposes of the tunnel. No need to configure virtual hosts or mongrels – the staging server is a simple relay. You will probably need to configure SSH to turn on GatewayPorts. That”s just a couple of quick steps:

  • sudo vi /etc/ssh/sshd_config
  • Find the line GatewayPorts if it”s there.
  • Change or add to: GatewayPorts yes
  • Restart SSH: sudo /etc/init.d/ssh restart

(based on other blog posts I came across, be sure to indicate GatewayPorts yes and not GatewayPorts clientspecified)

Now, via Facebook”s Developers application, each developer should configure an application for testing purposes. Set the Canvas Callback URL to http://your.stagingserver.com:####/ (Facebook requires that you have a trailing slash) and you should be good to go. Depending on your application, you may need to configure other settings (other callback URLs or iFrame/FBML, but the canvas callback URL is the primary setting. Make a note of the API key and the secret key.

Finally, we can setup the tunnel. Go into the Rails app that you pulled down from your Git repp and edit config/facebooker.yml. Add in the API key and secret key from your development application you just configured. For the canvas page name, enter the name of your application, as configured on Facebook. Then change the callback URL to the same URL the app is configured for: http://your.stagingserver.com:####/ (again, trailing slash!). Then enter the SSH username and hostname for your staging server, save the file, and you should be good to go.

At this point, you should be able to start your development server (ruby script/server) and then start the tunnel (rake facebooker:tunnel:start). If you’re on Windows, be sure to run these commands through Cgywin. At this point, you should be able to go to http://apps.facebook.com/yourappname and see your development app. While the app is loading, you should also see the SSH command window and the Ruby Webrick/Mongrel window showing the incoming connection and the Rails system handling the requests.


Rails Facebook Development – Sharing some code for tracking active/inactive users…

Posted: January 9th, 2010 | Author: | Filed under: posts | Tags: , , , , | 14 Comments »

The next version of FanGamb will be a Facebook app.  It’s not a 1:1 translation of the current game to Facebook – we’ll be incorporating many of our game design learnings from running the first version of the game for NFL/NCAA football this fall. Since FanGamb is a Rails app, we’ve been working on setting up a collaborative development process around building Facebook apps in a team environment.  I’ll post more on this process to come, but for now, I wanted to contribute some code from our Rails Facebooker-based (that’s the main Rails Facebook API plugin) app.

Documentation on Facebooker is a little light, so there isn’t a whole lot to go on.  There is a fairly active Google group, though, and a list of the methods, so we’re not totally in the dark.  But as far as hunting for best practices and example code, it’s been a lot of trial and error.

One of the things that we wanted to implement in our application is making sure we know which users have our app installed.  It’s pretty common to store the user ids in the app’s database – you need to be able to link it to other data elements that you’re storing for them.  However, Facebooker doesn’t by default help you keep that user model in sync with which users actually have the app installed on Facebook.  You can tell which of a user’s friends have the app, but not a master list.  When you have an active Facebook user session, you can look at User#has_added_app, but we want to be able to tell if a user has the app added even if they aren’t on the app at that moment (for things like leaderboards, etc.).

So, we need to be able to track when a user uninstalls the application and set their user record to be inactive.  Facebook has the post_authorize and post_deauthorize call backs for this tracking.  As I said, there isn’t a lot of sample Facebooker code out there, so if you’re looking to implement the same thing, here are our callback actions for you to utilize.

The first thing you’re going to want to do is probably put your callback actions in a separate controller, so that you can limit which filters are run on the controller.  Facebooker has a before filter ensure_app_installed (suggested for your application_controller) which basically forces a user trying to use the app to install it.  This won’t work for your post_deauthorize action, so you need to turn that off:

skip_before_filter :ensure_app_installed, :except => :post_authorize

Also, because Facebook posts to these URLs, Rails treats it as a form submission and will try to verify the authenticity token.  So you need to turn that off for both post_authorize and post_deauthorize:

skip_before_filter :verify_authenticity_token

With this setup, you’re able to create the rest of the methods.  Here’s the stub code:

class CallbacksController < ApplicationController
  skip_before_filter :ensure_app_installed, :except => :post_authorize
  skip_before_filter :verify_authenticity_token
  def post_authorize
    if request.post?
      #do something here
      render :nothing => true
    end
  end
  def post_deauthorize
    if request.post?
      #do something here
      render :nothing => true
    end
  end
end

One important point – the above code will work, but we can’t forget to verify the signature to ensure that the request is actually from Facebook, since these actions are outside of the Facebooker plugin (which typically handles this validation).

Looking at the Facebook development wiki, you can see some sample code for RFacebook on how to validate this.  Implementing this, our callback controller now looks like the following:

class CallbacksController < ApplicationController
  skip_before_filter :ensure_app_installed, :except => :post_authorize
  skip_before_filter :verify_authenticity_token
  def post_authorize
    if request.post?
      if verify_uninstall_signature
        #set user's has_app indicator to 1 to indicate active
      end
    end
    render :nothing => true
  end
  def post_deauthorize
    if request.post?
      if verify_uninstall_signature
        #set user's has_app indicator to 0 to indicate inactive
      end
    end
    render :nothing => true
  end
  private
      #based on http://wiki.developers.facebook.com/index.php/Post-Remove_URL
      def verify_uninstall_signature
        signature = ''
        keys = params.keys.sort
        keys.each do |key|
          next if key == 'fb_sig'
          next unless key.include?('fb_sig')
          key_name = key.gsub('fb_sig_', '')
          signature += key_name
          signature += '='
          signature += params[key]
        end
        signature += FACEBOOK_YAML['secret_key']
        calculated_sig = Digest::MD5.hexdigest(signature)
        if calculated_sig != params[:fb_sig]
          logger.warn "\nWARNING :: potential spoofing :: expected signatures did not match"
          logger.info "\nSignature (fb_sig param from facebook) :: #{params[:fb_sig]}"
          logger.info "\nSignature String (pre-hash) :: #{signature}"
          logger.info "\nMD5 Hashed Sig :: #{calculated_sig}"
          #check to see if ip variables are nil
          if not request.env['HTTP_X_FORWARDED_FOR'].nil? and not request.env['HTTP_X_REAL_IP'].nil?
            ip = request.env['HTTP_X_FORWARDED_FOR'] || request.env['HTTP_X_REAL_IP']
          else
            ip = request.remote_ip
          end
          logger.info "\nRemote IP :: #{ip}"
          return false
        else
          #logger.warn "\n\nSUCCESS!! Signatures matched.\n"
        end
        return true
      end
end

Get the code in a Gist here.

Note the one line that references FACEBOOK_YAML[‘secret_key'].  This should refer to your secret Facebook key.  We put this into the initializer block in environment.rb:

#load facebooker configuration for usage
facebook_config = File.join(RAILS_ROOT, 'config', 'facebooker.yml')
FACEBOOK_YAML = YAML::load(ERB.new(File.read(facebook_config)).result)[RAILS_ENV]

Phew!  That should do it – you should now be able to track whether your users have the app installed or not via the post callbacks.  Hopefully, this will help someone looking to keep track of active/inactive users in their Rails Facebook app!

Big props to my co-founder Alan deLevie who’s figured out a big chunk of this Facebooker stuff for the FanGamb team.

EDIT: typo fixed.  Thanks Sting Tao!