I have data in a spreadsheet that I am using and some of the fields are hyperlinked to go to another page. When I pull the data to a table on a dashboard, the hyperlink is gone. I need the hyperlinks to stay functional within the app.
Code I am working with is below:
function doGet() {
var ss = SpreadsheetApp.openById('1BMFFT2oj9QCwOiMnSQ7YbfrJwGz6x7Q9Kf7h-_IyI5Q');
var data = ss.getDataRange();
var dowFilter = Charts.newCategoryFilter().setFilterColumnIndex(2).build();
var yearFilter = Charts.newCategoryFilter().setFilterColumnIndex(3).build();
var monthFilter = Charts.newCategoryFilter().setFilterColumnIndex(4).build();
var tableChart = Charts.newTableChart()
.setDataViewDefinition(Charts.newDataViewDefinition().setColumns([1,2,4,5,6,9,7,8]))
.setDimensions(800, 400)
.getFormulas()
.build();
var lineChart = Charts.newLineChart()
.setDataViewDefinition(Charts.newDataViewDefinition()
.setColumns([1,8,9]))
.setDimensions(800, 400)
.setTitle('Email Open and Click Rate')
.setXAxisTitle('Date')
.setYAxisTitle('Rates')
.build();
var dashboard = Charts.newDashboardPanel().setDataTable(data)
.bind([dowFilter, yearFilter, monthFilter], [tableChart, lineChart])
.build();
var app = UiApp.createApplication();
var filterPanel = app.createVerticalPanel();
var chartPanel = app.createVerticalPanel();
filterPanel.add(dowFilter).add(yearFilter).add(monthFilter).setSpacing(10);
chartPanel.add(tableChart).add(lineChart).setSpacing(10);
dashboard.add(app.createVerticalPanel().add(filterPanel).add(chartPanel));
app.add(dashboard);
return app;
}
The Charts Service in Google Apps Script is a wrapper for the Google Visualization library, but it does not support all its capabilities. Embedded HTML is one example of that. You can't do this using the Charts Service.
Instead, you'd need to use the HtmlService, and call the Visualization Library form your client-side JavaScript.
See Insert Links into Google Charts api data? for examples of adding clickable links to chart components.
For the work of moving your existing design over, please see my blog Converting from UiApp + Chart Service to Html Service + Google Visualization API.
Related
By following the guide Create Your Own Google Pagespeed & Mobile Usability Tracking Google Sheet in 5 Steps I managed to set up mobile pagespeed score for a list of (up to 50) URLs.
However since late 2017 or something there is real data available from the Chrome User Experience Report that displays an average load time in seconds for a page based on chrome user data.
(This data is being used for example when using Pagespeed Insights by google.)
Instead of pulling a page score I as described above I would like to pull the average load time into my google sheet.
Is it possible to adapt the script used from the article above to pull load time in seconds instead of pagescore? Or is there any other way to do this?
Thanks in advance your help is much appreciated.
This is the script I run in script editor to get pagescore into google sheet according to the linked article with function =checkAll(C3):
/**
* Returns Mobile Pagespeed, Mobile Usability, and Desktop Pagespeed values in three adjacent columns
* by Cagri Sarigoz
*/
function checkAll(Url) {
//CHANGE YOUR API KEY WITH YOUR_API_KEY BELOW
var key = "AIzaSyB2SeOumbCd6YNfFWRg5Jo_WpISZi4gCFs";
var serviceUrlMobile = "https://www.googleapis.com/pagespeedonline/v2/runPagespeed?url="+Url+"&strategy=mobile&key="+key;
var serviceUrlDesktop = "https://www.googleapis.com/pagespeedonline/v2/runPagespeed?url="+Url+"&strategy=desktop&key="+key;
var array = [];
if (key == "YOUR_API_KEY")
return "Please enter your API key to the script";
var responseMobile = UrlFetchApp.fetch(serviceUrlMobile);
if(responseMobile.getResponseCode() == 200) {
var contentMobile = JSON.parse(responseMobile.getContentText());
if ( (contentMobile != null) && (contentMobile["ruleGroups"] != null) )
{
if (contentMobile["responseCode"] == 200)
{
var speedScoreMobile = contentMobile["ruleGroups"]["SPEED"]["score"];
var usabilityScoreMobile = contentMobile["ruleGroups"]["USABILITY"]["score"];
}
else
{
array.push(["Not Found!", "Not Found!", "Not Found!"]);
return array;
}
}
}
var responseDesktop = UrlFetchApp.fetch(serviceUrlDesktop);
if(responseDesktop.getResponseCode() == 200) {
var contentDesktop = JSON.parse(responseDesktop.getContentText());
if ( (contentDesktop != null) && (contentDesktop["ruleGroups"] != null) )
var speedScoreDesktop = contentDesktop["ruleGroups"]["SPEED"]["score"];
}
array.push([speedScoreMobile, usabilityScoreMobile, speedScoreDesktop]);
return array;
}
I am the writer of the blog post that you shared. As you said, the Google Apps Script there was using Google Pagespeed API v2. The current API version is v4, and v2 will be depreciated on June 30th.
So I updated the code with v4 on my own copy of the spreadsheet. You can make your own copy from here.
I also wanted to add the mobile-friendly test results but it turned out that Google Search Console's API quota restrictions were too tight, returning error almost all the time. So I commented out that part of the code for the time being.
I didn't have the time to update my blog post yet. You can see the new version of the script here.
I have a query that runs and can see the results. But while trying to save the query as a view table, I get error message saying
Failed to save view. No suitable credentials found to access Google
Drive. Contact the table owner for assistance.
I think the problem is caused by a table used in the query. The table is uploaded from a google sheet (with source URI), own by me. I have tried to enable Google Drive API from the project but no luck. Not sure how I can give BigQuery access to Google Drive.
I suspect the problem you are hitting is one of OAuth Scopes. In order to talk to the Google Drive API to read data, you need to use credentials that were granted access to that API.
If you are using the BigQuery web UI and have not explicitly granted access to Drive, it won't work. For example, the first time I tried to "Save to Google Sheets", the BigQuery UI popped up an OAuth prompt asking me to grant access to my Google Drive. After this it could save the results. Try doing this to make sure your credentials have the Drive scope and then "Save View" again.
If you are using your own code to do this, you should request scope 'https://www.googleapis.com/auth/drive' in addition to the 'https://www.googleapis.com/auth/bigquery' scope you are already using to talk to BigQuery.
If you are using the bq client, it has been updated to request this scope, but you may need to re-initialize your authentication credentials. You can do this with bq init --delete_credentials to remove the credentials, then your next action we re-request credentials.
Using Google App Script this worked for me:
function saveQueryToTable() {
var projectId = '...yourprojectid goes here...';
var datasetId = '...yourdatesetid goes here...';
var sourceTable = '...your table or view goes here...';
var destTable = '...destination table goes here...';
var myQuery;
//just a random call to activate the Drive API scope
var test = Drive.Properties.list('...drive file id goes here...')
//list all tables for the particular dataset
var tableList = BigQuery.Tables.list(projectId, datasetId).getTables();
//if the table exist, delete it
for (var i = 0; i < tableList.length; i++) {
if (tableList[i].tableReference.tableId == destTable) {
BigQuery.Tables.remove(projectId, datasetId, destTable);
Logger.log("DELETED: " + destTable);
}
};
myQuery = 'SELECT * FROM [PROJECTID:DATASETID.TABLEID];'
.replace('PROJECTID',projectId)
.replace('DATASETID',datasetId)
.replace('TABLEID',sourceTable)
var job = {
configuration: {
query: {
query: myQuery,
destinationTable: {
projectId: projectId,
datasetId: datasetId,
tableId: destTable
}
}
}
};
var queryResults = BigQuery.Jobs.insert(job, projectId);
Logger.log(queryResults.status);
}
The 'trick' was a random call to the Drive API to ensure both the BigQuery and Drive scopes are included.
Google Apps Script Project Properties
I have a Google Maps Engine project where a datasource can be updated via Google Forms/Google Apps Script. I know that there is a way to configure OAuth in GAS (https://developers.google.com/apps-script/reference/url-fetch/o-auth-config) but I can't figure out how to make it work after spending hours reading through the GAS and GME documentation. I have been able to get around it using the OAuth Playground to obtain an access token, but I need to manually refresh each hour. I know the answer is probably simple, but I am new to OAuth and I can't find a simple guide out there to help me.
How can I get my Google Apps Script to play nicely with Google Maps Engine through OAuth?
I have included how I currently access GME below:
/* This function is called when a new provider is added through the "Medical Providers" form
It sends an HTTP request to Google Maps Engine to add the new provider to the map */
function addNewtoTable(row){
var aPIKey = "MY_API_KEY";
var bearer = "ACCESS_TOKEN_FROM_OAUTH_PLAYGROUND";
var projectID = "MY_PROJECT_ID";
var tableID = "MY_TABLE_ID";
//tutorial here https://developers.google.com/maps-engine/documentation/tutorial
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Providers");
var address = sheet.getRange(row,2).getValue();
var response = Maps.newGeocoder().geocode(address);
for (var j = 0; j < response.results.length; j++) {
var result = response.results[j];
//Logger.log('%s: %s, %s', result.formatted_address, result.geometry.location.lat,
// result.geometry.location.lng);
};
var lat = result.geometry.location.lat;
var long = result.geometry.location.lng;
var name= '"'+sheet.getRange(row,1).getValue()+'"';
var phone= '"'+sheet.getRange(row,4).getValue().toString()+'"';
var email= '"'+sheet.getRange(row,3).getValue()+'"';
var inbounds= '"'+sheet.getRange(row,5).getValue().toString()+'"';
var outbounds = '"'+sheet.getRange(row,6).getValue().toString()+'"';
var lastIn = '" '+sheet.getRange(row,7).getValue().toString()+' "';
var lastOut = '" '+sheet.getRange(row,8).getValue().toString()+' "';
var gxid = '"'+sheet.getRange(row,9).getValue().toString()+'"';
//HTTP request goes here
var payload = '{features:[{type: "Feature",geometry:{type: "Point",coordinates: ['+long+','+lat+']},properties: {gx_id: '+gxid+',name: '+name+',phone:'+phone+',email:'+email+',inbound:'+inbounds+',outbound:'+outbounds+',last_inbound:'+lastIn+',last_outbound:'+lastOut+'}}]}';
Logger.log(payload);
var headers = {"Authorization": "Bearer ACCESS_TOKEN_FROM_OAUTH_PLAYGROUND", "Content-type": "application/json"};
var options ={"method" : "post","headers" : headers, "payload" : payload, "muteHttpExceptions" : true};
var httpresponse = UrlFetchApp.fetch("https://www.googleapis.com/mapsengine/v1/tables/MY_TABLE_ID/features/batchInsert",options);
Logger.log(httpresponse);
if (httpresponse!=""){
MailApp.sendEmail('MY_EMAIL', 'HTTP Request Failed to Send', httpresponse);
};
};
It's certainly possible. The App Script docs have a tutorial explaining how to connect to a remote service using OAuth that uses the Twitter API as an example. This example also shows an OAuth-authorized call being executed.
The main difference in the tutorial for Maps Engine is the first step, where you don't set up with Twitter, you set up in the Developers Console.
You want to create a new OAuth client ID, under APIs & Auth -> Credentials. It's a web application.
Instead of setting the "Callback URL" in Twitter, you'll set the "Authorized Redirect URI" in the console, when creating the client ID. Set the authorized origins to docs.google.com too, just in case.
You'll get your "Consumer Key" and "Consumer Secret" through console.developers.google.com too, they correspond to the Client ID and Client Secret that are referred to in this GME doc.
In addition to the set up, these pointers may help you.
The UrlFetchApp.addOauthService("twitter") calls can use any string as an identifier, there's nothing special about the phrase "twitter", but it needs to match oAuthServiceName
The URLs you need look like they should be these (grabbed from here):
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope); Scope is explained here.
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
A little too late for my purposes, but I found that Google themselves made a library for GAS that enables OAuth 2.0. Why this is not included within GAS is beyond me. This also looks to be pretty recent, with some updates as of 5 days ago.
I am trying to call Twitter's REST API from Google Apps Script.
The code I am using is copied one to one from here:
https://developers.google.com/apps-script/guides/services/external
and specifically:
function test() {
var consumerKey = 'XXXX'; // Copied from my twitter app setting.
var consumerSecret = 'XXXXX'; // Copied from my twitter app setting.
var oauthConfig = UrlFetchApp.addOAuthService('twitter');
oauthConfig.setAccessTokenUrl('http://api.twitter.com/oauth/access_token');
oauthConfig.setRequestTokenUrl('http://api.twitter.com/oauth/request_token');
oauthConfig.setAuthorizationUrl('http://api.twitter.com/oauth/authorize');
oauthConfig.setConsumerKey(consumerKey);
oauthConfig.setConsumerSecret(consumerSecret);
var options = {
'oAuthServiceName' : 'twitter',
'oAuthUseToken' : 'always'
};
var url = 'https://api.twitter.com/1.1/search/tweets.json?count=5&include_entities=false&result_type=recent&q=hello';
var response = UrlFetchApp.fetch(url, options);
var tweets = JSON.parse(response.getContentText());
Logger.log(tweets)
}
Nevertheless, I get Oauth ERROR every time I run it.
My settings in the twitter app allows for "Read and Write"
Any suggestions
Just go to your twitter application and set the callback url as
https://script.google.com
This is now best handled through the following open source Google Apps Script library:
https://github.com/googlesamples/apps-script-oauth1
The example in the documentation is twitter itself (because it's probably the only remaining user of oauth v1 out there...)
Cheers, M
Question 1: -
I am using the script below which works fine, but cant seem to get the Client ID (eg Bobs Bakers) I have many clients and want to run this from within google adwords scripts. (Not the API).
Question 2:
Is there a way to run this across all clients, giving me all campaigns they have? Or do I have to run this script from within each client?
function main() {
var campaignsIterator = AdWordsApp.campaigns()
.withCondition("Status = ENABLED");
.forDateRange('TODAY')
.get();
var csv = 'CampaignName, Impressions,Clicks,AveragePosition,AverageCpc,ConversionRate,Conversions,Ctr,Cost';
while (campaignsIterator.hasNext())
{
var campaign = campaignsIterator.next();
var stats = campaign.getStatsFor("TODAY");
var row = [
campaign,
stats.getImpressions(),
stats.getClicks(),
stats.getAveragePosition(),
stats.getAverageCpc(),
stats.getConversionRate(),
stats.getConversions(),
stats.getCtr(),
stats.getCost()];
csv += '\n' + row.join(',');
}
}
can't find the customer name, but here's a way to see the account id:
AdWordsApp.currentAccount().getCustomerId()
running the same script across accounts isn't possible as of yet. You'll have to run the script from within each client.