I manage approximately 200 Google My business accounts, all being owned under an email XXX#YYY.com
I would like to use the Google My Business API using a PHP SDK to retrieve all types of stats regarding each accounts (ie. view per timeframe, view through map, view through SERP, etc...).
I did get the authorization to use the Google My Business API and I downloaded the php SDK: https://developers.google.com/my-business/samples/google-api-services-mybusiness-v4p9-php-rev-20210224-1.zip?hl=fr
I also created a service account (which I'm really not familiar with) in order to auth with the library.
Now here is my code :
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
// set the service account json file location manually
$client->setAuthConfig(__DIR__.'/../global/yyyyy-xxxx-xxxxxxxxxx.json');
$client->setApplicationName("yyyyyb");
// set the scope to access GMBs
$client->setScopes([
"https://www.googleapis.com/auth/business.manage"
]);
$this->client = $client;
$mybusinessService = new Google_Service_Mybusiness($client);
$accounts = $mybusinessService->accounts;
$accountsList = $accounts->listAccounts()->getAccounts();
echo "<pre>";
print_r($accountsList);
echo "</pre>";
$locationNames = array("Paris");
$insightReqObj = new Google_Service_MyBusiness_ReportLocationInsightsRequest();
$insightReqObj->setLocationNames($locationNames);
$basicReqObj = new Google_Service_MyBusiness_BasicMetricsRequest();
// datetime range is mandatory
// TODO :: validate to not allow more than 18 months difference
$timeRangObj = new Google_Service_MyBusiness_TimeRange();
$timeRangObj->setStartTime("2020-01-01T15:01:23Z");
$timeRangObj->setEndTime("2021-01-11T15:01:23Z");
$metricReqObj = new Google_Service_MyBusiness_MetricRequest();
$metricReqObj->setMetric('ALL');
$basicReqObj->setMetricRequests(array($metricReqObj));
$basicReqObj->setTimeRange($timeRangObj);
$insightReqObj->setBasicRequest($basicReqObj);
$allInsights = $mybusinessService->accounts_locations->reportInsights("accounts/XXXXXXXX",$insightReqObj);
echo "<pre>";
print_r($allInsights);
echo "</pre>";
There are two issues :
When I print the accountlist, I only find information about my service account, I was expecting a list of all the accounts managed by my email : XXX#YYY.com ; I realise that it makes no sense since I don't even know how to grant the service account access to the My Business account managed by this email.
Also AllInsignt generate an error :
How can I access the statistics of all the accounts managed by my Gmail account : XXX#YYY.com ?
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 can't get the Locations list from my business under my code (PHP using the "Google APIs Client Library for PHP" together with "Google_Service_MyBusiness" Classes) when I use the "Service Account" authentication, the API returns an empty Location List.
I already have the Prerequisites and did the Basic setup, by the way, I got the information with success on OAuth Playground, under a specific AccountId, Eg: 1111111111, provided by another response there on the "OAuth Playground".
(PS: I tested with my "PERSONAL" and "LOCATION_GROUP" accounts and got success with both).
But when I try to do it over my code via Server Account authentication, I can't get all the information, just the Account data that return another AccoundId, Eg: 2222222222, different of the Accounts that I got on OAuth Playground.
I did the Authentication process on OAuth Playground, using the same project where I created the "Service Account", by the way, the Permission of this "Service Account" is OWNER.
Previously, my role in my company on the Google My Business was "SITE_MANAGER", so I saw a forum answer where just "MANAGER" level/role can list the Locations, so I requested to change my permission, but continues as not the success on Locations listing.
So, I saw another Google My Business support article recommending create a "Location Group" and put my current "Location" into this group to make easy handle it, I did it and no success again.
My code is simple, based on Google guide, OAuth 2.0 for Server to Server Applications, and some Forum Questions (BTW the author's question have the same issue than me):
<?php
putenv('GOOGLE_APPLICATION_CREDENTIALS=service-account-credentials.json');
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope("https://www.googleapis.com/auth/plus.business.manage");
require_once('Google_Service_MyBusiness.php');
$mybusinessService = new Google_Service_MyBusiness($client);
$accounts = $mybusinessService->accounts;
$accountsList = $accounts->listAccounts()->getAccounts();
foreach ($accountsList as $accKey => $account) {
var_dump('$account->name', $account->name);
$locations = $mybusinessService->accounts_locations;
$locationsList = $locations->listAccountsLocations($account->name)->getLocations();
var_dump('$locationsList', $locationsList);
// Final Goal of my Code
if (empty($locationsList)===false) {
foreach ($locationsList as $locKey => $location) {
$reviews = $mybusinessService->accounts_locations_reviews;
$listReviewsResponse = $reviews->listAccountsLocationsReviews($location->name);
$reviewsList = $listReviewsResponse->getReviews();
var_dump('$reviewsList', $reviewsList);
}
}
}
I expected the Location of my business (also the reviews, but it a next step), but I just got the empty Location list.
Finally, I got success using the ClientId/ClientSecret keys together with Refresh Token previously received on Google OAuth 2 Playground on the first time that I give permission to (my) App, instead "Service Account" authentication way :)
$client = new Google_Client();
$client->setClientId($clientId);
$client->setClientSecret($clientSecret);
$client->addScope("https://www.googleapis.com/auth/plus.business.manage");
$client->setSubject('my email user on GMB');
$client->refreshToken(' ###### ')
Now I got all the needed data for my application.
I'm creating an AI Assistant using Dialogflow and I need to use Google APIs (google calendar and gmail). The APIs were working perfectly (I used this as reference). However, when I integrated my code with the dialogflow webhook, it returns Webhook Call failed. Error: 500 Internal Server Error.
here is a code snippet:
$client = new Google_Client();
$client->addScope(Google_Service_Gmail::GMAIL_READONLY); //view your emails and settings
$client->addScope(Google_Service_Gmail::GMAIL_COMPOSE); //manage drafts and send emails
$client->addScope(Google_Service_Gmail::GMAIL_MODIFY);
$client->addScope(Google_Service_Gmail::GMAIL_SEND); //send email on your behalf
$client->addScope(Google_Service_Calendar::CALENDAR); //manage calendar
$client->setAuthConfig('client_secret.json');
$client->setAccessType('offline');
$client->setApprovalPrompt('auto');
if($_SERVER['REQUEST_METHOD'] == 'POST'){
if(isset($_SESSION['access_token']) && $_SESSION['access_token']){
$client->setAccessToken($_SESSION['access_token']);
$gmail = new Google_Service_Gmail($client);
$user = "emailaddress#gmail.com";
$calendar = new Google_Service_Calendar($client);
$intent = $json->queryResult->intent->displayName;
$location_any = $json->queryResult->parameters->location_any;
$text = $json->queryResult->parameters->text;
$name = $json->queryResult->parameters->name;
$choice = $json->queryResult->parameters->choice;
$subject = $json->queryResult->parameters->subject;
$location = $json->queryResult->parameters->location;
$description = $json->queryResult->parameters->description;
$startDateTime = $json->queryResult->parameters->startDateTime;
$endDateTime = $json->queryResult->parameters->endDateTime;
if($intent== "UnreadMessages"){
$unread = unReadMessages($gmail, $user);
$speech = "You have ".$unread." messages";
}
else if($intent == "GetSchedule"){
$events = get_event($calendar);
if($events){
$reply = "You have the following events coming up:";
foreach($events as $event){
$eventName = $event['eventName'];
$eventTime = $event['time'];
$reply .= $eventName."is at".$eventTime;
}
$speech = $reply;
}
else{
$speech = "You don't have any events coming up.";
}
}
}
I'm suspecting it may be because of the authentication process that's required everytime I try to run the app, since the error only starts popping up whenever I check for session tokens. My problem now is how do I remove this authentication process?
You have several serious issues with your approach here, but most of them result from you treating the interaction with the Google Assistant like it was a browser hitting your web page. Although Actions on Google uses HTTPS and a webhook, it is otherwise not really like a browser at all.
For example, you check $_SESSION to see if an access token has already been set. $_SESSION is typically implemented by setting a session ID in the browser with a session cookie. The Assistant doesn't use cookies at all. Although it has a userStorage object which can be used it similar ways, this is accessed very differently.
It isn't clear if this is what is causing the error, or if the problem is related here somewhere. If you do have error logs, this would be useful to include in the question.
There is a lot that remains unclear. Primarily - where does the auth token come from in the first place in your code.
In a purely web-based OAuth scheme, you'll direct the user to log in using Google Sign In and, as part of that process, request authorization to access their Drive and GMail. Google Sign In for the Assistant doesn't allow you to do that - all it gives you is an Identity Token.
You can use Account Linking to link the Assistant account to your system - but this requires you to have an OAuth server that generates the auth token that the Assistant will give back to you. This is your OAuth token - not one that comes from Google (unless you're proxying it).
If you have a web-based way to get authorization, you can leverage this to provide access through the Assistant as well using Google Sign In for the Assistant.
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
I am trying to read a feed from a Google Sites account (Google apps).
I don't need my app to require every user to login so i created my ClientID as a "Service Account" in the "Google API console".
I have added this Client ID and the scope (https://sites.google.com/feeds/) to the "Mange API client access" page in my google apps control panel.
I connect using the code below, all constants are defined in my code with the right values.
// api dependencies
require_once(GOOGLE_API_PATH);
// create client object and set app name
$client = new Google_Client();
$client->setApplicationName(GOOGLE_API_NAME);
// set assertion credentials
$client->setAssertionCredentials(
new Google_AssertionCredentials(
GOOGLE_API_EMAIL,
array(GOOGLE_API_SCOPE),
file_get_contents(GOOGLE_API_PK)
));
$client->setClientId(GOOGLE_API_CLIENTID);
// create service
$req = new Google_HttpRequest("https://sites.google.com/feeds/content/<herismydomainname.com>/intranet");
$val = $client->getIo()->authenticatedRequest($req);
// The contacts api only returns XML responses.
$response = json_encode($val->getResponseBody());
print "<pre>" . print_r(json_decode($response, true), true) . "</pre>";
The response i get is "Not authorized to access this feed "
When i try to get this feed in the OAuth2.0 playground logging in using my google apps account i get the expected response.
What am i overlooking here?
Service accounts and Google Sites can't be used together currently. Google Apps provides a consumer secret that can be used to access data across your domain as Two-Legged OAuth within OAuth 1.0a.
Check out http://support.google.com/a/bin/answer.py?hl=en&answer=162105 for how to configure your Apps account, and the sample code at https://developers.google.com/gdata/docs/auth/oauth#2LeggedOAuth.