How to set access token on analytics API? - javascript

i was wondering, the documentation has tutorials for implementing use of the Analytics API in several languages.
Now in PHP they show how to store the access token and maintain it , now i assume the JS somehow mentains it in some sort of local storage but i don't wish the user to authenticate each time he visitis so my plan is to save the access & refresh token in my database and simply applying it to the client-side instead of going through the all pop up procress.
According to tutorial this :
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, result);
Fires the popup which returns the access token but i'll say again i'm intrested in submiting token from database.
How can that be done?
is there some gapi.auth.setToken(token) method which after i could make calls to Core Reporting API?

I arrived here looking for a solution using this after having already written PHP to do the auth using google's PHP client libraries. I wanted to share the stored token as you mentioned, and be able to use javascript without re-authenticating, and/or triggering the popup (there may be a solution to this using the .init(callback) method, see docs/links at end).
Is there some gapi.auth.setToken(token) method
It turns out you can, there is the exact setToken(token) function you mention, and, you can even share the auth token generated earlier in PHP. What I'm not sure about yet, is if we should do it :)
I'm using PHP to do the initial auth, but presumeably in the javascript client you'd be able to call setToken() on something that you'd stored with getToken() in the same manner as this example. There may also be better approaches to this, like CORS (see links at end) mentioned in the API Authentication docs that I haven't had a chance to investigate any of these yet, but, I can give an example to answer the question, and might be useful to others needing the same behaviour
I first found Google developer Dan Holevoet's blog post with some sample JS code.
http://googleappsdeveloper.blogspot.com.au/2011/12/using-new-js-library-to-unlock-power-of.html
It's great to be able to query the API directly with javascript, and dynamically load lists etc, but the thing that worried me about this of course was storing clientid etc in js..
// Snippet from Dan's post
var clientId = 'YOUR_CLIENT_ID';
var apiKey = 'YOUR_API_KEY';
var scopes = 'https://www.googleapis.com/auth/calendar';
function handleClientLoad() {
gapi.client.setApiKey(apiKey);
window.setTimeout(checkAuth,1);
checkAuth();
}
But, according to Dan in an answer to the same question:
The apiKey is used in conjunction with designated referrers, which you
must declare in the APIs Console. If the key is sent from an
unauthorized referrer, it will not work. You should make your accepted
referrer list as limited as possible to ensure that others do not use
your apiKey for their own requests.
Now, my example is for the calendar API, but it all seems pretty consistent with the other APIs as well.
Note: This snippet was for proof-of-concept purposes only, and probably shouldn't be used in production. I assume the referrer protection mentioned makes something like this OK to do, but more thought needs to be given. It could be done by hidden input, AJAX call etc.. But in the end, they're all going to be visible in the javascript.
What I did to test the concept was to:
Authenticate via PHP client libs, using the same script/URL as callback (see [API console][2] for these callbacks)
On sucessful auth, in callback, set a global javascript variable in the page to the stored PHP auth token
Once page is loaded, on your first click event to use the javascript (or even in document ready), call authMe() to set the token
Then proceed as normal, calling any javascript API methods that you have given scope to in the initial PHP authentication process (in this case makeApiCall())
Like so:
In the php callback routine, regardless of whether authenticated yet (assuming that your callback URL is the same script), make this var global
<script type="text/javascript">
// A place to stick PHP's auth token once the auth dance is done
var dodgey_global_access_token = {};
</script>
Now, in php callback routine once we've checked that we're authenticated, and $_SESSION['token'] = $client->getAccessToken(); has been called (IE storing the auth token somewhere for later), or at least $client->getAccessToken() has something meaningful:
<script type="text/javascript">
// Set the js var via PHP here.. Yeck... Note json encode in php and parse in jquery
dodgey_global_access_token = $.parseJSON (<?php echo json_encode ($client->getAccessToken() ); ?>);
// dodgey_global_access_token now contains the auth token structure
// Removed auth-related functions in Dan's code - we'll already have a token
// Dan's orig function to list events in 'primary' calendar
function makeApiCall() {
gapi.client.load('calendar', 'v3', function() {
var request = gapi.client.calendar.events.list({
'calendarId': 'primary'
});
request.execute(function(resp) {
for (var i = 0; i < resp.items.length; i++) {
var li = document.createElement('li');
li.appendChild(document.createTextNode(resp.items[i].summary));
document.getElementById('events').appendChild(li);
}
});
});
}
// My function to setToken with the token injected from PHP authentication
function authMe () {
// Stuff the token into the gapi object
gapi.auth.setToken( dodgey_global_access_token );
// Now call the original 'makeAPICall' function now that we're 'authenticated'
makeApiCall();
}
</script>
Note: I used jquery in my example to quickly parse the JSON, we're already using it in the project, but if not, you'll have to find another library to do so
Relevant/useful docs:
// Sorry, as a new poster I can only post 2 hyperlinks,
// so embedding this in code snippet
//
// http://code.google.com/p/google-api-javascript-client/wiki/ReferenceDocs#gapi
// http://code.google.com/p/google-api-javascript-client/wiki/Authentication
// http://code.google.com/p/google-api-javascript-client/issues/detail?id=22
// http://code.google.com/p/google-api-javascript-client/wiki/CORS
// https://code.google.com/apis/console
Let me know if anything's unclear, and can post a working sample to demo.

Google API documentation has changed a bit from when this answer was first provided. google-api-javascript-client is no longer the recommended library for accessing google api libraries and Google suggests using discovery documents to load specific libraries.
As a result, the workflow that you are looking for in order to load all the libraries and set the access token would look like this:
var token = 'someaccesstokenfromoauth2'
gapi.load('client:auth2', function(){
gapi.client.load(
'https://analyticsreporting.googleapis.com/$discovery/rest',
'v4'
).then(function(){
gapi.auth.setToken({ access_token: token })
// business logic with gapi.client.analyticsreporting()
})
})
Load gapi with:
<script src="https://apis.google.com/js/api.js"></script>

Related

How to use the WP REST API with a custom endpoint using the Javascript library?

I have a custom endpoint which does nothing but return a test string. I can reach that endpoint by navigating to mydomain.com/wp-json/mytools/v1/method/get_user_data and it correctly returns my test string, but, I want to be able to reach that endpoint using Javascript, and, I read that the wp-api handles authentication automatically so I should be able to get a current logged in user with this method.
What I need is to be able to use something like wp.api.mytools.method.get_current_user and get the information for the currently logged in user. Is this even possible?
This is the way I created the endpoint:
register_rest_route( 'mytools/v1', '/method/(?P<method>[\w]+)', array(
'methods' => 'GET',
'callback' => 'invoke_method',
));
And this is the invoke_method function:
function invoke_method( WP_REST_Request $request ) {
return wp_get_current_user();
}
This functionality is already implemented by WordPress at the WP_REST endpoint '.../wp-json/wp/v2/users/me. In addition to the logged-in cookie WP REST authentication requires a nonce specified by a query argument '_wpnonce'. The value of this nonce is generated by calling wp_create_nonce( 'wp_rest' ). A normal WordPress front-end page will include the script .../wp-includes/js/api-request.js. This script will define a global wpApiSettings.nonce which will contain this nonce so you can use the request '.../wp-json/wp/v2/users/me?_wpnonce=' + wpApiSettings.nonce. So, you can use jQuery.get().
jQuery.get(
'.../wp-json/wp/v2/users/me?_wpnonce=' + wpApiSettings.nonce,
function( response ) {
var userData = JSON.parse( response );
) }
);
If you only want to get the current user I don't think you need Backbone.js. Backbone.js will synchronise collections and models using CRUD and you are not doing any of this.
Overall, yes, it IS possible.
Specifically, if wp-api if you're referring to the node-wpapi JS library, then yes it does handle authentication. Otherwise, you will need to implement Authentication yourself, using Cookie, Nonce, Basic-Auth or JWT.
For second part, it is definitely possible to use something like wp.api.mytools.method.get_current_user to get information. What you'll need is a client library (node-wpapi), and extend it to include your classes and functions, such as mytools and method.
Hope this helps to clarify

