Custom Stories with Open Graph

Open Graph lets apps tell stories on Facebook through a structured, strongly typed API. When people engage with these stories they are directed to your app or, if they don't have your app installed, to your app's App Store page, driving engagement and distribution for your app.
Stories have the following core components:
  • An actor: the person who publishes the story, the user.
  • An action the actor performs, for example:cookrun or read.
  • An object on which the action is performed: cook a meal, run a race, read a book.
  • An app: the app from which the story is posted, which is featured alongside the story.
We provide some built in objects and actions for frequent use cases, and you can also create custom actions and objects to fit your app.
Once posted to Facebook, Open Graph stories look like this:
In this tutorial, we will walk through the steps required to create and publish the Open Graph story abouteating a dish that you can see in the image above. We will use the Object API to dynamically create the object and we will teach you how to add an image uploaded from the device that will illustrate the object or the action. There are two ways to publish an Open Graph story, using API calls and using the Share Dialog:
  • Using the Share Dialog means that when the user wants to share from your app, a fast app-switch will be made to the Facebook for iOS app installed on the user's device, a dialog will be presented to the user from which they can do the sharing, and then the control will be returned to your app. The Share Dialog is fast to implement, and does not require you to implement Facebook Login in your app or the user to be logged in at the time of sharing.
  • Using API calls means you can create your own sharing interface within your app, so the user will never be taken away from your app and you can design the sharing experience to match the look and feel of your app. However, you will have to implement Facebook Login in your app and have the user log in with their Facebook credentials and give your app permission to share on their behalf before they can share.
In this document we cover both:
Whichever of these methods you choose, you will need to cover the first three sections in this document first:
After that you can jump to your desired method for publishing.

Prerequisites

This tutorial is a just walk-through through the process of creating and publishing an Open Graph story from your app. It is not intended to be a thorough discussion of Open Graph or the Object API. If you're not familiar with these concepts you may want to give the following documents a read before you go on:
Before you start any of the tutorials in this document you will need:
  • Your environment set up
  • A Facebook app properly configured and linked to your iOS app
  • The Facebook SDK added to your project
  • Your Facebook app ID, display name, and url scheme added your app's .plist file
If you haven't done this and need help doing so, you can follow our getting started guide.

If you want to publish using API calls

In order to post Open Graph stories from your app using the Graph API you will need to implement Facebook login first. There are two ways to implement Facebook login in iOS: using the Facebook login button or making an API call to open a session. The sample attached to this tutorial uses the Facebook login button, but you can implement either.
Also, in order to publish an Open Graph story to Facebook on the user's behalf using API calls, you will need the user to grant the publish_actions permission to your app. You can learn more about managing permissions in this guide.
The sample app attached to the part of this tutorial that uses Graph API calls to publish includes the Facebook Login code and the code to request the necessary permissions. You can find theFBOGSample app on the ios-howtos repo on github.com/fbsamples.

Setting up your app to use Open Graph

Set up your app's namespace

A namespace is required if you're going to be creating a custom Open Graph action for your app. To add a namespace, go to the app dashboard, select your app, click on ''Settings'' and add a unique qualifier in the Namespace field under Basic Info. The app settings page will tell you if your namespace is unique.

Enable deep linking

One of the most attractive features of sharing Open Graph stories from your app, is that when people engage with these stories they can be directed to your app or your app's App Store page, driving engagement and new installs. This is done through the use of app links, in a process called deep linking.
We will cover how to implement deep linking later into this tutorial, for now enable it from the app dashboard on the ''iOS'' section of your app's settings and provide your app's iPhone and/or iPad App Store IDs. To enable deep linking you will have to have enabled Login in the same interface first.
If you are in the development phase and don't have an App Store ID yet, you can the App Store ID of any other app in the App Store for testing purposes. You will have to provide a valid App Store ID for deep linking to work.

Creating an Open Graph Story

