Tutorial: Post to multiple Facebook wall or timeline in one go using Graph API batch request

Many Facebook application developers might have come across a situation where they need to post something to many pages, groups or friends. If we need to post on 50 walls and go by the traditional method of posting one by one, we would need 50 requests to Graph API. Each request will take its time and the webpage will take ages to load. In such situation Batch Request of Graph API comes to our rescue. All types of request to Graph API (GET, POST, DELETE etc) can be clubbed together to form a batch request. So we can post a status, delete a comment, like a post or whatever you wish, just by sending one request to Facebook. In this tutorial we will be using Facebook PHP SDK for the implementation. We will create a webpage that lists all your friends, groups and pages that you liked. You can post custom messages, pictures or links to selected walls or groups.

If you are looking for a basic tutorial on Facebook connect or wish to know the basics of Graph API, please head to: Tutorial: Integrate Facebook Connect to your website using PHP SDK

NOTE: Even though you will be able to post to Pages and Groups, this app will NOT be able to post to friend’s wall as Facebook has deprecated post to friend’s wall via API, and the reason they state is:
Post to friends wall via the API generate a high levels of negative user feedback, including “Hides” and “Mark as Spam” and so we are removing it from the API. If you want to allow people to post to their friend’s timeline from your app, you can invoke the feed dialog. Stories that include friends via user mentions tagging or action tagging will show up on the friend’s timeline (assuming the friend approves the tag).
Refer Facebook blog for details.

July 01, 2013 Update: This script is outdated. Please find the improved script at Updated: Post to multiple facebook pages or groups efficiently (v2.0)

Step 1 to 4 : Registering your application and Downloading PHP SDK

The primary thing to do is to register your facebook application and obtain an App ID and App secret. Then you will need to download the PHP SDK from Facebook Developer website. If you are a newbie or not sure how to do it, please refer the article Tutorial: Integrate Facebook Connect to your website using PHP SDK and follow Step 1 to 4.

Creating the access file (fbaccess.php)

Now we will create a file named ‘fbaccess.php’ which will be the heart of our web application. All the Facebook API calls and requests will be in this file.

Step 5 to 7 : Application Configuration, Creating app instance and User authentication

Please follow Step 5 to 7 form the article Tutorial: Integrate Facebook Connect to your website using PHP SDK.

The above steps will give you a code similar to:

//Application Configurations
$app_id        = "Your App ID goes here";
$app_secret    = "Your App Secret goes here";
$site_url      = "Your Site URL goes here";
 
try{
    include_once "src/facebook.php";
}catch(Exception $e){
    error_log($e);
}
// Create our application instance
$facebook = new Facebook(array(
    'appId'     => $app_id,
    'secret'    => $app_secret,
    ));
 
// Get User ID
$user = $facebook->getUser();
 
if($user){
    try{
        // Proceed knowing you have a logged in user who's authenticated.
        $user_profile = $facebook->api('/me');
    }catch(FacebookApiException $e){
        error_log($e);
        $user = NULL;
    }
}

Step 8:

Variable $user will have the user ID if we have an authenticated user. In that case, we will need to create the logout URL. If we have a user who is not authenticated, then we need to generate the login URL. We use the function getLoginUrl() and getLogoutUrl() to generate login and logout URL respectively. In our demo we will need to include only ‘publish_stream’ and ‘user_groups’ as scope parameters. With ‘publish_stream’ permission we can publish a post to your friend’s timeline or to a page that you liked. ‘user_groups’ permission grants information about the Facebook groups in which the application user is a member.

if($user){
    // Get logout URL
    $logoutUrl = $facebook->getLogoutUrl();
}else{
    // Get login URL
    $loginUrl = $facebook->getLoginUrl(array(
        'scope'            => 'publish_stream user_groups',
        'redirect_uri'     => $site_url,
        ));
}

Step 9:

In this step we will retrieve the logged in user’s details, his friend list, his groups and also the pages that he liked. We will retrieve these 4 items with just one request to Facebook Graph API using batch request. If we were to go by the normal method of not using the batch API we will need 4 requests to Graph API. With 4 requests the details can be retrieved as shown below.

$user_info         = $facebook->api('/'.$user);
$friends_list      = $facebook->api('/'.$user.'/friends');
$groups            = $facebook->api('/'.$user.'/groups');
$pages             = $facebook->api('/'.$user.'/likes');

Using batch request will cut down the requests from 4 to 1. For a batch request first step is to save the method calls into an array. We make an array named $queries and push each of the 4 requests into it.

$queries = array(
    array('method' => 'GET', 'relative_url' => '/'.$user),
    array('method' => 'GET', 'relative_url' => '/'.$user.'/friends'),
    array('method' => 'GET', 'relative_url' => '/'.$user.'/groups'),
    array('method' => 'GET', 'relative_url' => '/'.$user.'/likes'),
    );

Then we will POST the array as a single request as shown below.

try{
    $batchResponse = $facebook->api('?batch='.json_encode($queries), 'POST');
}catch(Exception $o){
    error_log($o);
}

The request will return the values that we requested indexed in the order of the array as a JSON. We will get the required user info, friends list, groups and pages by decoding the JSON.

$user_info         = json_decode($batchResponse[0]['body'], TRUE);
$friends_list      = json_decode($batchResponse[1]['body'], TRUE);
$groups            = json_decode($batchResponse[2]['body'], TRUE);
$pages             = json_decode($batchResponse[3]['body'], TRUE);

Step 10:

Now we can write the code for the batch posting. Here we assume that the content to be posted and the IDs of friends, groups and pages where the matter need to be posted is available in the $_POST variable. $_POST variable is a collection of key => value pairs and we assume that each IDs in the variable has a ‘id_’ prefix in the key. Thus by checking for the prefix ‘id_’ we can identify the User IDs, Groups IDs and Page IDs where the content is to be posted.

