I've managed to set up a PHP script that grabs data from our Google Analytics account and can run this great in the browser but I'm struggling to figure out how to allow this to work inside of the cronjob script instead.
Here's my code:
<?php
// Load the Google API PHP Client Library.
require_once dirname(__FILE__) . '/analytics/google-api-php-client-2.2.0/vendor/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfig(dirname(__FILE__) . '/analytics/client_secrets.json');
$client->setAccessType("offline"); //offline access
$client->addScope(Google_Service_Analytics::ANALYTICS_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
print "<br />start: ".date("H:i:s")."<br />";
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
$sessionid = $_SESSION['access_token']['access_token'];
// Create an authorized analytics service object.
$analytics = new Google_Service_AnalyticsReporting($client);
$view_id = urlencode("ga:XXXXXX");
$start_date = "yesterday"; //can be words or dates in Y-m-d
$end_date = "yesterday"; //can be words or dates in Y-m-d
$metrics = urlencode("ga:transactions");
$dimensions = urlencode("ga:transactionId,ga:date,ga:orderCouponCode");
$sort = "ga:date"; //for DESC use -FIELD e.g. -ga:date
$sampling = "HIGHER_PRECISION"; //https://developers.google.com/analytics/devguides/reporting/core/v3/reference#samplingLevel
$limit = "10000";
$filters = urlencode("ga:orderCouponCode!=(not set)");
$params = "ids=$view_id&start-date=$start_date&end-date=$end_date&metrics=$metrics&dimensions=$dimensions&filters=$filters&sort=$sort&samplingLevel=$sampling&max-results=$limit&access_token=$sessionid";
$data = file_get_contents("https://www.googleapis.com/analytics/v3/data/ga?$params");
$json_data = json_decode($data);
print "<pre>";
print_r($json_data);
print "</pre>";
} else {
// Handle authorization flow from the server.
if (! isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/cronjobs/ga_coupon_codes.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
}
print "<br />end: ".date("H:i:s")."<br />";
When my cronjob runs, the servers send me an email to say that it has finished running. I'm expecting to see both the "start" and "end" times printed in the response, as well as the JSON data, but the only thing that's coming back in the "end" time, leading me to believe it's not running through the main bit of it.
I know the main reason why it's not working is due to the authentication bit. In a cronjob I cannot use header('location: URL') but I can't figure out what to change this to in order to make it work.
When I set up the account, it was created as a service account and I can see from within the API console that I have a service account key.
I've also got an OAuth 2.0 client ID (which is what is in the client screts JSON file). If I run this in my browser I'm getting the connection to work, even after the hour runs out (where it's getting a new access token).
I've googled around for this for quite some time and found that adding "offline access" should help but obviously I'm still using the header() function. I can't find examples for me to use that are understandable to me and I'd really like to get this working in a cronjob.
Related
I am trying to get the organizations from a user with Google+ API or Google+ Domains API. I am following the steps on the official documentation and the logic I'm using is this one:
<?php session_start();
require_once 'vendor/autoload.php'; //INCLUDE PHP CLIENT LIBRARY
$scopes = array(
"https://www.googleapis.com/auth/plus.profiles.read",
"https://www.googleapis.com/auth/plus.me"
);
// Create client object and set its configuraitons
$client = new Google_Client();
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/');
$client->setAuthConfig("creds.json");
$client->addScope($scopes);
if( isset($_SESSION["access_token"]) ) {
$client->setAccessToken($_SESSION["access_token"]);
$service = new Google_Service_PlusDomains($client);
$me = $service->people->get('me');
var_dump($me);
echo "<br><br>*********************************************<br><br>";
$orgs = $me->getOrganizations(); // (THIS IS EMPTY!!!) ????
var_dump($orgs);
} else {
if( !isset($_GET["code"]) ){
$authUrl = $client->createAuthUrl();
header('Location: ' . filter_var($authUrl, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
}
?>
This perfectly works for G-Suite account I had before the transition of Google+ to Google+ Domains. When I use this same script on a newer G Suite account, it won't work. I have tried with $service = new Google_Service_Plus($client); and the result is the same thing. Any idea why it won't work with newer G Suite accounts? Is anybody else having the same issue?
Ok. I found the root cause of my problem. It happens that the User Resource and the People Resource are two different resources. Both of them have the "organization" attribute but the information of the user resource will not appear in your Google Plus profile and in order to populate the "organization" attribute of the people resource, the user is required to manually update the information from the "about me" page in Google Plus. At the moment, seems there is no way to programmatically update the information of the People Resource but users have to do it manually.
Thank you everyone for your time.
I've spent all day on this although, wasn't able to find a good example and answer, so I thought it may be relevant for the community.
<?php
session_start();
require_once ('Google/src/Google/autoload.php');
$client = new Google_Client();
$client->setApplicationName("xxxxx");
$client->setClientId('xxxxx');
$client->setClientSecret('xxxxx')
$client->setRedirectUri('xxxxx');
$client->addScope('profile');
$client->addScope('email');
$client->addScope('https://www.googleapis.com/auth/contacts.readonly');
if (isset($_GET['oauth'])) {
// Start auth flow by redirecting to Google's auth server
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else if (isset($_GET['code'])) {
// Receive auth code from Google, exchange it for an access token, and redirect to your base URL
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
} else if ($_SESSION['access_token']) {
// You have an access token; use it to call the People API
$client->setAccessToken($_SESSION['access_token']);
$service = new Google_Service_People($client);
$optParams = array('pageSize' => 10);
// TODO: Use service object to request People data
$results = $service->people_connections->listPeopleConnections('people/me', $optParams);
} else {
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/?oauth';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
Upon executing the script I simply get a blank white page, if I comment out $results = $service->people_connections->listPeopleConnections('people/me', $optParams) the script then works.
It looks like it loads the API properly and authenticates with Oauth and the token session variables are set; although when uncommented it is simply a white screen so I think the problem is retrieving data from the Google People API.
I'm trying to download a list of each users contacts (including name & email) to share a link with via email; after clicking a 'Login with Google' button.
Any assistance would be greatly appreciated, thank you for your time!
I followed again THIS TUTORIAL to upload a file on Google Drive with php, directly from my REMOTE SERVER: so I have created new API Project from Google API Console, enabled Drive API service, requested OAuth Client ID and Client Secret, wrote them in a script, then upload it together with Google APIs Client Library for PHP folder to this http://www.MYSERVER.com/script1.php, to retrieve Auth code:
<?php
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_DriveService.php';
$drive = new Google_Client();
$drive->setClientId('XXX'); // HERE I WRITE MY Client ID
$drive->setClientSecret('XXX'); // HERE I WRITE MY Client Secret
$drive->setRedirectUri('urn:ietf:wg:oauth:2.0:oob');
$drive->setScopes(array('https://www.googleapis.com/auth/drive'));
$gdrive = new Google_DriveService($drive);
$url = $drive->createAuthUrl();
$authorizationCode = trim(fgets(STDIN));
$token = $drive->authenticate($authorizationCode);
?>
When I visit http://www.MYSERVER.com/script1.php I allow authorization and get the Auth code that I can write in a second script. Then I upload it to http://www.MYSERVER.com/script2.php, who looks like:
<?php
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_DriveService.php';
$drive = new Google_Client();
$drive->setClientId('X'); // HERE I WRITE MY Client ID
$drive->setClientSecret('X'); // HERE I WRITE MY Client Secret
$drive->setRedirectUri('urn:ietf:wg:oauth:2.0:oob');
$drive->setScopes(array('https://www.googleapis.com/auth/drive'));
$gdrive = new Google_DriveService($drive);
$_GET['code']= 'X/XXX'; // HERE I WRITE AUTH CODE RETRIEVED AFTER RUNNING REMOTE script.php
file_put_contents('token.json', $drive->authenticate());
$drive->setAccessToken(file_get_contents('token.json'));
$doc = new Google_DriveFile();
$doc->setTitle('Test Drive');
$doc->setDescription('Document');
$doc->setMimeType('text/plain');
$content = file_get_contents('drive.txt');
$output = $gdrive->files->insert($doc, array(
'data' => $content,
'mimeType' => 'text/plain',
));
print_r($output);
?>
Well, now the file drive.txt is uploaded on my Google Drive and structure of token.json file is a sort of:
{"access_token":"XXX","token_type":"Bearer","expires_in":3600,"refresh_token":"YYY","created":1365505148}
Now, as you can imagine I can call script2.php and upload file until a certain time. Finally, the point is: I don't want the token to expire, I don't want to allow authorization each time it expire (recalling script1.php): I need to call the script2.php periodically during the day, to upload my file automatically, without user interaction. So, what's the best way to automatically refresh the token forever in this context? Do I need another script? Can I add some code to script2.php? or modify the token.json file? And where can I read the time remaining before the token expire? Thanks!
You don't have to periodically ask for an access token. If you have a refresh_token, PHP client will automatically acquire a new access token for you.
In order to retrieve an refresh_token, you need to set access_type to "offline" and ask for offline access permissions:
$drive->setAccessType('offline');
Once you get a code,
$_GET['code']= 'X/XXX';
$drive->authenticate();
// persist refresh token encrypted
$refreshToken = $drive->getAccessToken()["refreshToken"];
For future requests, make sure that refreshed token is always set:
$tokens = $drive->getAccessToken();
$tokens["refreshToken"] = $refreshToken;
$drive->setAccessToken(tokens);
If you want a force access token refresh, you can do it by calling refreshToken:
$drive->refreshToken($refreshToken);
Beware, refresh_token will be returned only on the first $drive->authenticate(), you need to permanently store it. In order to get a new refresh_token, you need to revoke your existing token and start auth process again.
Offline access is explained in detail on Google's OAuth 2.0 documentation.
After messing a lot I got this to work. I am using one file/script to get the offline token and then a class to do stuff with the api:
require_once 'src/Google/autoload.php'; // load library
session_start();
$client = new Google_Client();
// Get your credentials from the console
$client->setApplicationName("Get Token");
$client->setClientId('...');
$client->setClientSecret('...');
$client->setRedirectUri('...'); // self redirect
$client->setScopes(array('https://www.googleapis.com/auth/drive.file'));
$client->setAccessType("offline");
$client->setApprovalPrompt('force');
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
$client->getAccessToken(["refreshToken"]);
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
return;
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
if (isset($_REQUEST['logout'])) {
unset($_SESSION['token']);
$client->revokeToken();
}
?>
<!doctype html>
<html>
<head><meta charset="utf-8"></head>
<body>
<header><h1>Get Token</h1></header>
<?php
if ($client->getAccessToken()) {
$_SESSION['token'] = $client->getAccessToken();
$token = json_decode($_SESSION['token']);
echo "Access Token = " . $token->access_token . '<br/>';
echo "Refresh Token = " . $token->refresh_token . '<br/>';
echo "Token type = " . $token->token_type . '<br/>';
echo "Expires in = " . $token->expires_in . '<br/>';
echo "Created = " . $token->created . '<br/>';
echo "<a class='logout' href='?logout'>Logout</a>";
file_put_contents("token.txt",$token->refresh_token); // saving access token to file for future use
} else {
$authUrl = $client->createAuthUrl();
print "<a class='login' href='$authUrl'>Connect Me!</a>";
}
?>
</body>
</html>
You can load refresh token from file and use it as necessary for offline access:
class gdrive{
function __construct(){
require_once 'src/Google/autoload.php';
$this->client = new Google_Client();
}
function initialize(){
echo "initializing class\n";
$client = $this->client;
// credentials from google console
$client->setClientId('...');
$client->setClientSecret('...');
$client->setRedirectUri('...');
$refreshToken = file_get_contents(__DIR__ . "/token.txt"); // load previously saved token
$client->refreshToken($refreshToken);
$tokens = $client->getAccessToken();
$client->setAccessToken($tokens);
$this->doSomething(); // go do something with the api
}
}
More here: https://github.com/yannisg/Google-Drive-Uploader-PHP
the following code runs through well, but some times reports "Invalid token". It happens, when I have foreign website in my ID list. But when I log in with email/password pair, it runs well till the end. Any idea what is wrong?
Cheers:
Bob
<?php
/*
API ACCESS PANEL:
https://code.google.com/apis/console/
*/
session_start(); #the includes are as follows, using also gapi.class.php
require_once 'src/apiClient.php';
require_once 'src/contrib/apiAnalyticsService.php';
ini_set('display_errors', '1');
$client = new apiClient();
$client->setApplicationName("Google Analytics PHP Starter Application");
/*
Visit https://code.google.com/apis/console?api=analytics to generate your client id, client secret, and to register your redirect uri.
*/
$client->setClientId('');# MUST SET UP!
$client->setClientSecret('');# MUST SET UP!
$client->setRedirectUri('http://localhost/analytics/chart_server.php');# MUST SET UP!
$client->setDeveloperKey('');# MUST SET UP!
// requestReportData first parameter, an Analytics Profil ID must defined here:
$ga_profile_id='';# MUST SET UP!
//////////////////////////////////////////////////////////////////////////////
$service = new apiAnalyticsService($client);
// logout
if (isset($_GET['logout'])) {
unset($_SESSION['token']);
exit;
}
// get the tooken from Google, store into the session, call back this script with header-location
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['token'] = $client->getAccessToken();
header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
exit;
}
// if we got token in the session-ben, passing to $client (this is the OAuth client)
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
// if the token valid, then we have access:
if ($client->getAccessToken()){
#$props = $service->management_webproperties->listManagementWebproperties("~all");
/*
print "Web Properties " . print_r($props, true);
*/
print("auth OK");//ok
print_r($client->getAccessToken()); // print out for test
$_SESSION['token'] = $client->getAccessToken();// stor eback to the session
} else { // Authorize with OAuth cause we have no valid access token
#https://www.google.com/analytics/feeds/
#https://www.googleapis.com/auth/analytics.readonly
$scope="https://www.google.com/analytics/feeds/"; // we'd like to access this
$authUrl = $client->createAuthUrl($scope);
header("Location: ".$authUrl); /* Redirect browser */
# print "<a class='login' href='$authUrl'>Connect Me!</a>";
exit;
}
// test printout, OAuth account object:
$accounts = $service->management_accounts->listManagementAccounts();
print "List of accounts" . print_r($accounts, true) .;
//////////////////////////////////////////////////////////////////////////////////////////////
// Here is the Google Analytics API call, and the "TOKEN INVALID 401" error message //
//////////////////////////////////////////////////////////////////////////////////////////////
require 'gapi.class.php';
$ga = new gapi(null,null,$_SESSION['token']); // access token instead of mail, password pair
#$token=$ga->getAuthToken();# $_SESSION['token']
// http://code.google.com/p/gapi-google-analytics-php-interface/wiki/GAPIDocumentation
// requestReportData($report_id, $dimensions, $metrics, $sort_metric=null, $filter=null, $start_date=null, $end_date=null, $start_index=1, $max_results=30)
$dimensions=array('browser','date');// x coord
$metrics=array('visits','pageLoadTime','uniquePageviews'); // y coord
$sort_metric="-date"; #descending order
$filter = '';
$startDate = '2012-04-01';
$endDate = '2012-04-12';
$start_index=1;
$max_results=50;
#$ga->requestReportData($accProfiles[$profileNum]->getProfileId(),$dimensions,$metrics,$sort_metric,$filter, $start_date, $end_date, $start_index, $max_results );
$ga->requestReportData($ga_profile_id, $dimensions, $metrics, $sort_metric, $filter, $startDate, $endDate, $start_index, $max_results );
$results=$ga->getResults();
// test:
echo "Google Analytics data ";print_r($results);
#echo "#####".$ga->getMetrics();
// Set the JSON header
//header("Content-type: text/json");
#echo json_encode( array($dim, $met1, $met2, $met3 ) );
?>
Just forget the gapi.class.php. It is slow, and works only with USR/PSW.
The apiAnalyticsService is also slow, but works with tokens well.
Try changing your scope from this:
$scope="https://www.google.com/analytics/feeds/";
to this:
$scope="https://www.googleapis.com/auth/analytics.readonly";
I am trying to get to grips with interacting with the GA API v3 using php. Being quite new to php, I am struggling somewhat. Does anyone here have any experience with using the api with php (v3)?
http://code.google.com/intl/nl/apis/analytics/docs/index.html
Google does supply a small sample script but it's effectively useless (with my limited skills) as it returns an api key but doesn't tell you where it needs to go or why you need it.
If anyone has any knowledge I would be very grateful if you could show me how.
You need to make sure you register you API with Google from their API console. Make sure you turn on Google Analytics, and create a project.
After make sure you download the full api from Google Code.
You want to go into simple.php located in the Analytics folder (under examples) and uncomment lines 11-14, and replace with information from Google API Console:
$client->setClientId('xxxx.apps.googleusercontent.com');
$client->setClientSecret('xxxxxx');
$client->setRedirectUri('http://www.xxxx.com/xxx/examples/analytics/simple.php');
$client->setDeveloperKey('xxxxxxxxxxx');
This will let you connect and you will see the basic data. For more details and a great tutorial you can see it here.
Your total page should look like this:
<?php
require_once '../../src/apiClient.php';
require_once '../../src/contrib/apiAnalyticsService.php';
session_start();
$client = new apiClient();
$client->setApplicationName("Google Analytics PHP Starter Application");
// Visit https://code.google.com/apis/console?api=analytics to generate your
// client id, client secret, and to register your redirect uri.
$client->setClientId('addyourshere');
$client->setClientSecret('addyourshere');
$client->setRedirectUri('addyourshere');
$client->setDeveloperKey('addyourshere');
$service = new apiAnalyticsService($client);
if (isset($_GET['logout'])) {
unset($_SESSION['token']);
}
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['token'] = $client->getAccessToken();
header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
if ($client->getAccessToken()) {
$props = $service->management_webproperties->listManagementWebproperties("~all");
print "<h1>Web Properties</h1><pre>" . print_r($props, true) . "</pre>";
$accounts = $service->management_accounts->listManagementAccounts();
print "<h1>Accounts</h1><pre>" . print_r($accounts, true) . "</pre>";
$segments = $service->management_segments->listManagementSegments();
print "<h1>Segments</h1><pre>" . print_r($segments, true) . "</pre>";
$goals = $service->management_goals->listManagementGoals("~all", "~all", "~all");
print "<h1>Segments</h1><pre>" . print_r($goals, true) . "</pre>";
$_SESSION['token'] = $client->getAccessToken();
} else {
$authUrl = $client->createAuthUrl();
print "<a class='login' href='$authUrl'>Connect Me!</a>";
}