4

I have a site where I would like to show all visitors some data from my Google Analytics account (unique page views from separate countries). As far as I'm concerned it is possible to do this with OAuth 2.0 and Google Analytics API. I would like the authentication to be automated, so that whoever comes to my site can view this data, not just me who can log in to my Google Analytics account.

What I've done

  • Made a project with Google Developers Console.
  • Changed Analytics API to ON.
  • Created a service account.
  • Generated API key for both server- and browser applications (don't know which and where to use exactly).
  • Downloaded Google APIs Client Library for PHP.
  • Uploaded the .p12 key that was downloaded when I created a service account, uploaded it to my site and linked to it in google-api-php-client-master/examples/service-account.php.
  • Declared my service account client id in google-api-php-client-master/examples/service-account.php.

Current code

<?php
/*
 * Copyright 2013 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
session_start();
include_once "templates/base.php";

/************************************************
  Make an API request authenticated with a service
  account.
 ************************************************/
set_include_path("../src/" . PATH_SEPARATOR . get_include_path());
require_once 'Google/Client.php';
require_once 'Google/Service/Books.php';

/************************************************
  ATTENTION: Fill in these values! You can get
  them by creating a new Service Account in the
  API console. Be sure to store the key file
  somewhere you can get to it - though in real
  operations you'd want to make sure it wasn't
  accessible from the webserver!
  The name is the email address value provided
  as part of the service account (not your
  address!)
  Make sure the Books API is enabled on this
  account as well, or the call will fail.
 ************************************************/
$client_id = 'SECRET-NUMBERS.apps.googleusercontent.com';
$service_account_name = '';
$key_file_location = 'SOMENUMBERS-privatekey.p12';

echo pageHeader("Service Account Access");
if ($client_id == 'SECRET-NUMBERS.apps.googleusercontent.com'
    || !strlen($service_account_name)
    || !strlen($key_file_location)) {
  echo missingServiceAccountDetailsWarning();
}

$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
$service = new Google_Service_Books($client);

/************************************************
  If we have an access token, we can carry on.
  Otherwise, we'll get one with the help of an
  assertion credential. In other examples the list
  of scopes was managed by the Client, but here
  we have to list them manually. We also supply
  the service account
 ************************************************/
if (isset($_SESSION['service_token'])) {
  $client->setAccessToken($_SESSION['service_token']);
}
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
    $service_account_name,
    array('https://www.googleapis.com/auth/analytics.readonly'),
    $key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
  $client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();

/************************************************
  We're just going to make the same call as in the
  simple query as an example.
 ************************************************/
$optParams = array('filter' => 'free-ebooks');
$results = $service->volumes->listVolumes('Henry David Thoreau', $optParams);
echo "<h3>Results Of Call:</h3>";
foreach ($results as $item) {
  echo $item['volumeInfo']['title'], "<br /> \n";
}

echo pageFooter(__FILE__);

Issues

  • In google-api-php-client-master/examples/service-account.php there's this piece of code which I don't quite understand:

    $service_account_name = '';

what should I declare here?

  • When I have done all the above and loaded the page google-api-php-client-master/examples/service-account.php on my site, I get these two errors:

Warning: You need to set Client ID, Email address and the location of the Key from the Google API console

Fatal error: Uncaught exception 'Google_Auth_Exception' with message 'Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }'' in /home/texterx1/public_html/google-api-php-client-master/src/Google/Auth/OAuth2.php:327 Stack trace: #0 /home/texterx1/public_html/google-api-php-client-master/src/Google/Auth/OAuth2.php(289): Google_Auth_OAuth2->refreshTokenRequest(Array) #1 /home/texterx1/public_html/google-api-php-client-master/examples/service-account.php(75): Google_Auth_OAuth2->refreshTokenWithAssertion(Object(Google_Auth_AssertionCredentials)) #2 {main} thrown in /home/texterx1/public_html/google-api-php-client-master/src/Google/Auth/OAuth2.php on line 327

What have I done wrong?

Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
user3026192
  • 107
  • 7

1 Answers1

1

Ok the first thing you need to do is grab the Email address on developer console for your app that was created along with the app.

1046123799103-nk421gjc2v8mlr2qnmmqaak04ntb1dbp@developer.gserviceaccount.com

Login to your GA go to the admin section for the account you want the Service account to access. You need to give that email account Access at the account level just give them Read and analyze.


<?php
session_start();
require_once 'Google/Client.php';
require_once 'Google/Service/Analytics.php';
// Values from APIs console for your app    
$client_id = 'Client ID';
$service_account_name = 'Email address';
$key_file_location = 'The file you downloaded';

$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
if (isset($_SESSION['service_token'])) {
        $client->setAccessToken($_SESSION['service_token']);
    }
    $key = file_get_contents($key_file_location);

    $cred = new Google_Auth_AssertionCredentials(
        $service_account_name,
        array('https://www.googleapis.com/auth/analytics.readonly'),
        $key
        );
    $client->setAssertionCredentials($cred);
    if($client->getAuth()->isAccessTokenExpired()) {
        $client->getAuth()->refreshTokenWithAssertion($cred);
    }
    $_SESSION['service_token'] = $client->getAccessToken();
    $service = new Google_Service_Analytics($client);  
    $accounts = $service->management_accountSummaries->listManagementAccountSummaries();

   foreach ($accounts->getItems() as $item) {
    echo "Account: ",$item['name'], "  " , $item['id'], "<br /> \n";

    foreach($item->getWebProperties() as $wp) {
    echo '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WebProperty: ' ,$wp['name'], "  " , $wp['id'], "<br /> \n";    

    $views = $wp->getProfiles();
    if (!is_null($views)) {
    foreach($wp->getProfiles() as $view) {
        //  echo '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;View: ' ,$view['name'], "  " , $view['id'], "<br /> \n";    
    }
                }
            }
        }
Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • Thank you for your time. The key (.p12 file), do I need to do something with it on my computer before loading it up to my server? – user3026192 May 15 '14 at 13:03
  • I don't think so you should just be able to upload it. If it doesn't work let me know and I will do a test myself. – Linda Lawton - DaImTo May 15 '14 at 13:04
  • so if I got this value as Service account Client ID: `SOME-NUMBERS.apps.googleusercontent.com`, I should use the `SOME-NUMBERS` as `$service_account_name`? I tried that and it doesn't work. Thank you again for taking time, I have struggled with this issue for quite some time now. – user3026192 May 15 '14 at 13:10
  • The name is the email address value provided as part of the service account – Linda Lawton - DaImTo May 15 '14 at 13:13
  • OK, when I use th email address as `$service_account_name` I get another error: "*Warning: mkdir(): Permission denied in /home/texterx1/public_html/google-api-php-client-master/src/Google/Cache/File.php on line 103*" and "*Fatal error: Uncaught exception 'Google_Cache_Exception' with message 'Could not create storage directory: /tmp/Google_Client/44' in /home/texterx1/public_html/google-api-php-client-master/src/Google/Cache/File.php:104 Stack trace: #0 /home/texterx1/public_html/google-*" [...] – user3026192 May 15 '14 at 13:17
  • 1
    Ok you win I will do a test on this myself. I will get back to you. – Linda Lawton - DaImTo May 15 '14 at 13:20
  • I am working on it now. Currently stuck at "Insufficient Permission" so i have come farther then you did. TBH that tutorial isn't very good. – Linda Lawton - DaImTo May 15 '14 at 19:32
  • "Insufficient Permission".. Isn't that when you haven't declared the correct scope(s)? http://stackoverflow.com/questions/16978192/google-plus-api-insufficientpermissions-error – user3026192 May 15 '14 at 19:38
  • got it huge edit inc. I will wright up a tutorial on it tomorrow. It was because i was trying to give the user access at the View level it has to be the account level apperntly – Linda Lawton - DaImTo May 15 '14 at 19:52
  • Its late here i will check back on this tomorrow. – Linda Lawton - DaImTo May 15 '14 at 19:59