The basic method is same as in Step 9. First we need to make an array and push each and every Graph API request to the array. Then we will post the array as a single request to graph API using the function api().

$batchPost[] = array(
    'method' => 'POST',
    'relative_url' => "/{ID1}/feed",
    'body' => http_build_query($body) );
$batchPost[] = array(
    'method' => 'POST',
    'relative_url' => "/{ID2}/feed",
    'body' => http_build_query($body) );
$batchPost[] = array(
    'method' => 'POST',
    'relative_url' => "/{ID3}/feed",
    'body' => http_build_query($body) );
 
$multiPostResponse = $facebook->api('?batch='.urlencode(json_encode($batchPost)), 'POST');

Here $body is an array which has many key => value pairs. We use the function http_build_query() to URL encode the array. http_build_query() generates a URL-encoded query string from the associative (or indexed) array provided.

json_encode() returns a string containing the JSON representation of the array. We need to pass this string to the api() function for the batch request. As we made the string from multi-dimensional arrays there may be some issues like posting blank messages to user’s wall or timeline. The API request is similar to a URL query. So we need to encode the string to match the format. urlencode() is used for encoding a string to be used in a query part of a URL. This will solve the issue of posting blank data to the timeline.

Now we will modify the code to suit our application. First we will generate the array $body. We will get the data to be posted to user’s timeline from the $_POST variable. In this particular demo we will use just 6 of many possible post fields. The 6 fields that we use are message, link, picture, name, caption, and description. If you wish to have more fields please refer Facebook documentation for information on all possible fields.

A picture is worth a thousand words. So please see the images below to know what the fields are. The first pic shows the legacy Facebook wall and the second one shows how the post will look in the timeline. Of the 6 fields that we use 5 are shown there. The sixth one is ‘link’ field. In the ‘link’ field we specify the hyperlink for the ‘name’ field.

Sample post with details

Sample Wall post with field details

Sample Post Timeline

Sample Timeline post with field details

Now we need to generate Graph API request for each and push them to an array. Each request will need the ID of the user, group or page. For each key => value pair in the $_POST variable, we check for the prefix ‘id_’ in the key and if found we can confirm that the value associated with the key is an ID. For each IDs we generate Graph API request and push it to $batchPost array.

Another important point to note is that Facebook currently limits the number of batch request to 50. So you can do a maximum of 50 requests at once. So if you have more than 50 requests then you will have to do multiple batch requests. In our application, once the $batchPost array accumulates 50 requests we do a batch request and then flushes the array.

if(isset($_POST['submit'])){
    $body = array(
        'message'        => $_POST['message'],
        'link'           => $_POST['link'],
        'picture'        => $_POST['picture'],
        'name'           => $_POST['name'],
        'caption'        => $_POST['caption'],
        'description'    => $_POST['description'],
        );
 
    $batchPost=array();
 
    $i=1;
    foreach($_POST as $key => $value) {
        if(strpos($key,"id_") === 0) {
            $batchPost[] = array(
                        'method' => 'POST',
                        'relative_url' => "/$value/feed",
                        'body' => http_build_query($body)
                        );
            if($i++ == 50) {
                try{
                    $multiPostResponse = $facebook->api(
                        '?batch='.urlencode(json_encode($batchPost)),
                        'POST'
                        );
                }catch(FacebookApiException $e){
                    error_log($e);
                    echo("Batch Post Failed");
                }
                unset($batchPost);
                $i=1;
            }
        }
    }
    if(isset($batchPost) && count($batchPost) > 0 ) {
        try{
            $multiPostResponse = $facebook->api('?batch='.urlencode(json_encode($batchPost)), 'POST');
        }catch(FacebookApiException $e){
            error_log($e);
            echo("Batch Post Failed");
        }
    }
}

‘fbaccess.php’ is now complete and we will proceed to ‘index.php’.

Creating the main webpage (index.php)

Step 11:

In ‘index.php’, the first thing to do is to check whether the user is authenticated or not. If we have a user who is not authenticated, display a login button with the login URL. If we have a login user, we will display a form which has provision for entering custom data to be posted. It will also have option to select the users, groups and pages where the user wishes to post the data.

form with input text fields

Create 6 input text fields with names – message, link, picture, name, caption, and description. Then display the names of friends, pages and groups from the arrays $friends_list, $pages and $groups respectively and associate a check box with each of them. Name the check boxes with prefix ‘id_’ and ID of the object (user, page or group) as the value for the check box. And now add a submit button with name ‘submit’. In this demo script I have used an “image” input type to submit the form. For the PHP processing script to work we need to add a “_x” suffix to the field name in the processing PHP code, if we use an “image” input type to submit the form.

In the demo, I have added few extra functionalities like select all, error messages etc. I have also added a variable $limit which limits the number of displayed entries in each category, that is, friends, pages and groups. I have limited the number to 500 in the demo. You can just change the value of $limit and specify the limit for your code. You can download the complete source of the demo from here. Please feel free to comment if you find any mistakes or improvements to the script.

NOTE: Even though you will be able to post to Pages and Groups, this app will NOT be able to post to friend’s wall as Facebook has deprecated post to friend’s wall via API, and the reason they state is:
Post to friends wall via the API generate a high levels of negative user feedback, including “Hides” and “Mark as Spam” and so we are removing it from the API. If you want to allow people to post to their friend’s timeline from your app, you can invoke the feed dialog. Stories that include friends via user mentions tagging or action tagging will show up on the friend’s timeline (assuming the friend approves the tag).
Refer Facebook blog for details.

July 01, 2013 Update: This script is outdated. Please find the improved script at Updated: Post to multiple facebook pages or groups efficiently (v2.0)