Back to News for Developers

How-To: Subscribing to data changes using the Real-time Updates API

January 31, 2012ByBruce Hazan

A common question we get from developers is how to keep information of Users or Pages using their apps up to date. We wanted to share some of the best practices that can improve the reliability and performance of apps you write on Facebook.

We often see developers querying the Graph API each time a User logs in to their apps to fetch information and update their records. This presents several issues and has a huge hit on performance.

Instead, we encourage you to use the Real-time Updates API that we designed especially for this purpose, allowing developers to subscribe to changes in data in Facebook. Rather than polling Facebook’s servers, your app can then cache data and receive updates whenever the data changes.

For example, many apps rely on a User's location to fetch and display relevant information, it is very important that this data stays up to date on the app’s backend.

Real-time updates allows you to set up a subscription on the location field of the User object, whenever that field changes, Facebook will make an HTTP POST request to a callback URL you specified by with a list of changes.

You can currently subscribe to updates for these types of objects:

  • User – Get notifications about particular fields and connections corresponding to User objects in the Graph API.
  • Permissions – Get notifications when Users change the permissions they afford your applications. The fields are like those in the corresponding FQL table.
  • Page - Get notifications when Pages that have installed your app as a Tab change their public properties.
    Note that the page topic is only used for subscribing to changes to public attributes of the page (like name, category, picture etc). This is the same information that is returned by the Graph API call https://graph.facebook.com/. However, you can subscribe to the page's feed in the same way you subscribe to a User's feed - the subscription topic should be User and the subscription field should be feed

Below is PHP Sample code that sets up an endpoint that will receive both GET (for subscription verification) and POST requests (for actual change data).

<?php

  $verify_token = 'YOURVERIFYTOKEN';

  if ($_SERVER['REQUEST_METHOD'] == 'GET' && isset($_GET['hub_mode'])
    && $_GET['hub_mode'] == 'subscribe' && isset($_GET['hub_verify_token'])
    && $_GET['hub_verify_token'] == $verify_token) {
      echo $_GET['hub_challenge'];
  } else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $post_body = file_get_contents('php://input');
    $obj = json_decode($post_body, true);
    // $obj will contain the list of fields that have changed
  }

?>

Once this endpoint is set up, you will need to make a POST request to the actual Real-Time updates API to subscribe to a field.

<?php

  $app_id = 'YOUR_APP_ID';
  $app_secret = 'YOUR_APP_SECRET';
  $app_url = 'http://YOURAPPURL';
  $fields = 'location';
  $verify_token = 'YOURVERIFYTOKEN';

  // Fetching an App Token
  $app_token_url = 'https://graph.facebook.com/oauth/access_token?client_id='
                   .$app_id.'&client_secret='.$app_secret
                   .'&grant_type=client_credentials';
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $app_token_url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  $res = curl_exec($ch);
  parse_str($res, $token);

  if (isset($token['access_token'])) {
    // Let's register a callback
    $params = array(
      'object'
        =>  'user',
      'fields'
        =>  $fields,
      'callback_url'
        // This is the endpoint that will be called when
        // a User updates the location field
        =>  $app_url . '/index.php?action=callback',
      'verify_token'
        =>  $verify_token,
    );

    curl_setopt($ch, CURLOPT_URL, 'https://graph.facebook.com/'
                                  .$app_id.'/subscriptions?access_token='
                                  .$token['access_token']);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
    $res = curl_exec($ch);
    if ($res && $res != 'null') {
      print_r($res);
    }

    // Fetch list of all callbacks
    curl_setopt($ch, CURLOPT_POST, 0);
    $res = curl_exec($ch);
  }
  if ($res && $res != 'null') {
    print_r($res);
  }
  curl_close($ch);

?>

The code above should return a similar object listing current subscriptions:

{
   "data":[
      {
         "object":"user",
         "callback_url":"http:\/\/YOURAPPURL\/index.php?action=callback",
         "fields":[
            "location"
         ],
         "active":true
      }
   ]
}

It’s important to note that for security reasons, the POST request made by Facebook’s servers to your endpoint will never actually contain the data that changed but only the field.

This is what a query from Facebook's servers to your endpoint may look like:

{
   "object":"user",
   "entry":[
      {
         "uid":"499535393",
         "id":"499535393",
         "time":1326210816,
         "changed_fields":[
            "location"
         ]
      }
   ]
}

Once your endpoint gets called you can either query the Graph API immediately to fetch the new information or schedule it for a later call (next user login for example).

You can find more information about the Real-Time Updates API here.


Tags: