I'm showing Google's charts in some web pages. But I can't assure my clients will have network access to Google: a client computer will be in the same LAN as my web server (which can access Google), but I'm not guaranteed all the clients will have access outside the LAN.
I'd like to show data using Google Charts to those clients who can access it, and a plain HTML table to those who don't.
I tried setting a variable to false, and changing it to true in a method called when the Google Visualization API is loaded:
var canAccessGoogleVisualizationVar = false;
google.load('visualization', '1', {packages: ['corechart'], callback: canAccessGoogleVisualization});
function canAccessGoogleVisualization()
{
canAccessGoogleVisualizationVar = true;
}
But it doesn't seem to work.
How can I know from the client side if the Google Visualization is accesible or not?
Update: The code above didn't work because of the following code (which I didn't post before as I thought wasn't meaningful):
google.setOnLoadCallback(drawVisualization);
function drawVisualization()
{
// Check if Google Visualization is loaded
if (!canAccessGoogleVisualizationVar) {
alert('Can't access Google Visualization');
}
// The following code can be any of the samples from Google (see http://code.google.com/apis/ajax/playground/?type=visualization#pie_chart).
var data = new google.visualization.DataTable();
// Add columns and values to data
...
// Call new google.visualization.AnyChartBuilderFromTheAPI(<element>).draw(data);
}
I noticed my code didn't work because, if canAccessGoogleVisualizationVar == true, the if branch isn't taken, and if its false, the function drawVisualization() wouldn't have been executed.
So I took the if-test outside the function:
google.setOnLoadCallback(drawVisualization);
function drawVisualization()
{
// Any drawVisualization unchanged from the samples from Google (see http://code.google.com/apis/ajax/playground/?type=visualization#pie_chart).
}
// Check if Google Visualization is loaded at the end of this <script> </script>
if (!canAccessGoogleVisualizationVar) {
alert('Can't access Google Visualization');
}
</script>
But now it's not working because the evaluation if (!canAccessGoogleVisualizationVar) is being executed before the line google.load(?, ?, canAccessGoogleVisualization); calls the method canAccessGoogleVisualization().
How can I be sure I'm reading the value of canAccessGoogleVisualizationVar after having tried to execute the call to google.load(...);?
You can try
function canAccessGoogleVisualization()
{
if ((typeof google === 'undefined') || (typeof google.visualization === 'undefined')) {
return false;
}
else{
return true;
}
}
Related
I'm trying to show the Google Optimize variant in Google Tag Manager.
I tried to implement it by "Custom JavaScript Variable":
function() {
var property = window.keys(gaData);
var experiment_nr = window.keys(window.gaData[property].experiments);
var experiment_value = window.values(window.gaData[property].experiments).toString()
if (experiment_value == "") {
return "0"
} else {
return experiment_value
}
}
This is the result of it:
Then I tried to test my code with a 5 sec delayed trigger:
And this is the result of the DevTools JS console:
As you can see, the console does not accept it with GTM but accepts it when I type it manually in.
Can someone help me there?
The answer was actually quite simple.
Google Optimize uses a cookie called _gaexp.
There, you get a string summing up the Google Optimize experiment ID as well as the version at the very end:
GAX1.2.wHL2IJUnSg2n8PB4iQH66w.18362.1
All I had to do was to create a new variable reading the cookie:
New variable
1st Party Cookie with the cookie name "_gaexp"
You can of course get the cookie name with JavaScript by simply calling Cookies.get('_gaexp') from the DevTools Console (to check if the cookie value is right)
The _gaexp value has to be manipulated to isolate the variant:
New variable
Custom JavaScript
Add the following code:
function (){
if ({{GA_Optimize_Variable}}=='undefined'){
return '0'
} else {
return {{GA_Optimize_Variable}}.charAt({{GA_Optimize_Variable}}.length-1)
}
}
The _gaexp is not existant when Google Optimize leads your traffic to the original variant of the website. Therefore, a if statement is needed.
Finally, you can use your variable in Google Analytics events and/or dimension.
Try to using dataLayer instead of window object.
I am trying to force the Page Tracking on my site (see: Link). I am using a TMS, but not Google Tag Manager.
What I am hoping to achieve is prepend the market name to the URI which I can pull out of my site's dataLayer (variable = dataLayer.language and thus the new Page Path: dataLayer.language.substring(0,2)+document.location.pathname e.g. /en/pagepath1/pagepath2.
I've created a script below to define this.
There is a small complication here in that some of the pages already have the country/language variation passed in the URL so I have a regular expression to search for the market/language ISO code (lower case) to help perform an if statement that returns document.location.pathname where this is the case.
My script below however, seems to be fine but in testing it is returning "undefined" does anyone why this must be the case?
function PagePath() {
var StandardPagePath = document.location.pathname;
var NewPagePath = dataLayer.language.substring(0, 2) + document.location.pathname;
var LocaleRegExPatt = /^(at|cn|cz|de|dk|en|eu|fr|it|nl|no|pl|pt|pt-br|se)\//
try {
if (StandardPagePath.includes(LocaleRegExPatt)) {
return (StandardPagePath);
} else {
return (NewPagePath)
}
} catch (err) {}
}
My second question is how can I reference this function to pass through to the page tracking i.e. set the page here:
ga('set', 'page', {{PagePath function here}} );
Thanks in advance
Prelog:
I have implemented Google maps and Geolocation as a independent widgets, Now the user have the ability to add the widget as much as he wants in a page he is owns.
I am using $.getScript(URl, callback) to load the script for that URL to work.
Problem :
When the user add both the widgets or the same widget multiple times in a same page , the check windows.google fails and the $.getScript(url, callback) gets executed twice. Due to which I get an error from the Google Script
You have included the Google Maps JavaScript API multiple times on
this page. This may cause unexpected errors. when called using
$.getScript()
if(window.google !== undefined && window.google !== null) {
onScriptLoad(null, null, 200);
} else {
$.getScript(googleUrl, onScriptLoad);
}
The above line exists in both the widget and both the widgets are independent of each other. It always goes into the else block of both the functions.
Looking forward for some work around here, like to load the script synchronously using javascript or jquery
when your code runs in the first widget, it initiates the loading of the google API, however window.google isn't created until the script completes loading. This is asynchronous
Now, the second widget tests if window.google exists, but this is still happening before the google API loads, therefore, it too thinks it needs to load google API
so, instead of this:
if(window.google !== undefined && window.google !== null) {
onScriptLoad(null, null, 200);
} else {
$.getScript(googleUrl, onScriptLoad);
}
try
window.loadingGoogleApi = window.loadingGoogleApi || $.getScript(googleUrl);
window.loadingGoogleApi.then(onScriptLoad);
the loadingGoogleApi can be any name you choose (just don't use something that will be clobbered by other code)
I'm using a script within my Sheets document to grab data from Google Search Console. The script uses an OAuth2 library from GitHub, which seems to work perfectly most of the time.
I'm using a function to check whether the user still has API access - called hasAccess() - in order to display menu items appropriately. The trouble is, though the function works everywhere else, it doesn't work in the onOpen function... the place I really need it to!
I was wondering whether this had anything to do with permissions? Any help would be greatly appreciated, as I'm losing the will to live!
You can see my code here (I've cut out most of the bits that seemed irrelevant):
// Setup on sheet open
function onOpen(e) {
// Set date validation
range = sheet.getRange('A2:A');
range.setDataValidation(dateRule);
// Check auth mode
if (e && e.authMode === ScriptApp.AuthMode.NONE) {
// Add an enable menu item (works in all authorization modes).
menu.addItem('Enable add-on', 'onOpen');
} else {
// Add setup option
menu
.addItem('Setup', 'setupDialog')
.addToUi();
// Check if API service has been authorized and allow functions
var service = getService();
// THE FOLLOWING RESULT IS ALWAYS FALSE :(
Logger.log(service.hasAccess());
if (service.hasAccess()) {
// Add start option
menu
.addItem('Start', 'startDialog')
.addToUi();
// Add get dates option
menu
.addItem('Get dates', 'getDates')
.addToUi();
}
}
// Add help option
menu
.addItem('Help...', 'helpDialog')
.addToUi();
}
function test() {
var service = getService();
// BUT THIS WORKS..?
Logger.log(service.hasAccess());
}
/*** OAUTH2 FUNCTIONS ***/
// Much of the following is adapted from Martin Hawksey's OAuth2 solution for Blogger - check it out!
// https://mashe.hawksey.info/2015/10/setting-up-oauth2-access-with-google-apps-script-blogger-api-example/
// Create OAuth2 service using library
function getService() {
// Create a new service with the given name. The name will be used when
// persisting the authorized token, so ensure it is unique within the
// scope of the property store.
return OAuth2.createService('searchConsole')
// Set the endpoint URLs, which are the same for all Google services.
.setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
// Set the client ID and secret, from the Google Developers Console.
.setClientId(userProperties.getProperty('clientId'))
.setClientSecret(userProperties.getProperty('clientSecret'))
// Set the name of the callback function in the script referenced
// above that should be invoked to complete the OAuth flow.
.setCallbackFunction('authCallback')
// Set the property store where authorized tokens should be persisted.
.setPropertyStore(PropertiesService.getUserProperties())
// Set the scopes to request (space-separated for Google services).
// this is blogger read only scope for write access is:
// https://www.googleapis.com/auth/blogger
.setScope('https://www.googleapis.com/auth/webmasters.readonly')
// Below are Google-specific OAuth2 parameters.
// Sets the login hint, which will prevent the account chooser screen
// from being shown to users logged in with multiple accounts.
.setParam('login_hint', Session.getActiveUser().getEmail())
// Requests offline access.
.setParam('access_type', 'offline')
// Forces the approval prompt every time. This is useful for testing,
// but not desirable in a production application.
.setParam('approval_prompt', 'force');
}
// Handle OAuth2 callback
function authCallback(request) {
var searchConsoleService = getService(),
isAuthorized = searchConsoleService.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput('Success! You can close this tab.');
} else {
return HtmlService.createHtmlOutput('Denied. You can close this tab');
}
}
The way I made for make onOpen function to works is as follows:
Create the onOpen function with your custom code (i.e. the functionality).
In your main function - the one that executes once the spreadsheet is open - , add the followind code:
// Set trigger programatically - adding the "onOpen" function:
ScriptApp.newTrigger("onOpen")
.forSpreadsheet(SPREADSHEET_ID)
.onOpen()
.create();
This is the full code:
/** This is the main function that executes once the spreadsheet is open: */
function startProgram() {
// Set trigger programatically - adding the "onOpen" function:
ScriptApp.newTrigger("onOpen")
.forSpreadsheet(SPREADSHEET_ID)
.onOpen()
.create();
}
/** onOpen function that adds items to select in the spreadsheet: */
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('My Menu')
.addItem('Show message', 'showMessage_') // This is the name of the function to call.
.addToUi();
}
/** Show alert message. */
function loadCards_() {
SpreadsheetApp.getUi().alert("Today is: " + new Date());
}
Then, execute the code and reload/refresh the spreadsheet. You'll see the new menu with the item added to the spreadsheet.
I've been playing with the multiple address look up API from blockchain info (documented here https://blockchain.info/api/blockchain_api), I had my code working earlier in the day but bizzarely it's stopped.
The purpose of it is to eventually write a little JQuery library which will search the DOM for bitcoin addresses as data attributes and then insert the final balance into that element creating a polling mechanism to keep the page updated as well.
The original problem I ran into earlier while developing it was because it's a CORS ajax request but later I adjusted the query per the blockchain info API documents and I added cors=true it then seemed to work fine but now it doesn't seem to want to work at all again. I don't get how changing computers would effect this kind of request.
Here's my code on JSFiddle, http://jsfiddle.net/SlyFoxy12/9mr7L/7/
My primary code is:
(function ($) {
var methods = {
init: function(data, options) {
//put your init logic here.
},
query_addresses: function(addresses) {
var addresses_implode = addresses.join("|");
$.getJSON("http://blockchain.info/multiaddr?cors=true&active="+addresses_implode, function( data ) {
$.each( data.addresses, function( index ) {
$('#output').append(" "+data.addresses[index].final_balance);
});
});
}
};
$.fn.bitstrap = function () {
var addresses = new Array();
$('[data-xbt-address]').each(function () {
$(this).text($(this).data('xbtAddress'));
addresses.push($(this).data('xbtAddress'));
});
methods.query_addresses(addresses);
}
}(jQuery));
$().ready(function() {
$().bitstrap();
});
Ok, turns out it's an issue with Chrome some how, I've tried it in safari and it works again, it must have been a different version of Chrome on the other computer I used.
There seems to be more info about it here https://code.google.com/p/chromium/issues/detail?id=104920