The next step is creating a custom Open Graph story (action + object combination) for your app.
In addition to allowing you to create your own custom story, Open Graph also provides somebuilt-in action types that work with built-in objects. If built-in types fit your use case you will not need to create a custom story, you can use these built-in objects directly.
In order to create a custom Open Graph story, in your app's dashboard, select ''Open Graph'' from the left-hand navigation and click on the ''Add Custom Story'' button. A story is comprised of a verb (action) and noun (object). Use the wizard to create custom action and object types. For example, ''eat a dish'':

Editing Open Graph types

Once you've created a story, you can further customize it by editing each type to add the attributes of your choice. Click on the "Action Types" tab at the top. You will see a page listing your objects and actions.
You can also see your objects by selecting the "Object Types" tab. Click on your "dish" object. You will see a page where you can configure your object type in a more detail, as well as a list of all of your object properties. Take note of this page, we will reference it later.
Go back to the "Action Types" tab for your app and click on your "eat" action. Again you will see a list of properties for your action and if you scroll to the bottom of the page you will also see a list of "Capabilities". For more information on what these capabilities do, consult our documentation. Take note of these capabilities, we will reference them later as well.

Publishing using API calls

This section explains how to publish an Open Graph story using API calls. In order to follow this tutorial you will need to have covered the first three sections in this document:
If you want to see the complete code of this tutorial in action, you can find it in the FBOGSamplesample app on github.com/fbsamples/ios-howtos. However, this tutorial is self-contained and you don't need to check out the app code to be able to follow it.

Login and permissions

Once you have reached this point, in order to proceed, you will need to have user authentication with Facebook login working on your app. If you haven't done it, you should implement it now. You can refer to this documents Prerequisites section to find out how.
Also, in order to post Open Graph stories on a person's behalf, you must ask for and receive thepublish_actions permission. You will need to have implemented this permission request before you can proceed to the next section. See the Prerequisites section of this tutorial if you need more information.

Staging an image

In many cases, you will want to post images along with your user-owned object. In this case, for example, the user may want to add a photo of the dish. Images make the stories that result from using Open Graph much more interesting to people, which will drive greater engagement.
If you are building a mobile-only app, you perhaps do not have a website on which to host Open Graph objects and their images. Instead, you can use Facebook's image staging service. The image staging service enables you to upload an image to Facebook and receive a URL in return, which you can use to associate the image to a particular Open Graph object (or action).
To use the Image Staging Service, you begin with a UIImage and then use thestartForUploadingStagingResourceWithImage method to put it in the service. For example, if we let the user pick an image from the gallery using the image picker:
// When the user is done picking the image
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
  // Get the image
  UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage];

  // Dismiss the image picker off the screen
  [self dismissViewControllerAnimated:YES completion:nil];

  // stage an image
  [FBRequestConnection startForUploadStagingResourceWithImage:image completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
    if(!error) {
      // Log the uri of the staged image
      NSLog(@"Successfuly staged image with staged URI: %@", [result objectForKey:@"uri"]);

      // Further code to post the OG story goes here

    } else {
      // An error occurred 
      NSLog(@"Error staging an image: %@", error);
    }
  }];
}
If there's no error, we have successfully posted the image to the staging service and we have a uri that we can use to associate it with an object.

Creating an object

Now let's create an object using the FBOpenGraphObject protocol. Behind this protocol is anNSMutableDictionary in which we can store keys-value pairs based on the properties present in the Open Graph object type. When we created our Open Graph types, we mentioned that you could click on the type names to see the properties of an Open Graph object. These properties, includingog:titleog:description, and so on, can be set by assigning values to the corresponding keys in our FBOpenGraphObject.
Inside the callback from the image staging, if the image was staged successfully, you can add the code to create an object and attach the image to it:
// instantiate a Facebook Open Graph object
NSMutableDictionary<FBOpenGraphObject> *object = [FBGraphObject openGraphObjectForPost];

// specify that this Open Graph object will be posted to Facebook
object.provisionedForPost = YES;

// for og:title
object[@"title"] = @"Roasted pumpkin seeds";

// for og:type, this corresponds to the Namespace you've set for your app and the object type name
object[@"type"] = @"fbogsample:dish";

// for og:description
object[@"description"] = @"Crunchy pumpkin seeds roasted in butter and lightly salted.";