Update context variables using .js. Its possible?

i'm trying to send a user name to my WCS but i not sure how can i do that using a request. My consersation ask for the user email and use a js script to return a json from my sql server...
I'm doing something like that:
What's your email? // WCS
caique.rodrigues#test.com //USER
Just a minute.<script>getUserInformation('caique.rodrigues#test.com');</script> // WCS
nodeTrue //USER (I sent this after confirmated if the user exist and got the user name.)
Hi <span id='myText'></span><script>document.getElementById('myText').innerHTML = userName;</script>! //WCS
I know this is not the best way to do that but it is working. I'm trying to call my js functions using something like "output:{'action':}" (And handle it in my node.js like the 'car dashboard sample'), but, it's possible send a varible from my .js to a conversation context?
I had the same problem a few months ago. In this case, I used functions for access the context variables on the client side (Using this example from Ashley and accessing the context), but, for security issues of some company data, I did need to use custom code in the server-side... And, for this case, you can use the method call for Watson Conversation, and access the context variables and creates values with custom code in your favor.
Something like this:
conversation.message(payload, function (err, data) {
data.context.yourValue = returnFromYourDatabase;
if (err) {
return res.status(err.code || 500).json(err);
}
updateMessage(payload, data, req, res);
});
});
You can see the function updateMessage, this call is one example from IBM Developers, and this function is used to update the message in every request. You can use this function to set too, because this function get the parameters from the call.
For example:
function updateMessage(input, response) {
response.context.yourValue = returnFromYourDatabase;
var responseText = null;
if (!response.output) {
response.output = {};
}
}
See API Reference for Watson Conversation Service using Node.js.
See the Project with Node.js by IBM Developers.

Google Execution API with Simple Access API key to access AUTHORS spreadsheet?

