-
Notifications
You must be signed in to change notification settings - Fork 464
Graph API
The Graph API is the core of Facebook’s new interface. Let’s play with it.
Important side note: did you know you can play with the Graph API in your browser? It’s one of my favorite aspects of the new API. Facebook has released a Graph API Explorer, which lets you get an access token and explore the Graph easily. You can also make requests directly in your browser; for each example coming up, I include a link to the equivalent query. (If you haven’t been to http://graph.facebook.com, you should definitely click through and play with the results. Try your own nickname!)
Since I’m abbreviating the API results for space, I strongly encourage you to check it out.
First, you need to create your API object that you will use to make your calls. If you want, you can also pass an access token to access private or restricted data, as explained in the “Getting Private Data” section of this page.
@graph = Koala::Facebook::GraphAPI.new # pre 1.2beta
@graph = Koala::Facebook::API.new # 1.2beta and beyond
Note that you can also use the GraphAndRestAPI class, which allows all-in-one access to both the Graph and Rest API.
Let’s get some data from Facebook. To learn about an object, just use the get_object method. For instance, you can learn about people:
# http://graph.facebook.com/koppel
@graph.get_object("koppel")
# => {"name"=>"Alex Koppel", "id"=>"2905623", "last_name"=>"Koppel", "link"=>"http://www.facebook.com/koppel", "first_name"=>"Alex"}
And Pages:
# http://graph.facebook.com/contextoptional
@graph.get_object("contextoptional")
# => {"name"=>"Context Optional, Inc.", "id"=>"7204941866", ....}
Even anonymously, you can get certain connections like a Page’s feed:
# http://graph.facebook.com/contextoptional/feed
@graph.get_connections("contextoptional", "feed")
# => array_of_stream stories
Or pictures:
# http://graph.facebook.com/koppel/picture
@graph.get_picture("koppel")
# => "http://profile.ak.fbcdn.net/v224/784/109/q2905623_7065.jpg"
p. Note: You can pass a ‘type’ hash key with a value of ‘small’, ‘normal’, ‘large’, or ‘square’ to obtain different picture sizes, with the default being ‘square’. Also, you may need the user_photos permission.
As well as details about individual public stories:
# http://graph.facebook.com/7204941866_117111188317384
@graph.get_object("7204941866_117111188317384") # remember this ID
# => {"name"=>"Bare Escentuals Cosmetics",
# "message"=>"We've just launched the Bare Escentuals "Mom & Me" application!",
# "likes"=>3,
# ....
# }
You can also searches public posts for the keyword of your choice:
# http://graph.facebook.com/search?q=koala
@graph.search("koala")
# => {"data"=> [{"from"=>{"name"=>"Amy", ...}, "id"=>....,
# "message"=>"My apartment is infested with koala bears...."}]}
You can also pass nil as the first parameter to #search in conjunction with a “type” argument to see all of the public objects of a given type:
# http://graph.facebook.com/search?type=post
@graph.search(nil, {:type => "post"})
# => {"data"=> [{"from"=>{"name"=>"Bob", ...}, "id"=>....,
# "message"=>"I hope everyone can read this message...."}]}
Public data’s cool, but it’s often not enough. You want to know who your users are — their full details, their likes, their feed, their friends. Without an access token, you can’t get that:
@graph.get_connections("koppel", "likes")
# => Koala::Facebook::APIError: An access token is required to request this resource.
We’ll go over getting an access token in a moment. For now, head over to http://graph.facebook.com — Facebook’s Graph API developer site has a bunch of links, any of which will provide you with an access token. Copy that from the URL, and check out what you can do now:
# first, initialize a Graph API with your token
@graph = Koala::Facebook::GraphAPI.new(your_oauth_token) # pre 1.2beta
@graph = Koala::Facebook::API.new(your_oauth_token) # 1.2beta and beyond
# now, try that query again
# http://graph.facebook.com/koppel/likes?access_token=#{your_oauth_token}
@graph.get_connections("koppel", "likes")
# => [{"name"=>"Mechanics' Institute Library", ....}]
“me” is a very useful shortcut Facebook provides to getting the current user:
# http://graph.facebook.com/me?access_token=#{your_oauth_token}
@graph.get_object("me")
# => {"name"=>"Alex Koppel", ....}
Some newer Facebook calls take three parts — for instance, let’s say you want to get a user’s mutual friends. Easy:
# https://graph.facebook.com/me/mutualfriends/FRIEND_ID
@graph.get_connection("me", "mutualfriends/#{friend_id}")
# => [{"name"=>"Alex Koppel", ....}, ....]
With a user’s access token, you get any public information, plus additional information through extended permissions (see the OAuth section).
Reading’s all well and good, but no discussion of the graph would be complete without some writing. In order to write to the social graph, you’ll need to prompt your user for the publish_stream extended permission (see the OAuth section).
For the sake of simplicity, let’s assume the token we got above has the right permissions; otherwise, you’ll get an error. (Since writing to the graph involves sending POST requests, the browser follow-along unfortunately has to end.)
Let’s start by posting to our own walls using the put_wall_post method.
@graph.put_wall_post("hey, i'm learning kaola")
# => {"id"=>"2905623_123183957698327"}
p. Oops — we misspelled Koala! How embarrassing.
@graph.delete_object("2905623_123183957698327")
# => true
Let’s never speak of that again, okay?
You can also write to other people’s walls. For instance, I’ll send a link to a cool (if sappy) comic to my husband.
@graph.put_wall_post("explodingdog!", {:name => "i love loving you", :link => "http://www.explodingdog.com/title/ilovelovingyou.html"}, "tmiley")
=> {"id"=>"83901496_520908898070"}
Side note: put_wall_post posts to user/feeds, which doesn’t include a Share button. To get one when posting a link, you can use put_connections(user, “links”, hash_of_details).
Speaking of family, Mother’s Day was coming up when I wrote this. Let’s go back to that earlier post about the Mother’s Day app my company just released, and like it.
@graph.put_like("7204941866_117111188317384")
# => true
Now it has 4 likes:
@graph.get_object("7204941866_117111188317384")
# => {"message"=>"We've just launched the Bare Escentuals "Mom & Me" application", "likes"=>4...}
Actually, changed my mind. I’m not a huge cosmetics fan.
@graph.delete_like("7204941866_117111188317384")
# => true
Personal confession: I still haven’t picked out a gift for my mom. Time to talk about how I need to do that.
@graph.put_comment("7204941866_117111188317384", "Can't believe Mother's Day's just a week away! I'd better get on that gift.")
# => {"id"=>"7204941866_117111188317384_448625"} # ID of the comment
That’s more or less it for the Graph API. All the methods you just saw wrap a generic put_object method, which you can use whenever the convenience methods don’t work for you.
def put_object(parent_object, connection_name, args = {}) ....
Thanks to jagthedrummer for this contribution!
When fetching data from Facebook that returns a list of results (i.e. using API#get_connections or API#search) Facebook returns a limited number of results per request. To help make paging through these results easier, Koala returns a GraphCollection object, a subclass of Array, that includes a few methods to ease getting the next and previous pages of results.
@result = @graph.get_connections('me', 'feed')
@result.class
# => Koala::Facebook::GraphCollection
# You can use a GraphCollection just like a normal Array or results
@result.first
# => {"actions" => [], "message" => "This my feed message.", ...}
To get the next (or previous) page of results, use the next_page (or previous_page) method on a GraphCollection.
@next_page = @result.next_page
# => [{"actions" => [], "message" => "This my feed message.", ...}, ...]
@next_page.class
# => Koala::Facebook::GraphCollection
While paging through results is fun, most of the time you’ll want to fetch the next page of results only when requested by the user. The next_page_params and previous_page_params methods in conjunction with API#get_page method makes this a snap.
API#next_page_params returns an array with two entries describing the API URL to fetch the next page of results: the path and a hash of parameters.
@results.next_page_params
# => ['"me/feed", {"limit => "25", "access_token" => "...", ...}]
Using the result of next_page_params as the single argument to API#get_page you can retrieve the next page of your results.
Here’s an example using Rails:
# /app/controllers/foo_controller.rb
def index
# get the first page, or a next/previous page if appropriate params are sent
@results = params[:page] ? @graph.get_page(params[:page]) : @graph.get_connections("me", "feed")
end
# /app/views/foo/index.html.erb
<% @results.each do |result| %>
<!-- Display each result -->
<% end %>
<%= link_to 'Previous', url_for(:page => @results.previous_page_params) %>
<%= link_to 'Next', url_for(:page => @results.next_page_params) %>
Notice that API#get_connections only needs to be called once, when you fetch the first page of results. By using next_page_params to populate the “page” URL parameter, you can use params[:page] as a single parameter to API#get_page to get the next set of results (as above).
This example takes advantage of how Rails serializes an array as URL parameters (and how Rails interprets URL parameters when handling requests.) Even without this functionality, however, creating appropriate parameters to use from next_page_params should be fairly straight forward.
Sometimes, a Facebook user isn’t just a Facebook user, she’s a Page. The Graph API makes it straightforward to act for a Page a user manages.
First, get the user to grant your app the manage_pages permission. Then, you can get the Page’s access token, and use that to create a new API object:
# you can easily get the access token for a single page:
page_info = @user_graph.get_object(page, :fields => "access_token") # pre 1.2beta
# => {"access_token" => page_token, "id" => page_id}
page_token = @user_graph.get_page_access_token(page_id) # 1.2beta and beyond
# => access_token
# (if you don't get access_token, you're missing the manage_pages permission)
@page_graph = Koala::Facebook::GraphAPI.new(page_token) # pre 1.2beta
@page_graph = Koala::Facebook::API.new(page_token) # 1.2beta and beyond
# you can now use @page_graph to do things on behalf of the page
@user_graph.put_object('some-profile-id', 'feed', :message => 'This is posted as the user')
@page_graph.put_object('some-profile-id', 'feed', :message => 'This is posted as the page')
# you can also get a list of the user's pages and associated access tokens
# through the accounts connection (if you have manage_pages)
pages = @user_graph.get_connections(user_id, "accounts")
# => [{"name"=>"pageName", "id"=>"pageID", "access_token"=>"PageToken"}, ...other pages...]
# note on permissions:
# "The permissions granted by a user to your application will now also be applicable to their pages."
# see http://developers.facebook.com/docs/reference/api/
A few Graph API odds and ends that have come up over the years.
Koala’s put_wall_post posts to user/feeds (reflecting the design of Facebook libraries), which doesn’t include a Share button. To get one when posting a link, you can use put_connections(user, “links”, hash_of_details). Be aware, though, that as of this writing, not every argument is recognized when posting to links (in particular, name, description, and picture aren’t always respected — this may be fixed by the time use it).
In rare cases it can be useful to post unencoded parameters directly to Facebook — for instance, at one point posting certain strings (like <center></center> or %0D%0A) would add a line break to a wall post. All Koala form parameters are URL encoded, but it’s easy to post unencoded strings by constructing parameters yourself:
# this is posted without encoding and (at one time) would show up on two lines
@graph.put_connections("me", "feed?message=foo%0D%0Abar")
In some cases — for instance, if the user has opted out of the Facebook Platform entirely — your Graph API calls may return false instead of the expected object. It’s rare, but it does happen — something to keep in mind as you develop. See http://forum.developers.facebook.net/viewtopic.php?id=61050.
With Koala 1.2, we consolidated all the API classes into Koala::Facebook::API. If you’re still using an earlier version, use the GraphAPI, RestAPI, or (best) GraphAndRestAPI as appropriate. The older classes will continue to work as expected with 1.2, though with a deprecation warning.