// for og:url, we cover how this is used in the "Deep Linking" section below
object[@"url"] = @"http://example.com/roasted_pumpkin_seeds";

// for og:image we assign the image that we just staged, using the uri we got as a response
// the image has to be packed in a dictionary like this:
object[@"image"] = @[@{@"url": [result objectForKey:@"uri"], @"user_generated" : @"false" }];
All objects and action type names in your code must be lowercase.
If your app requires that your object has additional properties, you can add these properties to the type from the app dashboard by selecting your object type and then clicking on the ''Add New Property'' button and then add them to the object instance in the same manner we have added the properties above.

Posting the Open Graph object

Once we've created and configured our object we need to post it to the Facebook Graph. These objects can then be combined with actions to create stories that are published on Facebook.
To do this, we need to open a connection using the FBRequestConnection startForPostOpenGraphObject:completionHandler: method, passing it our instance ofFBOpenGraphObject and a callback that will be executed if the object was posted successfully. In order to do this, after the code where you created and configured your object, add the following:
// Post custom object
[FBRequestConnection startForPostOpenGraphObject:object completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
  if(!error) {
    // get the object ID for the Open Graph object that is now stored in the Object API
    NSString *objectId = [result objectForKey:@"id"];
    NSLog([NSString stringWithFormat:@"object id: %@", objectId]);

    // Further code to post the OG story goes here 

  } else {
    // An error occurred
    NSLog(@"Error posting the Open Graph object to the Object API: %@", error);
  }
}];
Now, if everything went well, we have an image that's hosted on the Facebook staging server, and a dish object instance that the image is linked to hosted in the Facebook Graph.
If you run this code inside your app, you can check out the resulting object using the object browser. Remember that this is a user-owned object so in order to see your object you will need to choose the user's name in ''Object Owner'' on the top menu for the object to display:
Our next step is to create an action to which we can associate the object and publish this story on behalf of the user.

Creating an action

Facebook Open Graph actions are the "verbs" that indicate that a user has done something. To implement an Open Graph action, we will use the FBOpenGraphAction protocol. LikeFBOpenGraphObjectFBOpenGraphAction is an NSMutableDictionary, and we can link our dish object to our action by assigning the object id we got as response in the previous section to the dishkey.
The we can use the FBRequestConnection startForPostWithGraphPath:graphObject:completionHandler: method to post the action. We need to supply this method with the namespace and type of our action. For example, in our case our namespace is "fbogsampleapp" and our action is "eat" so our path will be /me/fbogsampleapp:eat. If we wanted to use the built-in likes action, our path would be /me/og.likes.
In our case, our code, which should be added inside the callback from posting the object to the Facebook Graph, looks like so:
// create an Open Graph action
id<FBOpenGraphAction> action = (id<FBOpenGraphAction>)[FBGraphObject graphObject];
[action setObject:objectId forKey:@"dish"];

// create action referencing user owned object
[FBRequestConnection startForPostWithGraphPath:@"/me/fbogsample:eat" graphObject:action completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
  if(!error) {
    NSLog([NSString stringWithFormat:@"OG story posted, story id: %@", [result objectForKey:@"id"]]);
    [[[UIAlertView alloc] initWithTitle:@"OG story posted"
                                message:@"Check your Facebook profile or activity log to see the story."
                               delegate:self
                      cancelButtonTitle:@"OK!"
                      otherButtonTitles:nil] show];
  } else {
    // An error occurred
    NSLog(@"Encountered an error posting to Open Graph: %@", error);
  }
}];
So, to recap, we first staged our image on the staging service. If the staging was successful, we created an object and associated the image with it. Then we stored the object in the Facebook Graph. If storing the object was successful, we created an action, associated the object with it, and posted it to Facebook on behalf of the user. In the case any of these calls goes wrong, we have a function that handles the errors by displaying a relevant message to the user. We've now successfully published an Open Graph story to Facebook.
The next step is to implement deep linking, so when people engage with the story we posted on Facebook they can be directed to your app or your app's App Store page, closing the loop and thus driving engagement and installs.
You can see the code we just wrote in action in the FBOGSample app, which you can find on the ios-howtos repo on github.com/fbsamples.

