Can I POST data to a Google Web App without having to authenticate? - post

I'm trying to POST data to a Google Web App to automatically enter some tedious data. Whenever I try I get a response back asking me to log in, the Web App is deployed to be accessible by anyone.
Can I POST data to the form without authentication? If not, what type of authentication is required?
Edit: Quick code sample I threw together:
WebClient client = new WebClient();
var keyValue = new NameValueCollection();
keyValue.Add("agentName", "John Doe");
keyValue.Add("dayOff", "Sunday");
keyValue.Add("startTime", "8:00 AM");
Uri uri = new Uri("mywebapp url");
byte[] response = client.UploadValues(uri, "POST", keyValue);
string result = Encoding.UTF8.GetString(response);

In order to allow anyone to execute your script, even if they are not signed in to a Google account, you need to use the following settings in the "Deploy as web app" dialog:
Project version: if in doubt, select "New" to ensure that you are deploying the latest copy of the script's code.
Execute the app as: select "Me". This ensures that the "even anonymous" option will be available.
Who has access to the app: select "Anyone, even anonymous". (Note that if you select "Anyone", only users that are signed-in to a Google account will be able to execute your script.)
Once you have selected these options, click the "Update" button and copy the script URL. It should look like https://script.google.com/a/macros/<APPS DOMAIN>/s/<SCRIPT KEY>/exec. At this point an unauthenticated GET or POST to the script's URL should be successful.
Be aware that the script's execution will count against your daily Apps Script quota.

Related

Link to a specific sheet in published Google Sheet

I see similar questionns has been asked multiple times before, but I cant seem to get them to work. I've also read that Google changed how their URLs are built up, so most of the solutions were deprecated unfortunately.
I'm looking for a link to a specific sheet of a workbook that has been published. I've made a simple workbook to test, and the published link looks like this:
https://docs.google.com/spreadsheets/d/e/2PACX-1vRrmEbjecLvXhbm409pa6JJXZd_ZXTG8Zt6OevIUs5Axq5oxlCZKU0QXk-2lW05HyXJ2B4Bzy3bG-4L/pubhtml
As you can see there is a top menu to change between the sheets, but that doesn't affect the URL.
Is there any way I can get a URL to "Sheet2" directly? Or is that dependant on having the Sheet ID (I'm not the owner of said spreadsheet)?
I believe your goal as follows.
You want to retrieve the values from Sheet2 from the URL of https://docs.google.com/spreadsheets/d/e/2PACX-1vRrmEbjecLvXhbm409pa6JJXZd_ZXTG8Zt6OevIUs5Axq5oxlCZKU0QXk-2lW05HyXJ2B4Bzy3bG-4L/pubhtml.
The owner of this Spreadsheet is not you.
You don't know the Spreadsheet ID and each sheet ID in the Spreadsheet. You know only the URL of https://docs.google.com/spreadsheets/d/e/2PACX-###/pubhtml.
Under above situation, you want to retrieve the direct URL of the sheet 2.
For above goal, how about this answer?
Issue and workarounds:
Unfortunately, in the current stage, it seems that the Spreadsheet ID and each sheet ID cannot be directly retrieved from the URL of https://docs.google.com/spreadsheets/d/e/2PACX-###/pubhtml. I think that this is the current specification. Also I think that this reason might be due to the security. So in order to achieve your goal, it is required to think of the workaround.
In this answer, as a workaround, I would like to achieve your goal using Web Apps created by Google Apps Script. When Web Apps is used, the directlink of Sheet2 can be retrieved.
Flow:
The flow of this workaround is as follows.
Download the Google Spreadsheet as a XLSX data from the URL of https://docs.google.com/spreadsheets/d/e/2PACX-###/pubhtml.
Convert the XLSX data to Google Spreadsheet.
Publish the converted Google Spreadsheet to Web.
Retrieve the URLs of each sheet.
Usage:
Please do the following flow.
1. Create new project of Google Apps Script.
Sample script of Web Apps is a Google Apps Script. So please create a project of Google Apps Script.
If you want to directly create it, please access to https://script.new/. In this case, if you are not logged in Google, the log in screen is opened. So please log in to Google. By this, the script editor of Google Apps Script is opened.
2. Prepare script.
Please copy and paste the following script (Google Apps Script) to the script editor. And please enable Google Drive API at Advanced Google services. This script is for the Web Apps.
function doGet(e) {
const prop = PropertiesService.getScriptProperties();
const ssId = prop.getProperty("ssId");
if (ssId) {
DriveApp.getFileById(ssId).setTrashed(true);
prop.deleteProperty("ssId");
}
const inputUrl = e.parameter.url;
const re = new RegExp("(https?:\\/\\/docs\\.google\\.com\\/spreadsheets\\/d\\/e\\/2PACX-.+?\\/)");
if (!re.test(inputUrl)) return ContentService.createTextOutput("Wrong URL.");
const url = `${inputUrl.match(re)[1]}pub?output=xlsx`;
const blob = UrlFetchApp.fetch(url).getBlob();
const id = Drive.Files.insert({mimeType: MimeType.GOOGLE_SHEETS, title: "temp"}, blob).id;
prop.setProperty("ssId", id);
Drive.Revisions.update({published: true, publishedOutsideDomain: true, publishAuto: true}, id, 1);
const sheets = SpreadsheetApp.openById(id).getSheets();
const pubUrls = sheets.map(s => ({[s.getSheetName()]: `https://docs.google.com/spreadsheets/d/${id}/pubhtml?gid=${s.getSheetId()}`}));
return ContentService.createTextOutput(JSON.stringify(pubUrls)).setMimeType(ContentService.MimeType.JSON);
}
In this case, the GET method is used.
In this script, when the below curl command is run, the Google Spreadsheet is downloaded as a XLSX data, and the XLSX data is converted to Google Spreadsheet. Then, the converted Spreadsheet is published to the web. By this, the direct links of each sheet can be retrieved.
Also, in this script, it supposes that the original Spreadsheet is changed. So if you run the curl command again, the existing Spreadsheet is deleted and new Spreadsheet is created by downloading from the original Spreadsheet. In this case, the URLs are updated.
So if the Spreadsheet is not changed, you can continue to use the retrieved URLs. Of course, you can also directly use the downloaded and converted Spreadsheet.
3. Deploy Web Apps.
On the script editor, Open a dialog box by "Publish" -> "Deploy as web app".
Select "Me" for "Execute the app as:".
By this, the script is run as the owner.
Select "Anyone, even anonymous" for "Who has access to the app:".
In this case, no access token is required to be request. I think that I recommend this setting for your goal.
Of course, you can also use the access token. At that time, please set this to "Anyone".
Click "Deploy" button as new "Project version".
Automatically open a dialog box of "Authorization required".
Click "Review Permissions".
Select own account.
Click "Advanced" at "This app isn't verified".
Click "Go to ### project name ###(unsafe)"
Click "Allow" button.
Click "OK".
Copy the URL of Web Apps. It's like https://script.google.com/macros/s/###/exec.
When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.
4. Run the function using Web Apps.
This is a sample curl command for requesting Web Apps. Please set your Web Apps URL.
curl -L "https://script.google.com/macros/s/###/exec?url=https://docs.google.com/spreadsheets/d/e/2PACX-1vRrmEbjecLvXhbm409pa6JJXZd_ZXTG8Zt6OevIUs5Axq5oxlCZKU0QXk-2lW05HyXJ2B4Bzy3bG-4L/pubhtml"
In this case, the GET method is used at Web Apps side. So you can also directly access to the above URL using your browser.
Note:
When you modified the script of Web Apps, please redeploy the Web Apps as new version. By this, the latest script is reflected to the Web Apps. Please be careful this.
In this answer, I thought that you might use this from outside. So I used Web Apps. If you want to directly retrieved from the Google Apps Script, you can also use the following script.
function myFunction() {
const inputUrl = "https://docs.google.com/spreadsheets/d/e/2PACX-1vRrmEbjecLvXhbm409pa6JJXZd_ZXTG8Zt6OevIUs5Axq5oxlCZKU0QXk-2lW05HyXJ2B4Bzy3bG-4L/pubhtml";
const prop = PropertiesService.getScriptProperties();
const ssId = prop.getProperty("ssId");
if (ssId) {
DriveApp.getFileById(ssId).setTrashed(true);
prop.deleteProperty("ssId");
}
const re = new RegExp("(https?:\\/\\/docs\\.google\\.com\\/spreadsheets\\/d\\/e\\/2PACX-.+?\\/)");
if (!re.test(inputUrl)) throw new Error("Wrong URL.");
const url = `${inputUrl.match(re)[1]}pub?output=xlsx`;
const blob = UrlFetchApp.fetch(url).getBlob();
const id = Drive.Files.insert({mimeType: MimeType.GOOGLE_SHEETS, title: "temp"}, blob).id;
prop.setProperty("ssId", id);
Drive.Revisions.update({published: true, publishedOutsideDomain: true, publishAuto: true}, id, 1);
const sheets = SpreadsheetApp.openById(id).getSheets();
const pubUrls = sheets.map(s => ({[s.getSheetName()]: `https://docs.google.com/spreadsheets/d/${id}/pubhtml?gid=${s.getSheetId()}`}));
console.log(pubUrls); // You can see the URLs for each sheet at the log.
}
References:
Web Apps
Taking advantage of Web Apps with Google Apps Script
Advanced Google services
publish a Google Spreadsheet through Google Apps Scripts
Added:
As another workaround, when the original Spreadsheet is often changed, and the number of sheet is constant in the original Spreadsheet, and then, you want to retrieve only values, you can also use the following script. In this script, the URL is not changed even when the script is run again. So you can continue to use the URL.
Sample script:
function myFunction() {
const inputUrl = "https://docs.google.com/spreadsheets/d/e/2PACX-1vRrmEbjecLvXhbm409pa6JJXZd_ZXTG8Zt6OevIUs5Axq5oxlCZKU0QXk-2lW05HyXJ2B4Bzy3bG-4L/pubhtml";
const re = new RegExp("(https?:\\/\\/docs\\.google\\.com\\/spreadsheets\\/d\\/e\\/2PACX-.+?\\/)");
if (!re.test(inputUrl)) throw new Error("Wrong URL.");
const url = `${inputUrl.match(re)[1]}pub?output=xlsx`;
const blob = UrlFetchApp.fetch(url).getBlob();
const prop = PropertiesService.getScriptProperties();
let sheets;
let ssId = prop.getProperty("ssId");
if (ssId) {
const temp = Drive.Files.insert({mimeType: MimeType.GOOGLE_SHEETS, title: "tempSpreadsheet"}, blob).id;
const tempSheets = SpreadsheetApp.openById(temp).getSheets();
sheets = SpreadsheetApp.openById(ssId).getSheets();
tempSheets.forEach((e, i) => {
const values = e.getDataRange().getValues();
sheets[i].getRange(1, 1, values.length, values[0].length).setValues(values);
});
DriveApp.getFileById(temp).setTrashed(true);
} else {
ssId = Drive.Files.insert({mimeType: MimeType.GOOGLE_SHEETS, title: "copiedSpreadsheet"}, blob).id;
Drive.Revisions.update({published: true, publishedOutsideDomain: true, publishAuto: true}, ssId, 1);
prop.setProperty("ssId", ssId);
sheets = SpreadsheetApp.openById(ssId).getSheets();
}
const pubUrls = sheets.map(s => ({[s.getSheetName()]: `https://docs.google.com/spreadsheets/d/${ssId}/pubhtml?gid=${s.getSheetId()}`}));
console.log(pubUrls); // You can see the URLs for each sheet at the log.
}

Did anyone manage to get the id token from google sign in (Flutter)

I am trying to connect my users with my back end server , i used the example from the official google sign in plugin for flutter :
https://pub.dartlang.org/packages/google_sign_in
the sign process goes fine and i get the username and email ect..
but i need the id Token to authenticate the user with my server.
Ps: Not using firebase , only google sign in.
Can anyone guide me how to get the id Token ?
You can try using this
_googleSignIn.signIn().then((result){
result.authentication.then((googleKey){
print(googleKey.accessToken);
print(googleKey.idToken);
print(_googleSignIn.currentUser.displayName);
}).catchError((err){
print('inner error');
});
}).catchError((err){
print('error occured');
});
You can get access token and id token more simple like this:
final result = await _googleSignIn.signIn();
final ggAuth = await result.authentication;
print(ggAuth.idToken);
print(ggAuth.accessToken);
Or you also can add it to try-catch to handle an error.
try {
final result = await _googleSignIn.signIn();
final ggAuth = await result.authentication;
print(ggAuth.idToken);
print(ggAuth.accessToken);
} catch (error) {
print(error);
}
or try like this if id token was null, it worked for me.
As the docs point out you need oauth2 client id of your backend to request idToken or serverAuthCode.
from firebase google sigin in authentication copy the Web SDK configuration
add paste in the following to res/values/strings.xml, That should work
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="default_web_client_id">{Web app Client id goes here}</string>
</resources>
The issue may be related to not using firebase. There is a google-services.json file which is given to you when you register your app in firebase, and you can use that with google_sign_in (this is the default way shown in the documentation).
I was getting null for the token value when trying to implement this without the google-services.json, but successfully signing into google.
If you don't want to use firebase, you have to jump through a couple hoops.
In google cloud console, register your app.
Then make sure you are 'in' your app that you just created in the top drop down menu.
in "apis and services" in the sidebar menu, go through the create Oauth consent screen menu, I don't remember having to fill out many fields, so leave them blank if you don't know what to put in.
then go to the "credentials" menu in the sidebar, and click "Create New Credentials", and select OAuth2 client ID. Make a web client, even though you're trying to use it with an android/ios app.
Make a file android/app/src/main/res/values/strings.xml
using the web client we just made, insert <?xml version="1.0" encoding="utf-8"?> <resources> <string name="default_web_client_id">YOUR WEB CLIENT ID</string> </resources> into the strings.xml file.
[edit] make one more client in the google console for android, and put in your local machine's sha1 key. This step is done for you automatically if you're using firebase. In this case, you have to create both the web client and one for your android device. In production, you'd be using a specific client for your production app.
That should do it I believe, might have missed a step.
I also wanted to verify on my backend that the incoming idtoken was valid, so I had to also make a service account (in the apis and services -> credentials page) and use that in my go server.
I'm still struggling to get this to work with ios, but the android side works great.
To retrieve the Is idToken worked for me:
1. The google-services.json file must be placed in /android/app/
2. you need to add to your /android/app/build.gradle
apply plugin: 'com.google.gms.google-services'
3. and to /android/build.gradle
classpath 'com.google.gms:google-services:4.3.4'
And that's it. GoogleSignIn will return a real idToken instead of null.
font: https://github.com/flutter/flutter/issues/12140#issuecomment-348720774
One more clean way to achieve this:
late Map<String, dynamic> userObject = {};
var res = await _googleSignIn.signIn();
var googleKey = await res!.authentication;
userObject.addAll({
'accessToken': googleKey.accessToken,
'idToken': googleKey.idToken,
'displayName': res.displayName ?? '',
'email': res.email,
'id': res.id,
'avatarUrl': res.photoUrl ?? '',
'serverAuthCode': res.serverAuthCode ?? '',
});
I was struggling with this issue for about a month. Turns out I was getting the same access token, even when the user tried restarting the app. This was painful because my app dealt with scopes and in case a user misses to check one or more scopes in his first sign in, the app wouldn't work at all, even if he/she signs in again and gives the permissions.
Workaround which worked for me: I called the googleSignIn.currentUser.clearAuthCache() method followed by googleSignIn.signInSilently(). This returns a GoogleSignInAccount which can be used for further authentication. My guess is that the clearAuthCache() method clears the token cache and hence a new token is created. This should get you a new access token and let your app make valid calls.
I sincerely request Google developers to solve this issue. For now, this workaround is the only thing that worked.
Try this:
When you create your GoogleSignIn object:
GoogleSignIn(
clientId: "YOUR CLIENT ID"
)
i hope it helps ;)

slack api rtm.start missing_scope needed client

I have get access token and when I try to post rtm.start, I am getting below error:
{
error = "missing_scope";
needed = client;
ok = 0;
provided = "identify,read,post";
}
I have set the scope to read,post,identify in authorize API. I have read the API document over and over again. Only rtm.start mentioned client scope. But in oauth document I didn't find a client scope. So, what's wrong?
You have to do it before you get the token.
when you do the initial request to connect the app, include &scope="identify,read,post,client"
Under App Credentials get your Client ID and Client Secret.
Goto:
https://#{team}.slack.com/oauth/authorize?client_id=#{cid}&scope=client
replacing #{team} and #{cid} with your values.
When you approve the authorization you’ll goto that real url that doesn’t resolve. Copy the whole url to your clipboard and paste it into a text file. Extract out just the “code” part.
Now goto:
https://#{team}.slack.com/api/oauth.access?client_id=#{cid}&client_secret=#{cs}&code=#{code}"
And you’ll get back a token like:
xoxp-4422442222–3111111111–11111111118–11aeea211e
(from here: https://medium.com/#andrewarrow/how-to-get-slack-api-tokens-with-client-scope-e311856ebe9)

Best way to upload files to Box.com programmatically

I've read the whole Box.com developers api guide and spent hours on the web researching this particular question but I can't seem to find a definitive answer and I don't want to start creating a solution if I'm going down the wrong path. We have a production environment where as once we are finished working with files our production software system zips them up and saves them into a local server directory for archival purposes. This local path cannot be changed. My question is how can I programmatically upload these files to our Box.com account so we can archive these on the cloud? Everything I've read regarding this involves using OAuth2 to gain access to our account which I understand but it also requires the user to login. Since this is an internal process that is NOT exposed to outside users I want to be able to automate this otherwise it would not be feasable for us. I have no issues creating the programs to trigger everytime a new files gets saved all I need is to streamline the Box.com access.
I just went through the exact same set of questions and found out that currently you CANNOT bypass the OAuth process. However, their refresh token is now valid for 60 days which should make any custom setup a bit more sturdy. I still think, though, that having to use OAuth for an Enterprise setup is a very brittle implementation -- for the exact reason you stated: it's not feasible for some middleware application to have to rely on an OAuth authentication process.
My Solution:
Here's what I came up with. The following are the same steps as outlined in various box API docs and videos:
use this URL https://www.box.com/api/oauth2/authorize?response_type=code&client_id=[YOUR_CLIENT_ID]&state=[box-generated_state_security_token]
(go to https://developers.box.com/oauth/ to find the original one)
paste that URL into the browser and GO
authenticate and grant access
grab the resulting URL: http://0.0.0.0/?state=[box-generated_state_security_token]&code=[SOME_CODE]
and note the "code=" value.
open POSTMAN or Fiddler (or some other HTTP sniffer) and enter the following:
URL: https://www.box.com/api/oauth2/token
create URL encoded post data:
grant_type=authorization_code
client_id=[YOUR CLIENT ID]
client_secret=[YOUR CLIENT SECRET]
code= < enter the code from step 4 >
send the request and retrieve the resulting JSON data:
{
"access_token": "[YOUR SHINY NEW ACCESS TOKEN]",
"expires_in": 4255,
"restricted_to": [],
"refresh_token": "[YOUR HELPFUL REFRESH TOKEN]",
"token_type": "bearer"
}
In my application I save both auth token and refresh token in a format where I can easily go and replace them if something goes awry down the road. Then, I check my authentication each time I call into the API. If I get an authorization exception back I refresh my token programmatically, which you can do! Using the BoxApi.V2 .NET SDK this happens like so:
var authenticator = new TokenProvider(_clientId, _clientSecret);
// calling the 'RefreshAccessToken' method in the SDK
var newAuthToken = authenticator.RefreshAccessToken([YOUR EXISTING REFRESH TOKEN]);
// write the new token back to my data store.
Save(newAuthToken);
Hope this helped!
If I understand correctly you want the entire process to be automated so it would not require a user login (i.e run a script and the file is uploaded).
Well, it is possible. I am a rookie developer so excuse me if I'm not using the correct terms.
Anyway, this can be accomplished by using cURL.
First you need to define some variables, your user credentials (username and password), your client id and client secret given by Box (found in your app), your redirect URI and state (used for extra safety if I understand correctly).
The oAuth2.0 is a 4 step authentication process and you're going to need to go through each step individually.
The first step would be setting a curl instance:
curl_setopt_array($curl, array(
CURLOPT_URL => "https://app.box.com/api/oauth2/authorize",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "content-type: application/x-www-form-urlencoded",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS =>
"response_type=code&client_id=".$CLIENT_ID."&state=".$STATE,
));
This will return an html text with a request token, you will need it for the next step so I would save the entire output to a variable and grep the tag with the request token (the tag has a "name" = "request_token" and a "value" which is the actual token).
Next step you will need to send another curl request to the same url, this time the post fields should include the request token, user name and password as follows:
CURLOPT_POSTFIELDS => "response_type=code&client_id=".$CLIENT_ID."&state=".$STATE."&request_token=".$REQ_TOKEN."&login=".$USER_LOGIN."&password=".$PASSWORD
At this point you should also set a cookie file:
CURLOPT_COOKIEFILE => $COOKIE, (where $COOKIE is the path to the cookie file)
This will return another html text output, use the same method to grep the token which has the name "ic".
For the next step you're going to need to send a post request to the same url. It should include the postfields:
response_type=code&client_id=".$CLIENT_ID."&state=".$STATE."&redirect_uri=".$REDIRECT_URI."&doconsent=doconsent&scope=root_readwrite&ic=".$IC
Be sure to set the curl request to use the cookie file you set earlier like this:
CURLOPT_COOKIEFILE => $COOKIE,
and include the header in the request:
CURLOPT_HEADER => true,
At step (if done by browser) you will be redirected to a URL which looks as described above:
http://0.0.0.0(*redirect uri*)/?state=[box-generated_state_security_token]&code=[SOME_CODE] and note the "code=" value.
Grab the value of "code".
Final step!
send a new cur request to https//app.box.com/api/oauth2/token
This should include fields:
CURLOPT_POSTFIELDS => "grant_type=authorization_code&code=".$CODE."&client_id=".$CLIENT_ID."&client_secret=".$CLIENT_SECRET,
This will return a string containing "access token", "Expiration" and "Refresh token".
These are the tokens needed for the upload.
read about the use of them here:
https://box-content.readme.io/reference#upload-a-file
Hope this is somewhat helpful.
P.S,
I separated the https on purpuse (Stackoverflow wont let me post an answer with more than 1 url :D)
this is for PHP cURL. It is also possible to do the same using Bash cURL.
For anyone looking into this recently, the best way to do this is to create a Limited Access App in Box.
This will let you create an access token which you can use for server to server communication. It's simple to then upload a file (example in NodeJS):
import box from "box-node-sdk";
import fs from "fs";
(async function (){
const client = box.getBasicClient(YOUR_ACCESS_TOKEN);
await client.files.uploadFile(BOX_FOLDER_ID, FILE_NAME, fs.createReadStream(LOCAL_FILE_PATH));
})();
Have you thought about creating a box 'integration' user for this particular purpose. It seems like uploads have to be made with a Box account. It sounds like you are trying to do an anonymous upload. I think box, like most services, including stackoverflow don't want anonymous uploads.
You could create a system user. Go do the Oauth2 dance and store just the refresh token somewhere safe. Then as the first step of your script waking up go use the refresh token and store the new refresh token. Then upload all your files.

OAuth 2.0 with Google Analytics API v3

I used to be able to query the Google Analytics API with my account's login & password.
Google is now using OAuth for authentication which is great...
The only issue is that I only need ONE access token.
I don't wanna allow other users to fetch THEIR analytics data.
I just wanna be able to fetch MY data.
Is there a way I can generate an access token only for my app or my analytics account?
I know such solutions exists... For instance, Twitter provides what they call a "single-user oauth" for apps that don't require a specific user to sign in.
One again, all I'm trying to accomplish here is to fetch MY OWN analytics data via the API.
Is there a way to properly do that?
I'm adding a PHP answer - you may be able to adjust or convert it to garb / ruby code.
You should be able to use Analytics with service accounts now. You will indeed have to use a private key instead of an access token.
Create an app in the API Console
Basically, you go to the Google API Console and create an App.
Enable Google Analytics in the services tab.
In the API Access tab, create a new OAuth ID (Create another client ID... button), select service account and download your private key (Generate new key... link). You'll have to upload the key to your web server later.
On the API Access page, in the Service account section, copy the email address (#developer.gserviceaccount.com) and add a new user with this email address to your Google Analytics profile. If you do not do this, you'll get some nice errors
Code
Download the latest Google PHP Client off SVN (from the command line svn checkout http://google-api-php-client.googlecode.com/svn/trunk/ google-api-php-client-read-only).
You can now access the Analytics API in code:
require_once 'Google_Client.php';
require_once 'contrib/Google_AnalyticsService.php';
$keyfile = 'dsdfdss0sdfsdsdfsdf44923dfs9023-privatekey.p12';
// Initialise the Google Client object
$client = new Google_Client();
$client->setApplicationName('Your product name');
$client->setAssertionCredentials(
new Google_AssertionCredentials(
'11122233344#developer.gserviceaccount.com',
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents($keyfile)
)
);
// Get this from the Google Console, API Access page
$client->setClientId('11122233344.apps.googleusercontent.com');
$client->setAccessType('offline_access');
$analytics = new Google_AnalyticsService($client);
// We have finished setting up the connection,
// now get some data and output the number of visits this week.
// Your analytics profile id. (Admin -> Profile Settings -> Profile ID)
$analytics_id = 'ga:1234';
$lastWeek = date('Y-m-d', strtotime('-1 week'));
$today = date('Y-m-d');
try {
$results = $analytics->data_ga->get($analytics_id,
$lastWeek,
$today,'ga:visits');
echo '<b>Number of visits this week:</b> ';
echo $results['totalsForAllResults']['ga:visits'];
} catch(Exception $e) {
echo 'There was an error : - ' . $e->getMessage();
}
Terry Seidler answered this nicely for php. I want to add a java code example.
Api console setup
Start by doing the required steps in the google api console as Terry explained:
Basically, you go to the Google API Console and create an App. Enable
Google Analytics in the services tab. In the API Access tab, create a
new OAuth ID (Create another client ID... button), select service
account and download your private key (Generate new key... link).
You'll have to upload the key to your web server later.
On the API Access page, in the Service account section, copy the email
address (#developer.gserviceaccount.com) and add a new user with this
email address to your Google Analytics profile. If you do not do this,
you'll get some nice errors
Get the necessary libraries
Download the google analytics java client from:
https://developers.google.com/api-client-library/java/apis/analytics/v3
Or add the following maven dependencies:
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-analytics</artifactId>
<version>v3-rev94-1.18.0-rc</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson</artifactId>
<version>1.18.0-rc</version>
</dependency>
Now for the code:
public class HellowAnalyticsV3Api {
private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
public void analyticsExample() {
// This is the .p12 file you got from the google api console by clicking generate new key
File analyticsKeyFile = new File(<p12FilePath>);
// This is the service account email address that you can find in the api console
String apiEmail = <something#developer.gserviceaccount.com>;
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(apiEmail)
.setServiceAccountScopes(Arrays.asList(AnalyticsScopes.ANALYTICS_READONLY))
.setServiceAccountPrivateKeyFromP12File(analyticsPrivateKeyFile).build();
Analytics analyticsService = new Analytics.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(<your application name>)
.build();
String startDate = "2014-01-03";
String endDate = "2014-03-03";
String mertrics = "ga:sessions,ga:timeOnPage";
// Use the analytics object build a query
Get get = analyticsService.data().ga().get(tableId, startDate, endDate, mertrics);
get.setDimensions("ga:city");
get.setFilters("ga:country==Canada");
get.setSort("-ga:sessions");
// Run the query
GaData data = get.execute();
// Do something with the data
if (data.getRows() != null) {
for (List<String> row : data.getRows()) {
System.out.println(row);
}
}
}
You can use a refresh token. Store the refresh token in a db or secure config file, then use it to show the stats.
Google API Offline Access Using OAuth 2.0 Refresh Token will give you an idea of how to capture then store your refresh token.
See also Using OAuth 2.0 for Web Server Applications - Offline Access
Hello I found a solution, it works for me
you have to change this one
immediate: true
to
immediate: false
and it looks like
function checkAuth() {
gapi.auth.authorize({
client_id: clientId, scope: scopes, immediate: false}, handleAuthResult);
}
Google has the 'Service Account' (Calls Google APIs on behalf of your application instead of an end-user), but the way it works is a bit different as it won't use access tokens but a private key instead.
You can find more details at https://developers.google.com/accounts/docs/OAuth2ServiceAccount

Resources