You are here:  Home  /   BLOG  /   Action Links – Facebook Developers

Action Links – Facebook Developers

Action Links

Open Graph Actions are the high-level “interactions” users can perform in your app. When these actions are published, the activities may appear in a users’ Timeline or their friends’ News Feeds and Ticker. Open Graph Action Links show up alongside the Like and Comment actions in any Open Graph story allowing friends to quickly take action in response to a story without having to navigate away from that story. This in turn will drive more distribution to your app with fewer user clicks.

Story with Action Link:

Story after Action Link Clicked:

Action Links can be configured for a built-in action type or a custom action type. When the user takes the action, you should then publish a story against that action. The resulting Action Link story may be seen in the user’s Timeline, on their friends’ News Feed and Ticker.

Note that at this time action links are currently not available in mobile.

In this document we will cover the following:

How It Works

We will walk through an example flow to demonstrate how action links work and highlight the integration points.

Example Flow

The example flow we will use is based on a cooking app that allows users to “cook a recipe”. Here is an example flow for how an action link can be triggered and processed:

  1. User 1 takes an action on the app to say that they “cooked a recipe”. The app allows users to also “save” recipes, the “cook” action is configured to have an associated action link of “save”. This is due to the fact that a user can cook a recipe and save a recipe.
  2. User 2 sees the story that User 1 “cooked a recipe”. In that story, at the bottom next to the “Like” and “Comment” they also see, “Save This Recipe”.
  3. When User 2 clicks on “Save This Recipe”, Facebook will check if the user has installed the app or not.
    • If the user has installed the app: Facebook will make a server-to-server call to the https:// endpoint specified in the App Dashboard for that action link. The call will contain a signed_request parameter with a payload that includes the following data:
      • A valid access_token for User 2.
      • The user Id for User 2.
      • The action type in the form <APP_NAMESPACE>:<ACTION>.
      • The action Id (optional).
      • The object URL.
      • A sample signed_request is shown below:
        { "objects": [ { "url": "http:\/\/\/nyccookbook\/pizza.html" } ], "action_link": { "type": "nyccookbook:save" }, "actions": [ { "id": "3936222850404" } ], "algorithm": "HMAC-SHA256", "expires": 1335830400, "issued_at": 1335823862, "oauth_token": "12345678901234567890", "user": { "country": "us", "locale": "en_US" }, "user_id": "621273" }
    • If the user has not installed the app: The user will be redirected based on whether Authenticated Referrals are enabled for your app:
      • If enabled, the permissions dialog will be displayed to allow the user to install your app. After the app is installed the user will be redirected to the object URL.
      • If disabled, the user will be redirected to the object URL.
      • When directed to the object URL, the following data will be provided:
        • The action Id in the fb_action_ids parameter.
        • The action type in the form <APP_NAMESPACE>:<ACTION> in the fb_action_link_type parameter.
  4. The endpoint configured to handle the action link can return one of two messages:
    • “success=>true”:
      { "success":"true" }
    • “redirect=><some url>”: Example
      { "redirect":"http:\/\/\/somepage\/" }
    • If the message is “success=>true”::
      1. The endpoint should publish a story using the “save” action against the same object (“recipe”) on behalf of User 2.
      2. Then return a JSON encoded “success” message.
      3. User 2 will simply see the action link text of “Save This Recipe” change to “Saved” (the past tense definition for the action “save”) in the story they clicked.
      4. Note: if the user were to refresh that story or see it again, they would no longer see an action link for “Save This Recipe” because a story has been published for them already (“saved a recipe”).
    • Else if the message is “redirect=>“::
      1. The endpoint may decide to redirect the user from Facebook possibly to install the app first or provide some additional context about the action. To do this the endpoint should respond with a JSON encoded “redirect” message along with the redirect_url.
      2. User 2 will then see a dialog box telling them that they can visit your app to continue the process. Since the user is supposed to stay on Facebook, this flow is considered an error case.

Suppressing Action Links

If you have configured action links in the App Dashboard you can suppress the action link appearing for a particular story. To do this when you publish the action pass in no_action_link=true.

Integration Points

These are the steps that you need to do to properly handle action links:

  • Configure the action link to action association using the App Dashboard.
  • Implement the server endpoint that will handle the action link calls.
  • Optionally configure Authenticated Referrals if you want to pre-authorize users who click on an action link and have not installed the app.

We will walk you through the configuration steps and also show some sample code for an action link handler.