Publishing using the Share Dialog

Using the iOS share dialog makes it easy for an app to allow its users to post Open Graph stories to Facebook. The share dialog allows apps publish Open Graph stories without needing to authenticate its users through Facebook login and without having to ask them for publish permissions. The Share Dialog does this by doing a fast app-switch to the native Facebook for iOS app installed in the user's device. The user shares from a pre-populated dialog in the Facebook app and then control is returned to your app. If you want to avoid the fast app switch that comes with the share dialog and you don't mind requiring login with Facebook before posting, you can share your Open Graph stories using the Graph API as explained in the Publishing using API calls section.
This tutorial assumes that you have already gone through the first three sections of this document, and you already have an Open Graph story that you're ready to share:
If you want to see the complete code of this tutorial in action, you can find it in the FBOGSampleSDsample app on github.com/fbsamples/ios-howtos. However, this tutorial is self-contained and you don't need to check out the app code to be able to follow it.
To share the story, first we create an object of the type fbogsamplesd:dish, a custom object that we have created for our app, and give it a title, an image, a url and a description.
// Create an object
id<FBGraphObject> object =
[FBGraphObject openGraphObjectForPostWithType:@"fbogsamplesd:dish"
                                        title:@"Roasted pumpkin seeds"
                                        image:@"http://i.imgur.com/g3Qc1HN.png"
                                          url:@"http://example.com/roasted_pumpkin_seeds"
                                  description:@"Crunchy pumpkin seeds roasted in butter and lightly salted."];
Then, we create an action and we link the object to the action.
// Create an action
id<FBOpenGraphAction> action = (id<FBOpenGraphAction>)[FBGraphObject graphObject];

// Link the object to the action
[action setObject:object forKey:@"dish"];
All objects and action types in your code must be lowercase.
At this point, if we want to, we can tag other users and the place where the action occurred, using the user and place ids. In order to be able to do this, we need to enable the tags, place capabilities in the action's dashboard. In this case we will also enable user generated photos, which we will use later. To do this, in your apps dashboard go to Apps > your app > Open Graph > Action Types > your action. Scroll all the way to the bottom and check the appropriate boxes for the capabilities you want for your app.
Now you can tag places and users like this:
// Tag one or multiple users using the users' ids
[action setTags:@[<user-ids>];

// Tag a place using the place's id
id<FBGraphPlace> place = (id<FBGraphPlace>)[FBGraphObject graphObject];
[place setId:@"141887372509674"]; // Facebook Seattle
[action setPlace:place];
Remember that if your app is in sandbox mode, you will only be able to tag users who are administrators or developers of your app.
If you are sharing your Open Graph story using the Share Dialog, the story is being explicitly shared as the user has to go through the dialog flow and accept the post. As a result, you don't need to set the ExplicitlyShared flag (by doing [action setExplicitlyShared:true] as you would when using API calls). In fact doing this will NOT work and through an error when attempting to post.
When all this is done, we check if the share dialog is available usingcanPresentShareDialogWithOpenGraphActionParams:, and if it is we present it using one of thepresentShareDialogWithOpenGraphAction:* methods and passing it the action.
// Check if the Facebook app is installed and we can present the share dialog
FBOpenGraphActionShareDialogParams *params = [[FBOpenGraphActionShareDialogParams alloc] init];
params.action = action;
params.actionType = @"fbogsamplesd:eat";

// If the Facebook app is installed and we can present the share dialog
if([FBDialogs canPresentShareDialogWithOpenGraphActionParams:params]) {
  // Show the share dialog
  [FBDialogs presentShareDialogWithOpenGraphAction:action
                                        actionType:@"fbogsamplesd:eat"
                               previewPropertyName:@"dish"
                                           handler:^(FBAppCall *call, NSDictionary *results, NSError *error) {
                                             if(error) {
                                               // There was an error
                                               NSLog([NSString stringWithFormat:@"Error publishing story: %@", error.description]);
                                             } else {
                                               // Success
                                               NSLog(@"result %@", results);
                                             }
                                           }];

  // If the Facebook app is NOT installed and we can't present the share dialog
} else {
  // FALLBACK GOES HERE
}

Using the Feed Dialog as fallback

Again, if the share dialog is not available, we will fall back to the feed dialog. But in this case, the fallback will be slightly more complicated because the feed dialog doesn't support Open Graph stories. We will replace our story by a simple link to the tutorial and post the link using the feed dialog.
// FALLBACK: publish just a link using the Feed dialog  
// Put together the dialog parameters
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                               @"Roasted pumpkin seeds", @"name",
                               @"Healthy snack.", @"caption",
                               @"Crunchy pumpkin seeds roasted in butter and lightly salted.", @"description",
                               @"http://example.com/roasted_pumpkin_seeds", @"link",
                               @"http://i.imgur.com/g3Qc1HN.png", @"picture",
                               nil];