From what I understand, deploying a Google Script as a Google Execution API allows me to call each function from my script separately as and when I need it.
I have a webpage with some buttons and forms that I want to run the functions within my script on.
I have a Google Script with some (example) functionality:
function addPlayer(name,email,group) {
//name email group
var ss = SpreadsheetApp.openById(SHEET_ID); //Sheet belonging to me, script author.
var sheet = ss.getSheetByName("Players");
sheet.appendRow(new Date(),name,email,group);
}
function updatePlayer() {
//update player row with new data
//name email group
}
function anotherFunction() {
//store some data in another sheet within spreadsheet.
}
function listPlayers()
{
//return data from sheet
}
And a sample webpage which wants to run functions from that script:
function OnLoadCallback() { //on gapi load
gapi.client.setApiKey(API_KEY); //developer dashboard generated browser API key
// Create execution request.
var request = {
'function': 'addPlayer',
'parameters': [name,email,group],
'devMode': true
};
// Make the request.
var op = gapi.client.request({
'root': 'https://script.googleapis.com',
'path': 'v1/scripts/' + scriptId + ':run',
'method': 'POST',
'body': request
});
}
I get a 401 UNAUTHENTICATED error at the moment saying I do not have valid auth credentials.
Is it possible for this webpage to use the API without requiring each webpage visitor to oAuth (which doesn't make sense to me as it's not THEIR data/sheet I am trying to access but my own? I know if I deploy as web app I can set it to execute AS me, but is there any similar equivalent for the Execution API?
I chose to use execution script as I need to be able to run several different functions, and as a webapp my only option would be the doPost() which wouldn't let me differentiate adding to sheets/updating sheets/reading from sheets easily?
Am I missing something completely here? If this is entirely the wrong approach I would be super grateful if someone could point me in the right direction.
Thanks!
Based on this SO question, by adding SpreadsheetApp calls, you've modified the authentication scope required for your script. You need to update your scope to include Spreadsheets.
To use the API, you must supply a valid OAuth token that covers all the scopes used by the script. To find the correct scopes to include in the authentication token, open the project in the script editor, then select File > Project properties and click the Scopes tab.
Here is the link for the list of OAuth scope.
Check also this SO question for more information.

Authorizing xAPI interactions through Javascript triggers against my LRS

I've constructed a course in Storyline2, and defined several triggers via javascript as xAPI (tincan) activities.
I have an LRS endpoint link and authorization token, but I'm yet to understand where these credentials should be embedded in order for the whole thing to function properly.
I was given this at another message board:
var tincan = new TinCan({url: window.location.href});
Which of these needs to be replaced by one of the above mentioned? I'm guessing another should be added via "+" after "href".
That example code (which I guess you got from the article I wrote here: http://tincanapi.com/share-statements-between-courses/ ) is envisaging that you will launch the Storyline content from something like an LMS. In that case you will enter the endpoint and authorization details in the LMS settings, and the LMS will pass those to Storyline.
See: http://tincanapi.com/share-statements-between-courses/
If you want to put the details directly in the package, see the example code here: http://rusticisoftware.github.io/TinCanJS/
(included below for convenience)
var lrs;
try {
lrs = new TinCan.LRS(
{
endpoint: "https://cloud.scorm.com/tc/public/",
username: "<Test User>",
password: "<Test Password>",
allowFail: false
}
);
}
catch (ex) {
console.log("Failed to setup LRS object: " + ex);
// TODO: do something with error, can't communicate with LRS
}

Google Tag Manager - read cookie just after they are set

I need to read cookie that are set by Google Tag Manager.
Right now if Google Tag Manager is loaded first time for end-user I can't read cookies (because it happens later, but not immediately).
Is there a good way (callback?) that can help me to read cookies once they are set? This issue is only relevant if user visits page first time.
From the discussion in the comments below the question, I would suggest the following solution (assuming you also send Pageviews to Google Analytics). Examples are based on Simo Ahava's (excellent) blog.
(Please note that I haven't had the opportunity to test it thoroughly, as I am currently unable to create a complete test case for this setup -- there might be some hiccups)
1. Create a Variable to read the _ga cookie
Reference: https://www.simoahava.com/analytics/macro-magic-google-tag-manager/#1-client-time
This will return the value for the cookie with name specified (be careful in where you use the value read, as there is always a chance that cookies are rejected by the User's browser policies).
Create a new Variable, with:
Variable Name of GA Cookie
Cookie Name of _ga
(source: simoahava.com)
2. Define a callBackFunction
Reference: https://www.simoahava.com/analytics/macro-magic-google-tag-manager/#8-hitcallback-with-a-universal-analytics-tag & https://www.simoahava.com/analytics/macro-magic-google-tag-manager/#6-get-clientid-using-_ga-cookie
This callback function will be executed right after the Pageview is sent (i.e. after the _ga cookie is set).
Create a Custom JavaScript Macro with the following code:
function () {
return function () {
// Code to be executed in order to read the cookie:
try {
var gaCookie = {{GA Cookie}};
// Do what you need to with the cookie here:
// ...
return gaCookie;
} catch (e) {
console.log('No Universal Analytics cookie found.');
return 'N/A';
}
}
}
3. Define a hitCallback after sending the Pageview
Reference: https://www.simoahava.com/analytics/macro-magic-google-tag-manager/#8-hitcallback-with-a-universal-analytics-tag
This will execute the callback function you just defined right after the Pageview is sent.
In the Fields to set option of your Pageview Tag, set:
Field Name to hitCallback
Value to {{callBackFunction}}
Hope it can help you move forward.

Categories

Resources