I am novice to Google Analytics Api. I just started working on a small project where I want to pull data from the API and display it on each user’s Dashboard, using one single Google Analytics Account. I tried to follow the tutorial provided by google and made adjustments where required due to update to the library.
I am working on a codeigniter based platform and I was able to create a Google Client Object and also to make use of a refresh token which is saved in the database. I use the refresh token in order to have the data available on the dashboard without having to manually login every time.
The access token is there every time when I am logged in, and I can use it to set the client access token and create a Google Service Analytics object ($service = new Google_Service_Analytics($client);). I am printing the service and I can see the client id, client secret, etc and the access token being passed to it; but other like Google_Service_Analytics_DataGa_Resource Object are empty ( I do not know if they should be like that or not at this particular step ?).
When I am trying to request the user accounts
$accounts = $analytics->management_accounts->listManagementAccounts();,
I get a blank screen and my view is not being rendered.
I could not find such a problem being encountered before, so I am a bit confused why is happening. I do not get any error messages or anything that might point me to the cause of it or the right direction.
Note: I did managed to make it work using the same credentials trough JavaScript, but in this case it is not what I am looking for. I was able to retrieve data, display data in charts,etc using JS. I am new to making posts, so if anything is required from my part in order for you to have a better idea of what is going on, please do let me know.
I would greatly appreciate it I could get any indication to why that might be happening, or anything that would put me on the right path.
Codeigniter controller Class as follows
// Step 1 - Load PHP Client Libraries
require_once APPPATH.'libraries/Google/Client.php';
require_once APPPATH.'libraries/Google/Analytics.php';
class GoogleTest extends CI_Controller {
public function index(){
$this->load->helper(array('url','form'));
$this->load->model('googleapi_model'); //used to get the refresh token
// Step 2 - Start a session to persist credentials
session_start();
// Step 3 - Create and configure a new client object
$client = new Google_Client();
$client->setApplicationName("API Project");
// Insert client id, api key, client secret, project scope and redirect uri
$client->setDeveloperKey("***************");
$client->setClientId('********************');
$client->setClientSecret('******************');
$client->setRedirectUri('****************');
$client->setScopes(array('https://www.googleapis.com/auth/analytics.readonly'));
// Check if refresh token exists, it is used to login users automatically & it is being generated only once when you login the first time from the created
// google analytics app, this will take precedence to Step 4 or 6 below ;
if(count($this->googleapi_model->getGoogleRefreshToken()) > 0){
$db_refresh_token = $this->googleapi_model->getGoogleRefreshToken();
$client->refreshToken($db_refresh_token[0]->refreshtoken);
$_SESSION['token'] = $client->getAccessToken();
}else{
if ($client->getAccessToken()) {
$token = $client->getAccessToken();
$authObj = json_decode($token);
$refreshToken = $authObj->refresh_token;
if(isset($refreshToken) && $refreshToken != null){
$this->googleapi_model->insertGoogleRefreshToken($refreshToken);
}
}
}
//Step 4 - Handle authorization flow from the server
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
$redirect = 'http://' . $_SERVER['HTTP_HOST']. $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
}
// Step 5 - Retrieve and use stored credentials
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
// Stept 6 - Either prompt the user to login or run the demo
if(!$client->getAccessToken()){
$authUrl = $client->createAuthUrl();
$this->data['auth'] = $authUrl;
}else{ //Create analytics service object
echo 'authenticated';
$analytics = new Google_Service_Analytics($client);
//TILL HERE MY CODE WORKS FINE, NO ERRORS, VIEW BEING RENDERED
$accounts = $analytics ->management_accountSummaries->listManagementAccountSummaries();
// $accounts = $analytics->management_accounts->listManagementAccounts();
echo '<pre>';
print_r($analytics);
echo '</pre>';
}
$this->data['content'] = '/public/dashboard/google_test';
$this->load->view('template/template', $this->data);
}
Make sure you're logged into the google account that API app is in.
And that you have clicked 'connect'.
Then run the script.
Also turn on error reporting (including notices)
Related
I previously had issue with the Google account to access Youtube's API. So i created a new fresh gmail account & managed to get it working. Not only after like One hour. I found out that Refresh Token wasn't refreshing. I don't know why. This is becoming frustrating as it seems i would have to forfeit using Youtube services any longer.
This is my code below: perhaps i'm doing something wrong.
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
$client->setAccessType('offline');
$client->setApprovalPrompt('force'); // this line is important when you revoke permission from your app, it will prompt google approval dialogue box forcefully to user to grant offline access
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
$_SESSION[$tokenSessionKey] = $manually_stored_token; //$client->getAccessToken();
if (isset($_SESSION[$tokenSessionKey])) {
$client->setAccessToken($_SESSION[$tokenSessionKey]);
}
// Check to ensure that the access token was successfully acquired.
if($client->isAccessTokenExpired()) {
$client->refreshToken($refresh_token);
if(!$client->isAccessTokenExpired()) {
// do something
} else {
// refresh access token not granted
}
} else if ($client->getAccessToken()) {
// do something
} else {
// do something
}
I checked my account https://myaccount.google.com/u/0/security, under "Sign-in & Security" for authorized access to your Google Account, I still have authorization. So i don't know why its not refreshing my Token.
When you first authorise, you are given both the access_token and refresh_token in the response.
After that, you will only get a access_token back.
The refresh_token you must save and re-use.
If for what ever reason you loose it, you must reset your authorise access.
I had this issue and had to make a dirty hack as no one could give me an answer.
Basic fix is to "un-authorise" a user and then "re-authorise" them again. As if you do not, you will never get the refresh_token back.
To test and inspect. Open your account that is being authorised.
Go into the Dashboard and find "Apps connected to your account" section.
There you will see your app and can manually remove it for testing.
However, you will need to code for this later, but is good enough for testing.
I want to build a script that will check a Authenticated User's Google Calendar via the Google Calendar PHP Client. I was able to build a simple page that lets a user Auth and give permission to the Calendar Events. I receive a token and then grab a 15 upcoming events via:
$googleCal = new Google_Service_Calendar($googleClient);
$results = $googleCal->events->listEvents($calendarId, $optParams);
But what I'm struggling with is how to save this so I can have a script check this everyday to see if there were new events added. I think what I have is close just struggling to get over the finish line.
Thanks!
--
Update, I'm trying to use the refresh token, here is my code:
public function checkRedirectCode()
{
if(isset($_GET['code']))
{
$this->client->authenticate($_GET['code']);
// $this->setToken($this->client->getRefreshToken());
$this->setToken($this->client->getAccessToken());
$this->storeUser($this->getPayload());
return true;
}
return false;
}
public function setToken($token)
{
$_SESSION['access_token'] = $token;
$this->client->setAccessToken($token);
}
I have been able to echo the refresh token so I know I'm getting a proper refresh token but I'm getting errors whenever I use the commented out string. Any ideas?
To enable your script to be called beyond the lifetime of the original access token (which only last an hour), you will need to retrieve and store the refresh token during the initial authorisation, and then use this to generate a new access token each time your script runs.
Access tokens have limited lifetimes. If your application needs access
to a Google API beyond the lifetime of a single access token, it can
obtain a refresh token. A refresh token allows your application to
obtain new access tokens.
https://developers.google.com/identity/protocols/OAuth2#basicsteps (4. Refresh the access token, if necessary.)
After the user has authenticated your app, they are returned to your redirect URI with the code query-string.
The following is an example of authenticating and getting the refresh token (this uses Analytics, but should be the same for other services):
$client = new Google_Client();
$client->setClientId('xxx');
$client->setClientSecret('xxx');
$client->setRedirectUri('xxx');
//authenticate with the code returned from google
$authenticate = $client->authenticate($_GET['code']);
//get the refresh token
$refreshToken = $client->getRefreshToken();
//store refresh token in database...
Then, when you run your daily script, use the refresh token (retrieved from your database) to generate a new access token:
$client = new Google_Client();
$client->setClientId('xxx');
$client->setClientSecret('yyy');
$client->addScope(Google_Service_Analytics::ANALYTICS_READONLY);
$client->refreshToken($user->refresh_token);
$newToken = $client->getAccessToken();
$client->setAccessToken($newToken);
So I have recently integrated the new Office365 Rest API with PHP and have it working successfully with the Contacts API.
The system will generate the request url and redirect the user back once authentication is complete which works perfectly fine however if you go back to the script it will automatically log you through the process again as Office365 does not force reauthorisation.
Our script currently allows multiple users to sync their accounts with our system however this is only letting one user perform this per browser session.
require_once('./src/Office365_Client.php');
$client = new Office365_Client();
$forward_url = $client->createAuthUrl();
if (isset($_GET['code'])) {
$code = $_GET['code'];
$client->setCode($code);
$responseObj = $client->getTokens();
$access_token = $client->getAccessToken();
$refresh_token = $client->getRefreshToken();
$_SESSION['access_token'] = $access_token;
$_SESSION['instance_url'] = $instance_url;
$icustomer = (isset($_SESSION['icustomer'])) ? $_SESSION['icustomer'] : false;
header("location: " . $_SESSION['redirUrl'] . "?crm=office365&access_token=$access_token&refresh_token=$refresh_token");
//die();
//////////////////////////////////////////////////////////
// LOAD CONTACTS
/////////////////////////////////////////////////////////
//$client->getContactsFolders();
///////////////////////////////////////////////////
} else {
header("location: $forward_url");
}
Ideally it should work as followed:
User visits our website -> We generate Auth URL and the user is redirected to the Login Page for Office365 (They will then to autheticate if previously not done so) -> Once complete this will return them back to our selection screen with their code ready for their access token to be created. If the user wishes to add a different Office365 account they should be able to go through that process again without using a different browser.
Add prompt=login to the authorization request, so:
header("location: $forward_url" . "&prompt=login");
Have you tried logging out? The logout URI is https://login.windows.net/common/oauth2/logout. So you would want to do something like
https://login.windows.net/common/oauth2/logout?post_logout_redirect_uri=<some page in your app>
I'm trying to make some script, that will automatically add an event from Joomla add new page to a Google calendar. I made it with this code and it even works, but only for a small amount of time.
I maybe misunderstood, how the Google authorization works. First i must authorize the script to use that calendar and so on. I made it once but after an hour i had to do it again. I would like to authorize it forever or at least for one year (something longer than one hour). And i can't even authorize it during the saving process, because its in saving script, that automatically redirect back to post management.
One more thing to mention: there is an redirect uri and i set it on index.php of administration pages. Not sure if its a problem, but it shouldn't because news are added at index.php?...... so it's still the same page.
But it all works for an hour (or something around that) so i believe that problem is not redirect uri.
THX
here is my code (its copy pasted from some google api example page):
require_once "google-api-php-client/src/Google_Client.php";
require_once "google-api-phpclient/src/contrib/Google_CalendarService.php";
session_start();
$client = new Google_Client();
$client->setApplicationName("Add Google Calendar Entries");
$client->setClientId('####');
$client->setClientSecret('####');
$client->setRedirectUri('####');
$client->setDeveloperKey('####');
$cal = new Google_CalendarService($client);
if (isset($_GET['logout'])) {
unset($_SESSION['token']);
}
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
if ($client->getAccessToken()) {
$calList = $cal->calendarList->listCalendarList();
$_SESSION['token'] = $client->getAccessToken();
$event = new Google_Event();
// some calendar adding stuff
} else {
$authUrl = $client->createAuthUrl();
print "<a class='login' href='$authUrl'>Authorize!</a>";
}
// Google Calendar API END
}
Just to summarize: I want my authorization to work longer and maybe there is a mistake in my code or in my understanding of how that works.
The key piece to get long term access if to request "offline" access from the user when you request authorization.
$client->setAccessType('offline');
$authUrl = $client->createAuthUrl();
This should return a refresh token as well as the current session token. You MUST save this refresh token. Even if they authorize the app again later, the refresh token will NOT be sent again. (And on that note, if they are already authorized and you have them authorize again after adding offline access, sometimes you won't get the refresh token.)
Then you can do a check like the following to keep them logged in:
$client->setAccessToken($site->token);
if($client->isAccessTokenExpired()) {
$NewAccessToken = json_decode($client->getAccessToken());
$client->refreshToken($NewAccessToken->refresh_token);
}
Finally, I should add that you will need to save the accessToken to the database instead of just the session to actually make it persist over different sessions. Hopefully that was obvious already.
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.