// Show the feed dialog
[FBWebDialogs presentFeedDialogModallyWithSession:nil
                                       parameters:params
                                          handler:^(FBWebDialogResult result, NSURL *resultURL, NSError *error) {
                                            if (error) {
                                              // Error launching the dialog or publishing a story.
                                              NSLog([NSString stringWithFormat:@"Error publishing story: %@", error.description]);
                                            } else {
                                              if (result == FBWebDialogResultDialogNotCompleted) {
                                                // User cancelled.
                                                NSLog(@"User cancelled.");
                                              } else {
                                                // Handle the publish feed callback
                                                NSDictionary *urlParams = [self parseURLParams:[resultURL query]];

                                                if (![urlParams valueForKey:@"post_id"]) {
                                                  // User canceled.
                                                  NSLog(@"User cancelled.");

                                                } else {
                                                  // User clicked the Share button
                                                  NSString *result = [NSString stringWithFormat: @"Posted story, id: %@", [urlParams valueForKey:@"post_id"]];
                                                  NSLog(@"result %@", result);
                                                }
                                              }
                                            }
                                          }];
If you have followed this tutorial up to this point, your app should be able to post an Open Graph story to Facebook using the Share Dialog with the Feed Dialog as fallback. The next section explains how to add an image to your Open Graph story. If your story doesn't require images, you can skip directly toimplementing deep linking, so when people engage with the story we posted on Facebook they can be directed to your app or your app's App Store page, closing the loop and thus driving engagement and installs.

Adding an image to your Open Graph story

