I have managed to obtain info from an "view" using php in the google analytics, however it only works if i authenticate with the google account, otherwise it displays the following error:
"Fatal error: Uncaught exception 'Google_Service_Exception' with message 'Error calling POST https://analyticsreporting.googleapis.com/v4/reports:batchGet: (403) User does not have sufficient permissions for this profile.'"
what i need basically is to find a way of obtaining the "view info" without authenticating, since i have a custom cms and i need to show this info in the cms admin section
Here is my code:
<?php
session_start();
require_once 'google-api-php-client/src/Google/autoload.php';
$client = new Google_Client();
$client->setAuthConfigFile('pathToFile.json');
$client->addScope(Google_Service_Analytics::ANALYTICS_READONLY);
// If the user has already authorized this app then get an access token
// else redirect to ask the user to authorize access to Google Analytics.
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
// Create an authorized analytics service object.
$analytics = new Google_Service_AnalyticsReporting($client);
// Call the Analytics Reporting API V4.
$response = getReport($analytics);
// Print the response.
$info = printResults($response);
} else {
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/api/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
function getReport(&$analytics) {
// Replace with your view ID. E.g., XXXX.
$VIEW_ID = "VIEW_ID_NUMBER";
// Create the DateRange object.
$dateRange = new Google_Service_AnalyticsReporting_DateRange();
$dateRange->setStartDate("2016-01-01");
$dateRange->setEndDate("today");
// Create the Metrics object.
$sessions = new Google_Service_AnalyticsReporting_Metric();
$sessions->setExpression("ga:goalCompletionsAll");
$sessions->setAlias("objetivos");
//Create the Dimensions object.
$medium = new Google_Service_Analyticsreporting_Dimension();
$medium->setName("ga:medium");
$minute = new Google_Service_Analyticsreporting_Dimension();
$minute->setName("ga:minute");
$hour = new Google_Service_Analyticsreporting_Dimension();
$hour->setName("ga:hour");
$date = new Google_Service_Analyticsreporting_Dimension();
$date->setName("ga:date");
$day = new Google_Service_Analyticsreporting_Dimension();
$day->setName("ga:day");
$goals = new Google_Service_Analyticsreporting_Metric();
$goals->setExpression("ga:goalStartsAll");
// Create the ReportRequest object.
$request = new Google_Service_AnalyticsReporting_ReportRequest();
$request->setViewId($VIEW_ID);
$request->setDateRanges($dateRange);
$request->setDimensions(array($medium, $date, $hour, $minute));
$request->setMetrics(array($sessions, $goals));
$body = new Google_Service_AnalyticsReporting_GetReportsRequest();
$body->setReportRequests( array( $request) );
return $analytics->reports->batchGet( $body );
}
?>
any info regarding this subject is greatly appreciated.
thanks
You can use a service account to access Google Analytics data without the Google authentication screen.
Create a service account and key
In the Google API Console (https://console.developers.google.com/), navigate to the Credentials tab. Under Create credentials, select Service account key. Choose a nice name and under Role I selected Project-->Viewer, which I can confirm to work. Under Key type, select JSON and click the Create button. A JSON file is downloaded to your system which you should look after since it's the only copy. You can't download it again later, so losing it will render that service account useless.
Give the account access to the Google Analytics view's data
The JSON file contains the Google Account (an e-mail address ending with iam.gserviceaccount.com). Copy that e-mail address and give it Read and analyze permissions on the Google Analytics view you want to have access to.
To get any information about GA you need to authenticate yourselfself.
If you do not want to use authentification path with the pop up windows you can use the "p12 key" to workaround this issue. The p12 files need to be attached to you request and there is no need to be logged (this is the solution for server side application), but this only work with your own data, so the ownder of the p12 key need to have access The desired account
https://developers.google.com/analytics/devguides/reporting/core/v4/authorization
Check this to know how to get the p12
https://webapps.stackexchange.com/questions/58411/how-where-to-obtain-a-p12-key-file-from-the-google-developers-console
Related
I'm trying to get a connexion between a google Calendar account and the google calendar API to update a MySQL database based on the events contained by the google calendar. It seems that my client is set up, and now I have to get the CalendarList, but I'm having trouble here.
I took inspiration on what have been done in the quickstart.php and what is explained in the google documentation to try some tests.
The problem is that all my requests return an empty result when I use the method getItems();
My code:
function getClient()
{
$client = new Google_Client();
$client->setApplicationName('Google Calendar API PHP synchroniser');
$client->setScopes(Google_Service_Calendar::CALENDAR_READONLY);
$client->setAuthConfig('Path/To/My/AccountService/File.json');
$client->setAccessType('online');
$client->setPrompt('MyCalendarWithMyData');
// Load previously authorized token from a file, if it exists.
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
/*
$tokenPath = 'token.json';
if (file_exists($tokenPath)) {
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
}
// If there is no previous token or it's expired.
if ($client->isAccessTokenExpired()) {
// Refresh the token if possible, else fetch a new one.
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
} else {
//I don't know what to put here.
}
}
*/
return $client;
}
$client = getClient(); // based on quickstart.php
$service = new Google_Service_Calendar($client);// from the sample on documentation
$calendarList = $service->calendarList->listCalendarList();
$calendars=$calendarList->getItems();
var_dump($calendars);
My goal is when I got the calendar list to get each events relative to each calendar in the calendar list to update my database.
Thanks
G.G
What you need to remember is that a Service account is not you. A service account is a dummy user. This user has its own google calendar account, drive account and probably a few more.
If you do a
$calendar = $service->calendars->get('primary');
echo $calendar->getSummary();
You will see that in fact your service account does have a calendar. What it doesnt have is anything by default in its calendar list.
If you want it to have access to your personal Google calendar then you will need to go to the google calendar website and share the calendar with the service accounts email address. then it should be able to do the following make sure you note the calendar id for the calendar you shared with it while you are in the settings.
$calendar = $service->calendars->get('calendarid');
echo $calendar->getSummary();
If you really want it in calendar list you can add it.
$calendarListEntry = new Google_Service_Calendar_CalendarListEntry();
$calendarListEntry->setId("calendarId");
$createdCalendarListEntry = $service->calendarList->insert($calendarListEntry);
echo $createdCalendarListEntry->getSummary();
Service account set up
As i have mentioned service accounts need to be preauthorized. You need to go to the Google Calendar website and under settings for the calendar you want it to be able to access you need to share the calendar with it as shown
useful links
Oauth2 service accounts
Google developer console Service accounts
I'm trying to set up the Google Search Console API in Laravel and I'm struggling with getting it working with my newly-generated credentials. I've set up an API key in the console and inserted this into my code, however upon trying to fetch the data the application returns 401 Invalid credentials. I feel really stupid for not being able to get this working since I would assume copying the API key and inserting it in my code would do the job. Which key is required to authenticate and retrieve data from the Search Console API?
I have tried setting up a new API key and using that key in the setAccessToken field. I even tried setting up Oauth 2.0 and using those credentials to authenticate. It seems the program crashes at 'setAccessToken'. The only other key I applied is the developer key ($client->setDeveloperKey())
public static function debugSiteData() {
// Dates (YYYY-mm-DD)
$fromDate = date('Y-m-d', strtotime('-3 months'));
$toDate = date('Y-m-d', strtotime('-1 day'));
$client = new Google_Client();
$client->setApplicationName("application_name");
$client->setDeveloperKey('AIza(...)');
$client->addScope(Google_Service_Webmasters::WEBMASTERS_READONLY);
$webmaster = new Google_Service_Webmasters($client);
$searchConsole = new SearchConsoleClient($client);
$searchConsole->setAccessToken("ACCESS TOKEN");
// $debugData = var_export($searchConsole);
$search = new \Google_Service_Webmasters_SearchAnalyticsQueryRequest();
$search->setStartDate($fromDate);
$search->setEndDate($toDate);
$console = $webmaster->urlcrawlerrorscounts->query('http://www.website.com/', array())->getCountPerTypes();
return '<pre>' . $console . '</pre>';
}
With the method above I'm getting a 401 Invalid credentials error. I feel like it's something really simple but I can't seem to figure it out at this point.
Using Oauth is a good idea to trigger Google APIs, in your case, you need to store the credentials in your DB after Oauth callback, access_token, refresh_token, expires_in, then you need to use those credentials to use the Google API's
$client = new Google_Client();
// Set Client Id (From Google Cloud Console)
$client->setClientId($client_id);
// Set Client Secret (From Google Cloud Console)
$client->setClientSecret($client_secret);
// Set Access Token With Oauth credentials (form DB)
$client->setAccessToken([
'access_token' => $token,
'refresh_token' => $refresh_token,
'expires_in' => $expires_in
]);
// Check if the access token is expired
if ($client->isAccessTokenExpired()) {
// This will refresh the token automatically
$token = $client->refreshToken(null);
$this->setAccessToken($token);
}
I want to get events of one of my apps that uses Google Analytics.
I am little confused with example given in the official documentation. I make it work but i don't understand how to use it for my case.
require_once 'GA/vendor/autoload.php';
// Start a session to persist credentials.
session_start();
// Create the client object and set the authorization configuration
// from the client_secretes.json you downloaded from the developer console.
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->addScope(Google_Service_Analytics::ANALYTICS_READONLY);
// If the user has already authorized this app then get an access token
// else redirect to ask the user to authorize access to Google Analytics.
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
// Create an authorized analytics service object.
$analytics = new Google_Service_Analytics($client);
After this code I want to get events data - how should I specify counter id, and event info?
Using Query Explorer I managed to created query that I need:
googleapis.com/analytics/v3/data/ga?ids=ga%3A111111&start-date=30daysAgo&end-date=2016-05-11&metrics=ga%3AtotalEvents&dimensions=ga%3AeventLabel
I am not sure what you mean by counter id. You have your analytics service you just need to make the request now.
$params = array('dimensions' => 'ga:AeventLabel');
// requesting the data
$data = $analytics->data_ga->get("ga:89798036", "30daysAgo", "2016-05-11", "ga:totalEvents", $params );
// displaying the data
foreach ($data->getRows() as $row) {
print "ga:AeventLabel ".$row[0]." ga:totalEvents ".$row[1]";
}
I use this class with the following code and it works well:
require 'GoogleAPI/gapi.class.php';
define('ga_profile_id','YOUR-DEV-ID');
$ga = new gapi('YOUR-DEV-ID#developer.gserviceaccount.com','GoogleAPI/cert.p12');
$ga->requestReportData('YOUR-APP-ID',array('eventAction'),array('visitors'),null,"eventAction==loginViaWebsite",$"2016-05-11","2016-05-11");
$logins = $ga->getResults();
if($logins) $logins = $logins[0]->getMetrics();
I am trying to insert events into Google Calendar, but I get errors everytime. I've been searching for hours to get answer, but I found nothing for my problem. I tested a lot of examples, without success. I'm new in Google Calendar, and I can't really understand the google api documentation.
I have a Fullcalendar which uses the Google Calendar (Gcal) as backend. I can read data from Gcal without any problems. When I try to displayed using Fullcalendar, but when I want to write some test datas into Gcal it gives me errors. I want to make a Calendar application which serves as a reservation app. So I have a Calendar, which is displayed to everyone who enter the page, and they can reserve appointments, which are stored in my Google Calendar.
The main is problem is that, I don't really know how to make the connection to Google Calendar for writing data. Every sample I've seen, solves the problem different way, major of them are outdated, some of them uses Sessions, but I don't need Session because the Calendar I want to display is FIX, everyone sees the same.
The code:
require_once 'Google/src/Google/autoload.php';
require_once "Google/src/Google/Client.php";
require_once "Google/src/Google/Service/Calendar.php";
$client_id = 'XXXXXXXXXX-f9ltk86b2klat20k1osmfbgpu4u1vqse.apps.googleusercontent.com';
$client_secret = 'XXXXXXXXXXXXXXXXXXXXXXX';
$key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; // Server Key
$email_address = 'XXXXXXXXXXXX-f9ltk86b2klat20k1osmfbgpu4u1vqse#developer.gserviceaccount.com';
$client = new Google_Client();
$client->setApplicationName("Calendar");
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setDeveloperKey($key);
$client->setScopes(array(
'https://www.googleapis.com/auth/plus.login',
));
$cal = new Google_Service_Calendar($client);
$event = new Google_Service_Calendar_Event();
$event->setSummary('Title');
$event->setDescription('Title');
$event->setLocation('Somewhere');
$start = new Google_Service_Calendar_EventDateTime();
$start->setDateTime('2013-08-17T16:00:00.000-07:00');
$event->setStart($start);
$end = new Google_Service_Calendar_EventDateTime();
$end->setDateTime('2013-08-17T17:00:00.000-07:00');
$event->setEnd($end);
$createdEvent = $cal->events->insert('<Calendar ID>', $event);
The exception it generates:
[19-Jun-2015 09:08:59 Europe/Berlin] PHP Fatal error: Uncaught exception 'Google_Service_Exception' with message 'Error calling POST
https://www.googleapis.com/calendar/v3/calendars/hpba8d7p1f6l65ruhbl9qigvks%40group.calendar.google.com/events?key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX:
(401) Login Required' in
/var/www/XXXXXXXXXXXXXXXXXXXX/calendar/Google/src/Google/Http/REST.php:110
Login Required means that you have not authenticated properly.
By looking at the scope you are using I think that might give you a hint as to why its not working
'https://www.googleapis.com/auth/plus.login'
You are passing the scope for Google+ you should be passing one of the Google calendars scopes if you want to access Google calendar data.
https://www.googleapis.com/auth/calendar read/write access to Calendars
https://www.googleapis.com/auth/calendar.readonly read-only access to Calendars
Authenticate with a service account
<?php
require_once 'Google/autoload.php';
session_start();
/************************************************
The following 3 values an befound in the setting
for the application you created on Google
Developers console. Developers console.
The Key file should be placed in a location
that is not accessable from the web. outside of
web root.
In order to access your GA account you must
Add the Email address as a user at the
ACCOUNT Level in the GA admin.
************************************************/
$client_id = '[your client]';
$Email_address = '[your service account email]';
$key_file_location = '[Your key]';
$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
$key = file_get_contents($key_file_location);
// separate additional scopes with a comma
$scopes ="https://www.googleapis.com/auth/calendar";
$cred = new Google_Auth_AssertionCredentials(
$Email_address,
array($scopes),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$service = new Google_Service_Calendar($client);
?>
code ripped from tutorial PHP Google Calendar service account
Tip: make sure that you have given the service account access to the calendar in question. You just need to add the service account email to the calendar like you would any other user.
I want to write a PHP script that imports web stats data from GA. The script is accessible through a web front end (for triggering the import) and resides on a local server (127.0.0.1).
As I understood from the documentation is that there are two options for authenticating and using the core API:
API key - grants only access to statistics
OAuth2 - full authorization
If I understand the mechanics of OAuth2 correctly then this is not an option in my scenario because I cannot specify a callback URL. Hacky solutions come to my mind - like establishing a web profile authentication directly connecting to GA from the browser and then fetching the data by JavaScript and feeding it to the import script - but I would prefer to refrain from such solutions. Also because the browser interaction triggering the import process might be substituted with a cron job in the future.
The API key seems to be exactly what I want but the GET request from the browser fails.
GET request:
https://www.googleapis.com/analytics/v3/data/ga
?ids=ga:[profile ID]
&start-date=2013-01-01&end-date=2013-01-05
&metrics=ga:visits
&key=[the API key]
Response:
{
error: {
errors: [
{
domain: "global",
reason: "required",
message: "Login Required",
locationType: "header",
location: "Authorization"
}
],
code: 401,
message: "Login Required"
}
}
The URL though should be fine. Except for the key parameter it is the same as the one generated with http://ga-dev-tools.appspot.com/explorer/ which is also working (AOuth2 is used in that case). The API key is fresh.
Then again generating a new API key confronts me with the next inconveniency which is that apparently the key is only valid for a day.
So at the end of the day my question is this:
Is it possible to fetch data in the above described scenario without having to authenticate manually or generate API keys on a daily basis?
As already suggested, use this library: https://code.google.com/p/google-api-php-client/
but, instead of using oauth, create a service account from the api console (just select server application). This will provide you with a client id, an email that identify the service account, and *.p12 file holding the private key.
You then have to add the service account (the email) to your analytics as an admin user in order to get the data you need.
To use the service:
$client = new Google_Client();
$client->setApplicationName('test');
$client->setAssertionCredentials(
new Google_AssertionCredentials(
EMAIL,
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents(PRIVATE_KEY_FILEPATH)
)
);
$client->setClientId(CLIENT_ID);
$client->setAccessType('offline_access');
$analytics = new Google_AnalyticsService($client);
To get some data:
$analytics->data_ga->get(PROFILE_ID, $date_from, $date_to, $metrics, $optParams)
For the details check api docs. Also, be careful, there is a query cap (unless you pay)
I think to get this working, you need to use OAuth but with a slight modification to run it from server. Google calls this auth method "Using OAuth 2.0 for Web Server Applications"
As described on that page, you can use a PHP client library to get the authentication done. The client library is located here.
An example example on how to use this client library are on the same project's help pages. Note that you'll have to make some modifications to the code as the comments say to store the token in db and to refresh it regularly.
<?php
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_PlusService.php';
// Set your cached access token. Remember to replace $_SESSION with a
// real database or memcached.
session_start();
$client = new Google_Client();
$client->setApplicationName('Google+ PHP Starter Application');
// Visit https://code.google.com/apis/console?api=plus to generate your
// client id, client secret, and to register your redirect uri.
$client->setClientId('insert_your_oauth2_client_id');
$client->setClientSecret('insert_your_oauth2_client_secret');
$client->setRedirectUri('insert_your_oauth2_redirect_uri');
$client->setDeveloperKey('insert_your_simple_api_key');
$plus = new Google_PlusService($client);
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['token'] = $client->getAccessToken();
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
if ($client->getAccessToken()) {
$activities = $plus->activities->listActivities('me', 'public');
print 'Your Activities: <pre>' . print_r($activities, true) . '</pre>';
// We're not done yet. Remember to update the cached access token.
// Remember to replace $_SESSION with a real database or memcached.
$_SESSION['token'] = $client->getAccessToken();
} else {
$authUrl = $client->createAuthUrl();
print "<a href='$authUrl'>Connect Me!</a>";
}
I have a similar setup. The thing that you don't realize is that you can specify a http://localhost or http://127.0.0.1 or anything else as an origin and callback URL. You need to setup some web interface on your local server that initiates an OAuth setup for the user with the GA access. Note that this is one time. The callback handler must be something like this:
Note: The libraries used here are the same as the previous answer, the detailed code is in the wrapper.
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . '/content/business-intelligence';
if (isset($_GET['code'])) {
require_once 'GAPI.php';
$client = GAPI::init(); //create client instance of Google_Client
$client->authenticate(); //convert auth code to access token
$token = $client->getAccessToken();
$retVal = CF_GAPI::persistToken($token); //save token
if($retVal)
$redirect .= "?new_token";
else
$redirect .= "?bad_token";
}
header('Location: ' . $redirect); //redirect to bi index
Once you have saved the token saved, you must set it in the client before making requests to GA to get your analytics data. Like:
try {
$token = GAPI::readToken(); //read from persistent storage
} catch (Exception $e) {
$token = FALSE;
}
if($token == FALSE) {
$logger->crit("Token not set before running cron!");
echo "Error: Token not set before running cron!";
exit;
}
$client = GAPI::init(); //instance of Google_Client
$client->setAccessToken($token);
The GAPI::init() is implemented as follows:
$client = new Google_Client();
$client->setApplicationName(self::APP_NAME);
$client->setClientId(self::CLIENT_ID);
$client->setClientSecret(self::CLIENT_SECRET);
$client->setRedirectUri(self::REDIRECT_URI);
$client->setDeveloperKey(self::DEVELOPER_KEY);
//to specify that the token is stored offline
$client->setAccessType('offline');
//all results will be objects
$client->setUseObjects(true);
//tell that this app will RO from Analytics
$client->setScopes('https://www.googleapis.com/auth/analytics.readonly');
return $client;
My mysql table has columns like id, title, send_to_emails, frequency, dimensions, metrics, filters, profile_id which completely define each report to the generated from GA. You can play around with them using the documentation, list of metrics & dimensions and the sandbox tester that you already know about.