reverse engineering the google +1 button-using-firebug

When Google released its +1 button, I wanted to be able to use it in a PHP application. Specifically,I wanted to be able to obtain the counter for a series of links in order to rank the links by popularity. Unfortunately, Google did not offer a Google +1 true API at the time (and still does not offer one as far as I know).  However, given that the button are being displayed all over the web without any authentication, it was likely that something relatively easy to understand was happening in the background. Something similar to what Twitter, LinkedIn and Facebook did with their buttons.
Firebug has always been the best application when it comes to understanding this type of service so let's see what we can find. Let's head to http://vote2012.fr/ which has a +1 button and let's turn firebug on then reload the page (I am using Firefox).
The Net tab looks like the following:

Sometimes, it can get messy so you may want to sort by Domain and find the Google calls.
Looks like there are multiple calls to the host plusone.google.com (3). Looks like this one is going to be easy :)
Let's open the first link in a new tab:

We get a page with the counter only:

Let's turn firebug on and reload the page. We haven't made substantial progress but we have been able to isolate the calls pertaining to this button. Now, we are going to use by far one the most interesting features of firebug: the ability to search within the code/page related to a tab. So let's find the string "vote2012.fr". We get:

Credit:Viola

Looks like we found what we were looking for. If we examine closely the call, we noticed that it is a POST to the url https://clients6.google.com/rpc?key=AIzaSyCKSbrvQasunBoV16zDH9R33D88CeLr9gQ
The POST parameters look like:


Exactly what we needed! Humm, it is a non-standard HTTP POST call as the Headers tab indicates:
Content-Type:
[code]application/json; charset=UTF-8[/code]

instead of the usual
Content-Type:application/x-www-form-urlencoded
Now, if we look more closely at the parameters, we get:

So it is basically json-rpc. Let's try to replicate the finding in PHP.

So it is basically json-rpc. Let's try to replicate the finding in PHP.

$url = 'http://vote2012.fr/';
$requests[] = array(
    'apiVersion' => 'v1',
    'id'      => 'p',
    'jsonrpc' => '2.0',
    'key' => 'p',
    'method'  => 'pos.plusones.get',
    'params'  => array("nolog" => "true", "id" => $url, "source" => "widget", "container" => $url, "userId" => "@viewer", "groupId" => "@self"),
);
$json_request = json_encode($requests);
$ctx = stream_context_create(array(
    'http' => array(
        'method'  => 'POST',
        'header'  => 'Content-Type: application/json\r\n',
        'content' => $json_request
    )
));
$json_response = file_get_contents('https://clients6.google.com/rpc?key=AIzaSyCKSbrvQasunBoV16zDH9R33D88CeLr9gQ', false, $ctx);

print_r(json_decode($json_response, true));
And we get:
Array
(
    [0] => Array
        (
            [result] => Array
                (
                    [kind] => pos#plusones
                   [id] => http://vote2012.fr/
                    [isSetByViewer] =>
                    [metadata] => Array
                        (
                            [type] => URL
                            [globalCounts] => Array
                                (
                                    [count] => 0
                                )
                        )


Category Article

What's on Your Mind...

Thank f' u C0mment