Action Links configuration is done through the App Dashboard, by associating one action with another action. You must configure each action so they are associated with the same object.

  1. If you have not already done so, create a new action to represent your action link. In our previous example we would have added a “save” action.
  2. Edit the main action, e.g. the “cook” action in our example to make the association. Click on the Advanced section. Fill in the Linked Action field using the type-ahead and selecting your action link, e.g. “save” in our example.
  3. Add the endpoint information for your action link. This is the endpoint that will be called when the action link is clicked in a story. This endpoint must match the domain of the app and must be a valid https:// endpoint. Fill in the Action Link URL field in the Advanced section for the main action, e.g. the “cook” action in our example.

You may want to change the “Imperative Tense” displayed for an action link. By default the imperative tense is set to be the same as the “Present Tense” setting. So in our example, the action link is “save” and the imperative tense we want is “save”. So we do not need to change the default setting.

Note: If you already have Open Graph action types that have been approved then your “Imperative Tense” settings will match your “Present Tense” settings and at this time you will not be able to change the setting.

Testing Your Implementation

  1. After configuring your actions and setting the correct imperative tense and setting the action and endpoints, you’re ready to start testing
  2. As a developer, post a story using the configured action.
  3. As the same developer, goto your profile and then to your Activity Log.
  4. You will see the story you just posted; click on the timestamp on the left to show what the story looks like in News Feed
  5. You should see that the story has an action link in it at the bottom of the post next to Like, Comment and Unfollow this Post.
  6. Click the Action Link, which will then call the endpoint you configured server-to-server.
    1. On your server, simply have the endpoint returned a json encoded “success” message
    2. In the story, you will see the Action Link text change to the past tense.
    3. As a developer, if there is an issue with the endpoint or with the returned value, you will get an error message in the story UI with the error details.


  • Once you publish a story using the Imperative Tense action for a given object for a user, that user will no longer see any Action Link text in future stories. While you’re testing, to re-enable that Action Link test, you can simply find the action_id for the Action Link story and perform an http DELETE to endping<action_id> which will return “true”. If you then refresh any story that has an Action Link configured, you will once again see the Action Link at the bottom of the story.
  • In the example above, you would DELETE the “saved a recipe” story, which is the Action Link story to the main story “cooked a recipe”.

Frequently Asked Questions

Q: What happens if I don’t publish a story when a user clicks on the action link?
A: Each time the user comes back to that story, they will see the option of clicking the Action Link. If you don’t publish a story to stop this, that will become annoying to the user and lead to a bad experience for them.

Q: Do Action Links display in Mobile News Feed?
A: We have not yet enabled this, but yes, we will be shortly.

Q: Can I create aggregations from my Action Link stories?
A: Yes, Action Link stories are exactly the same type of stories as any other story and can have complex properties and interesting aggregations.

Q: Do I need to have an https endpoint for my action link?
A: Only if you’re not in sandbox mode. If you’re developing and have sandbox mode turned on, then our system will simply hit the http:// version of the endpoint you’ve entered.

Sample Code

Here is sample code for an action link endpoint. This corresponds to our sample app where the endpoint processes the incoming data, extracts the “recipe” object and publishes the “save” action. Finally the endpoint returns a “success=>true” JSON response.

<?php  $app_id = 'APP_ID'; // Your app Id $app_secret = "APP_SECRET"; // Your app secret  // Function to parse an incoming signed request and get the // data function parse_signed_request($signed_request, $secret) { list($encoded_sig, $payload) = explode('.', $signed_request, 2);  $sig = base64_url_decode($encoded_sig); $data = json_decode(base64_url_decode($payload), true);  if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') { error_log('Unknown algorithm. Expected HMAC-SHA256'); return null; }  // Check the signature $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true); if ($sig !== $expected_sig) { error_log('Bad Signed JSON signature!'); return null; } return $data; }  // Helper function for parsing signed request function base64_url_decode($input) { return base64_decode(strtr($input, '-_', '+/')); }  // Variable to hold success result $success_result = 'false';  // Parse the signed request $parsed_data = parse_signed_request($_REQUEST['signed_request'],$app_secret); if ($parsed_data != null) { // Get the access token $access_token = $parsed_data['oauth_token']; // Get the object URL $recipe = $parsed_data['objects'][0]['url'];  // The Graph API endpoint for publishing a save action $graph_url_publish =  "" . $access_token; $postdata = http_build_query( array( 'recipe' => $recipe ) ); $opts = array('http' => array( 'method'  => 'POST', 'header'  => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata ) ); $context  = stream_context_create($opts); // Publish the save action $result = json_decode(file_get_contents($graph_url_publish, false, $context)); if (($result != null) && isset($result->id)) { // Set the result flag to true $success_result = 'true'; } }  // Print the output $success = array( 'success' => $success_result ); $output = json_encode($success); echo $output; ?>
Updated 7 hours ago