I'm trying to retrieve data from an AdSense account through the AdSense Management API.
I have successfully retrieved data using Google APIs Explorer when connected with my AdSense account.
I am now trying to get this data from a PHP script which will be run in a crontab.
My understanding is that I need a Service account which I created and I generated a json file.
The following code fails if I try to use the json file with two different errors :
if I use the setSubject with the owner of the AdSense account :
"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method."
If I comment the setSubject :
"reason": "noAdSenseAccount",
"message": "User does not have an AdSense account."
Code:
<?php
require_once '../../vendor/autoload.php';
putenv('GOOGLE_APPLICATION_CREDENTIALS=../conf/Mercury-testlpstats.json');
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope('https://www.googleapis.com/auth/adsense.readonly');
//$client->setSubject('AdTech#Lagardere-Pub.com');
$service = new Google_Service_AdSense($client);
$startDate = '2017-05-01';
$endDate = '2017-05-01';
$optParams = array(
'metric' => array('INDIVIDUAL_AD_IMPRESSIONS', 'EARNINGS'),
'dimension' => 'DATE',
'filter' => array('AD_UNIT_ID==ca-pub-XXXX:YYYY'),
'useTimezoneReporting' => true
);
$report = $service->accounts_reports->generate('pub-ZZZZZ', $startDate, $endDate, $optParams);
2nd attempt with OAuth
I've created a OAuth account in https://console.cloud.google.com/apis/credentials/oauthclient/. When I check the AdSense API, my account appears in the list of authorized users in https://console.cloud.google.com/apis/api/adsense.googleapis.com/overview.
I've downloaded the corresponding JSON and changed my code but it still says:
"insufficientPermissions" if I set $client->useApplicationDefaultCredentials();
"Login Required" otherwise
require_once '../../vendor/autoload.php';
$client = new Google_Client();
$client->setAccessType('online');
$client->setAuthConfigFile('/home/al1/lpstats/conf/client_secret_725834039890-klbuc13f8089rjh7eis439b93n7sqqfv.apps.googleusercontent.com.json');
$client->addScope('https://www.googleapis.com/auth/adsense.readonly');
$service = new Google_Service_AdSense($client);
$startDate = '2017-05-01';
$endDate = '2017-05-01';
$optParams = array(
'metric' => array('INDIVIDUAL_AD_IMPRESSIONS', 'EARNINGS'),
'dimension' => 'DATE',
'filter' => array('AD_UNIT_ID==ca-pub-5035025648894332:3442683203'),
'useTimezoneReporting' => true
);
$report = $service->accounts_reports->generate('pub-5035025648894332', $startDate, $endDate, $optParams);
unauthorized_client
Means that the user you are authencating with does not have access to the Adsence Account you are trying to access.
Service account support
There are a number of Google APIs which don't support service accounts. Most noticeably would be YouTube API which does not even have a way of sharing your account with another user.
There are others which will allow you to share your data with another user but require that the user in question respond to an email notification. Blogger is one and Adsence is apparently another.
Solution
You will need to authenticate using Oauth2 using a user who has access to the adsence account in question. Authenticate your code once save the refresh token and use the refresh token to request a new access token within your cron job.
Related
I understand that there were already similar questions here, but the answers to them did not help me.
Trying to connect through a service account to the calendars of users who are part of the domain. For connection I use Google API PHP Client (https://github.com/googleapis/google-api-php-client)
Account setup followed the instructions (https://developers/admin-sdk/directory/v1/guides/delegation)
Here's my code:
<?php
require '/vendor/autoload.php';
$client = new Google_Client();
putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json');
$client->useApplicationDefaultCredentials();
$client->authorize();
$scopes = implode(' ', [Google_Service_Calendar::CALENDAR, Google_Service_Calendar::CALENDAR_EVENTS]);
$client->setScopes($scopes);
$client->setSubject('user#email.com');
$service = new Google_Service_Calendar($client);
$optParams = [
'maxResults' => 10,
'orderBy' => 'startTime',
'singleEvents' => TRUE,
'timeMin' => date('c')
];
$results = $service->events->listEvents('root#email.com', $optParams);
$events = $results->getItems();
And then I get an authorization error:
Error: {
"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."
}
Can you tell me if someone 's already faced a mistake like this? Should the root#email.com be mail or mail that was generated during access setup? Or is the problem somewhere else at all?
Thank you in advance for any help!
Your code is actually correct. Be sure you authorized your service account to use the same scopes you are trying to use in your code. This is a common issue with service accounts.
Here a walk-through from the docs:
Go to your G Suite domain’s Admin console.
Select Security from the list of controls. If you don't see Security listed, select More controls from the gray bar at the bottom of the page, then select Security from the list of controls.
Select Advanced settings from the list of options.
Select Manage API client access in the Authentication section.
In the Client name field, enter the client ID obtained from the service account creation steps above.
In the One or More API Scopes field enter the scopes required for your application (for a list of possible scopes, see Authorize requests).
For example, if you require domain-wide access to Calendar and Calendar Events: https://www.googleapis.com/auth/calendar, https://www.googleapis.com/auth/calendar.events
Click the Authorize button.
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 am using Google APIs PHP client to to access the Google Drive API.
My problem is that I want to get permission to access user email. However the authenticate screen doesn't show the permission I am seeking. It just display "Application would like to ....Have offline access. But when done from the Google API playground, it correctly displays access to users email prompt.
So I think there is something wrong in my code level while creating authenticate url. Please help me to resolve the issue.
$client = new Google_Client();
$guzzleClient = new \GuzzleHttp\Client(array( 'curl' => array( CURLOPT_SSL_VERIFYPEER => false, ), ));
$client->setHttpClient($guzzleClient);
$client->setAuthConfig($oauth_credentials);
$client->setRedirectUri($redirect_uri);
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$client->setState($this->uri->segment(3));
$client->addScope("https://www.googleapis.com/auth/drive");
If all you want is the email address of the current authencated user you can simply go though the google drive api.
About.get method Gets information about the user, the user's Drive, and system capabilities.
{
"user": {
"kind": "drive#user",
"displayName": "Linda Lawton",
"photoLink": "xxxx",
"me": true,
"permissionId": "xxxx",
"emailAddress": "xxxx#gmail.com"
}
}
Side note on scope:
Scopes are what tells the user what data you want to access. https://www.googleapis.com/auth/drive basically says you want full access to their Google drive account https://www.googleapis.com/auth/classroom.profile.emails would request access to their email address.
Offline access
'offline' tells the user you want to be able to access their account when they are not using your application. By adding this you will receive a refresh token which you can save and use at anytime to get a new access token to access a users data.
I am trying to create Google calendar events using Google Api OAuth service Account from PHP GAE.
I need the correct Session ID or the user EMail ID in the Calendar events field ‘created by’.
This is possible well in Google Apps Script(GAS), it creates the events with the correct session ID.
But, I want the same to be done in PHP GAE(Google App Engine). So, I tried to impersonate the user ID as follows:Perform Google Apps Domain-Wide Delegation of Authority
My aim is to insert the correct user ID of any end user automatically as like in GAS(Google Apps Script). I don't want any default credentials to be set in the field ‘created by’..
Using the PHP client library i tried to impersonate a user in Calendar API.I didn't get any complete sample for Calendar API.So, I tried the Drive API documentation sample, this sample seems to be working fine, Using other domain user also
Using Calendar API I wrote the below example.
<?php
require_once realpath(dirname(__FILE__).'/google-api-php-client-master/src/Google/autoload.php');
require_once realpath(dirname(__FILE__).'/google-api-php-client-master/src/Google/Service/Calendar.php');
require_once realpath(dirname(__FILE__).'/google-api-php-client-master/src/Google/Service/Oauth2.php');
use google\appengine\api\users\User;
use google\appengine\api\users\UserService;
$user = UserService::getCurrentUser();
$userEmail=$user->getEmail();
$client_email = '34234242424-qssjf8kg1kk42dnjdvd2ndrk7rou44#developer.gserviceaccount.com';
$private_key = file_get_contents('key.p12');
$scopes = array('https://www.googleapis.com/auth/calendar');
$credentials = new Google_Auth_AssertionCredentials(
$client_email,
$scopes,
$private_key
);
$credentials->sub = $userEmail;
$client = new Google_Client();
$client->setAssertionCredentials($credentials);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion();
}
$service =new Google_Service_Calendar($client);
$event = new Google_Service_Calendar_Event();
$start = new Google_Service_Calendar_EventDateTime();
$start->setDateTime('2015-09-26T10:00:00.000-07:00');
$event->setStart($start);
$end = new Google_Service_Calendar_EventDateTime();
$end->setDateTime('2015-09-26T10:00:00.000-07:00');
$event->setEnd($end);
$createdEvent = $service->events->insert('abc#group.calendar.google.com', $event);
It’s working well when i check this email, i got the correct service account credentials.
But when i used different email ID, i got this below error
PHP Fatal error: Uncaught exception 'Google_Auth_Exception' with message 'Error refreshing the OAuth2 token, message: '{ "error" : "unauthorized_client", "error_description" : "Unauthorized client or scope in request." }'' in /base/data/home/apps/s~production/1.3874/google-api-php-client-master/src/Google/Auth/OAuth2.php:363 Stack trace: #0 /base/data/home/apps/s~production/1.387/google-api-php-client-master/src/Google/Auth/OAuth2.php(314): Google_Auth_OAuth2->refreshTokenRequest(Array) #1 /base/data/home/apps/s~ei-html-production/1.3874/final.php(34): Google_Auth_OAuth2->refreshTokenWithAssertion() #2 {main} thrown in /base/data/home/apps/s~production/1.38742/google-api-php-client-master/src/Google/Auth/OAuth2.php on line 363
Plz help me what i did wrong.Why the issue happens, when I used diff email ID, my end user who'll create cal events, could be any GMAIL or Google based domain ID.
So, plz help with at least a sample part...
Reference links:
How do I Insert Google Calendar Event using Google Api 3 for any user in the domain?
How to create a Google Calendar event without a reminder / How to get Service Accounts to impersonate users
You can only impersonate users on a google apps domain where you have the necessary permission for (search for 'domain wide delegation'). You've got that covered.
Once you're authorized for impersonation you have to recreate a fresh Google Client for each user you impersonate. You'll only receive an access_token you can use for this very user. If you just change the email address once you're authorized it will not work.
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.