You can also add an image to your Open Graph story. This can be either an image your app provides that's hosted on the web somewhere or, more interestingly, a user-generated image that's local to the device. In this example, we're picking an image from the user's image gallery using aUIImagePickerController. To do this, we will ask the user to choose an image from the image picker and we will move the code that posts to Facebook to theimagePickerController:didFinishPickingMediaWithInfo: method, which will be called once the user has finished choosing the image they want to add to their story. There we will package that image in a dictionary that will contain a UIImage in the url and a user_generated value of "true" and put it inside an array of images, and then attach the array to the action by assigning it to the image key in its dictionary. To do this, you will need to modify your code to look like this:
// When the user is done picking the image
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{

  /// Package the image inside a dictionary
  NSArray* image = @[@{@"url": [info objectForKey:UIImagePickerControllerOriginalImage], @"user_generated": @"true"}];

  // Create an object
  id<FBGraphObject> object =
  [FBGraphObject openGraphObjectForPostWithType:@"fbogsamplesd:dish"
                                          title:@"Roasted pumpkin seeds"
                                          image:@"http://i.imgur.com/g3Qc1HN.png"
                                            url:@"http://example.com/roasted_pumpkin_seeds"
                                    description:@"Crunchy pumpkin seeds roasted in butter and lightly salted."];

  // Create an action
  id<FBOpenGraphAction> action = (id<FBOpenGraphAction>)[FBGraphObject graphObject];

  // Set image on the action
  [action setObject:image forKey:@"image"];

  // Link the object to the action
  [action setObject:object forKey:@"dish"];


  // ...
You can do something similar to capture images directly from the camera. Also, you can attach multiple images to an action, each as a dictionary in the image array.
SDK Image size limits are 480x480px minimum resolution to 12MB maximum file size. The error code for images that go below or above the size limits is 102.
If you've followed this tutorial your app should now be able to post an Open Graph story to Facebook using the Share Dialog, with the Feed Dialog as fallback and possibly an image. The next step is toimplement deep linking, so when people engage with the story we posted on Facebook they can be directed to your app or your app's App Store page, closing the loop and thus driving engagement and installs.
If you want to see the complete code of this tutorial in action, you can find it in the FBOGSampleSDsample app on github.com/fbsamples/ios-howtos.

Deep linking

The final step in implementing Open Graph is to bring users to our app whenever they interact with stories posted from your app that they see on their news feed. With deep linking, if a user interacts with your story and does not have your app installed, they will be taken to your app's page in the App Store and be presented with an opportunity to download your app. If they do have your app installed, they will be sent to your app. In order to provide an optimal user experience, when directed to your app, the user should land in a view inside your app that features (or is related to) the object in the story they were interested in. For example, in this case, if a person clicks on the story about their friend eating roasted pumpkin seeds they should be directed to a view inside your app featuring this dish rather than a random view that provides no context.
To achieve this, you can attach a url to your object (using the og:url property we set when we defined our Open Graph object, above) and later use it as reference. When your app is opened, this url will be passed to it and you will be presented with an opportunity to parse it, determine what object the user chose to interact with, and put the user in a relevant part of your app.
To get deep linking working, we will override theapplication:openURL:sourceApplication:annotation method in your app's app delegate to include a call to FBAppCall handleOpenURL:sourceApplication:fallbackHandler:. This method will handle urls that are passed from Facebook and ignore everything else. If you have implemented login, as you should have, you will already have overriddenapplication:openURL:sourceApplication:annotation to handle the response from the login process. Now you will need to modify it to also handle links from deep linking.
Looking back at the code we wrote when we configured our object, our og:url format is "http://yourappdomain/" with some app-specific data attached to it. We want to extract only the app specific data, parse it, and then show the correct view controller. In order to do this, in your app delegate, you will need to modify your application:openURL:sourceApplication:annotation to look like this:
// In order to process the response you get from interacting with the Facebook login process
// and to handle any deep linking calls from Facebook
// you need to override application:openURL:sourceApplication:annotation:
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {

  BOOL wasHandled = [FBAppCall handleOpenURL:url sourceApplication:sourceApplication fallbackHandler:^(FBAppCall *call) {
    if([[call appLinkData] targetURL] != nil) {
      // get the object ID string from the deep link URL
      // we use the substringFromIndex so that we can delete the leading '/' from the targetURL
      NSString *objectId = [[[call appLinkData] targetURL].path substringFromIndex:1];

      // now handle the deep link
      // write whatever code you need to show a view controller that displays the object, etc.
      [[[UIAlertView alloc] initWithTitle:@"Directed from Facebook"
                                  message:[NSString stringWithFormat:@"Deep link to %@", objectId]
                                 delegate:self
                        cancelButtonTitle:@"OK!"
                        otherButtonTitles:nil] show];
    } else {
      //
      NSLog([NSString stringWithFormat:@"Unhandled deep link: %@", [[call appLinkData] targetURL]]);
    }
  }];

  return wasHandled;
}
Now, if you post a test Open Graph story from your app, and you engage on it from your native Facebook app, you will be directed to your app and you will be shown an alert view with the object id from the story you come from. You should replace this alert by some behavior suitable for your app, for example showing a view that features the object.
You can learn more about implementing deep linking by reading our Handling App Links guide.
So, summarizing, what we've done is publish an image to the staging service, attach the image to an Open Graph object and publish that object to the Facebook graph, create an Open Graph action, attach the object to the action, publish the action, and written code to handle any deep links to close the loop when people are directed to your app through your stories. You are now ready to let people use our app, share interesting things they find in it, and help their friends discover our app.
Was this document helpful?