Currently the script works totally fine but has one issue, every time there is an error, it stops, then I have to delete that row with error and run the script again.
What I want is, if there is an error then it should return the results as null and then move to next line item, so that there is no manual interruption.
function getSearchAnalytics(){
var service = getService();
if (service.hasAccess()) {
for(var i=7;i<525;i++){
var site = s_searchAnalytics.getRange(i, 1).getValue();
if (!site){
continue;
return null
}
var apiURL = 'https://www.googleapis.com/webmasters/v3/sites/' + URLDecode(site) + '/searchAnalytics/query?fields=rows&alt=json';
var lastRow = s_searchAnalytics.getLastRow();
s_searchAnalytics.getRange(i,2,lastRow,5).clear();
var headers = {"Authorization": "Bearer " + getService().getAccessToken()};
var payload = {
"startDate" : startDate,
"endDate" : endDate,
"dimensions" : ["device"],
"rowLimit" : "25000"
};
var options = {
"headers": headers,
"contentType":'application/json',
"method" : "post",
"payload" : JSON.stringify(payload),
"muteHttpExceptions": true
};
try {
var response = UrlFetchApp.fetch(apiURL, options);
}
catch (e) {
Logger.log(e);
}
Logger.log(response)
if (!response){
continue;
return null
}
var result = JSON.parse(response.getContentText());
if (result.error){
Browser.msgBox(result.error.errors[0].message);
return null
}
var row = []
for (var k in result.rows){
row.push([
result.rows[k].keys[0],
result.rows[k].metric1,
result.rows[k].metric2,
result.rows[k].metric3,
result.rows[k].position
]);
}
s_searchAnalytics.getRange(i,2,row.length,5).setValues(row);
}} else {
var authorizationUrl = service.getAuthorizationUrl();
Logger.log('Open the following URL and re-run the script: %s', authorizationUrl);
}
}
I tried to replicate your code and found some issues:
Using return statement in your loop with terminate the whole function. Instead, use only continue. In line 9 and 47: the code will never reach the return null because you already use continue. Continue will leave the current iteration and move to the next one.
Instead of using if(!response), It would be easier to determine if the API call has an error by identifying the response code.
Informational responses (100–199)
Successful responses (200–299)
Redirects (300–399)
Client errors (400–499)
Server errors (500–599)
By using the response code, we can prevent writes if the response code is not 200(OK).
Here I modified your code:
function getSearchAnalytics() {
var service = getService();
if (service.hasAccess()) {
for (var i = 7; i < 525; i++) {
var site = s_searchAnalytics.getRange(i, 1).getValue();
if (!site) {
continue;
}else{
var apiURL = 'https://www.googleapis.com/webmasters/v3/sites/' + URLDecode(site) + '/searchAnalytics/query?fields=rows&alt=json';
var startDate = Utilities.formatDate(s_searchAnalytics.getRange(2, 2).getValue(), "GMT+7", "yyyy-MM-dd");
var endDate = Utilities.formatDate(s_searchAnalytics.getRange(3, 2).getValue(), "GMT+7", "yyyy-MM-dd");
var lastRow = s_searchAnalytics.getLastRow();
s_searchAnalytics.getRange(i, 2, lastRow, 5).clear();
var headers = {
"Authorization": "Bearer " + getService().getAccessToken()
};
var payload = {
"startDate": startDate,
"endDate": endDate,
"dimensions": ["device"],
"rowLimit": "25000"
};
var options = {
"headers": headers,
"contentType": 'application/json',
"method": "post",
"payload": JSON.stringify(payload),
"muteHttpExceptions": true
};
try {
var response = UrlFetchApp.fetch(apiURL, options);
} catch (e) {
Logger.log(e);
}
Logger.log(response)
if (response.getResponseCode() == 200) {
var result = JSON.parse(response.getContentText());
var row = []
for (var k in result.rows) {
row.push([
result.rows[k].keys[0],
result.rows[k].clicks,
result.rows[k].impressions,
result.rows[k].ctr,
result.rows[k].position
]);
}
s_searchAnalytics.getRange(i, 2, row.length, 5).setValues(row);
}
}
}
} else {
var authorizationUrl = service.getAuthorizationUrl();
Logger.log('Open the following URL and re-run the script: %s', authorizationUrl);
}
}
Reference:
HTTP response status code
I took ideas from both your codes and it worked. Here is the final version that's working.
function getSearchAnalytics(){
var service = getService();
if (service.hasAccess()) {
for(var i=7;i<525;i++){
var site = s_searchAnalytics.getRange(i, 1).getValue();
if (!site){
continue;
return null
}
var apiURL = 'https://www.googleapis.com/webmasters/v3/sites/' + URLDecode(site) + '/searchAnalytics/query?fields=rows&alt=json';
var startDate = Utilities.formatDate(s_searchAnalytics.getRange(2, 2).getValue(), "GMT+7", "yyyy-MM-dd");
var endDate = Utilities.formatDate(s_searchAnalytics.getRange(3, 2).getValue(), "GMT+7", "yyyy-MM-dd");
var lastRow = s_searchAnalytics.getLastRow();
s_searchAnalytics.getRange(i,2,lastRow,5).clear();
var headers = {"Authorization": "Bearer " + getService().getAccessToken()};
var payload = {
"startDate" : startDate,
"endDate" : endDate,
"dimensions" : ["device"],
"rowLimit" : "25000"
};
var options = {
"headers": headers,
"contentType":'application/json',
"method" : "post",
"payload" : JSON.stringify(payload),
"muteHttpExceptions": true
};
try {
var response = UrlFetchApp.fetch(apiURL, options);
}
catch (e) {
Logger.log(e);
}
Logger.log(response)
if (response.getResponseCode() == 200) {
}
var result = JSON.parse(response.getContentText());
if (result.error){
continue;
return null
}
var row = []
for (var k in result.rows){
row.push([
result.rows[k].keys[0],
result.rows[k].clicks,
result.rows[k].impressions,
result.rows[k].ctr,
result.rows[k].position
]);
}
s_searchAnalytics.getRange(i,2,row.length,5).setValues(row);
}} else {
var authorizationUrl = service.getAuthorizationUrl();
Logger.log('Open the following URL and re-run the script: %s', authorizationUrl);
}
}
I keep running to Cannot find function for each in object error while trying to loop entries. Is there something I am not seeing?. Here the code. This code is supposed to fetch time data from a system via API do calculations and send email
function getTime() {
var range = [5323, 9626, 4998];
var user = [];
for (var i = 0; i < range.length; i++) {
var auth = 'token'
var from = '2020-01-08'
var to = '2020-01-09'
var url = 'https://api.10000ft.com/api/v1/users/' + range[i] + '/time_entries?from=' + from + '&to=' + to + '&auth=' + auth;
var options = {
method: 'get',
headers: {
Authorization: 'Bearer ' + auth
}
};
var submitted_time_entries = {};
var response = UrlFetchApp.fetch(url, options);
var response = JSON.parse(response.getContentText());
var time_entries = response.data;
time_entries.forEach(function (time_entry) {
if (time_entry.user_id in submitted_time_entries) {
submitted_time_entries[time_entry.user_id] += time_entry.hours;
} else {
submitted_time_entries[time_entry.user_id] = time_entry.hours;
}
});
submitted_time_entries.forEach(function (user_id) {
if (submitted_time_entries[user_id] < 3) {
//send mail
}
});
}
}
response.data is probably not the array you expect. The server may be returning an error or a successful response that isn't parseable as an array. To find out, print response.data to the console and confirm it's the array you expect.
Seems my API returned an object. I figured out the way around it by using Object.keys method and it worked. Here is the working code.
function getTime() {
var range = [53, 926, 8098];
var user = [];
for (var i = 0; i < range.length; i++) {
var auth = 'token';
var from = '2020-01-08'
var to = '2020-01-09'
var url = 'https://api.10000ft.com/api/v1/users/' + '449625' + '/time_entries?from=' + from + '&to=' + to + '&auth=' + auth;
var options = {
method: 'get',
headers: {
Authorization: 'Bearer ' + auth
}
};
var submitted_time_entries = {};
var response = UrlFetchApp.fetch(url, options);
var response = JSON.parse(response.getContentText());
var time_entries = response.data;
Object.keys(time_entries).forEach(function (time_entry) {
if (time_entry.user_id in submitted_time_entries) {
submitted_time_entries[time_entry.user_id] += time_entry.hours;
} else {
submitted_time_entries[time_entry.user_id] = time_entry.hours;
}
});
Object.keys(submitted_time_entries).forEach(function (user_id) {
if (submitted_time_entries[user_id] < 3) {
Logger.log(time_entry)
//send mail
}
});
}
}
I'm now working on the api of Gatecoin and want to get my open order on Google Sheet. I'm trying this:
function GetOrder() {
var method = "GET"
var URL = "https://api.gatecoin.com/Trade/Orders"
var contentType = "application/json"
var d = new Date()
var now = d.getTime()
var msg = method + URL + contentType + now
var publicKey = :Public_key
var privateKey = :Private_key
var hash = Utilities.computeHmacSha256Signature(msg, privateKey, Utilities.Charset.US_ASCII);
var hashInBase64 = Utilities.base64Encode(hash);
var options ={
'contentType': 'application/json',
'method': method,
'API_PUBLIC_KEY': publicKey,
'API_REQUEST_SIGNATURE': hashInBase64,
'API_REQUEST_DATE': now
};
var rdata = UrlFetchApp.fetch("https://api.gatecoin.com/Trade/Orders", options)
}
But the response mentions I was not logged in. What am I doing wrong?
I believe your options should have headers defined in an object as such:
var options ={
“contentType”: “application/json”,
“method”: method,
“headers”: {
“API_PUBLIC_KEY”: publicKey,
“API_REQUEST_SIGNATURE”: hashInBase64,
“API_REQUEST_DATE”: now
}
};
I'm trying to do a httpRequest within another. I'll explain what I'm doing.
I am retrieving some datas from a Parse table (GET request) and, if this request succeed, I want to to another GET request to another Parse table, and unfortunately my second http Request didn't work at all, it didn't even finish as success or error.
This is what I have until now.
function getUserInformations(deviceId)
{
var response = new Parse.Promise();
var userInfos;
var apiKey = <<API Key>>;
var url = "http://api.timezonedb.com/?zone=";
Parse.Cloud.httpRequest({
method: "GET",
url: "https://api.parse.com/1/classes/User",
headers: {
"X-Parse-Application-Id": <<Application Id>>,
"X-Parse-REST-API-Key": <<REST API Key>>,
"Content-Type": "application/json"
},
success: function(httpResponse) {
var jsonObject = JSON.parse(httpResponse.text);
var x;
var count = 0;
for (x in jsonObject.results)
{
if (jsonObject.results.hasOwnProperty(x))
count++;
}
for (x = 0; x < count; x++)
{
if (jsonObject.results[x].deviceId == deviceId)
break;
}
if (x < count && jsonObject.results[x].deviceId == deviceId)
{
userInfos.email = jsonObject.results[x].email;
userInfos.name = jsonObject.results[x].name;
}
url += userInfos.timeZone;
url += "&format=json&key=";
url += apiKey;
Parse.Cloud.httpRequest({
method: "GET",
url: url,
headers: {
"Content-Type":"application/json"
},
success: function(httpResponse) {
var timestamp = httpResponse.data.timestamp;
var date = new Date(timestamp * 1000);
var hours = date.getHours();
var minutes = "0" + date.getMinutes();
var time = hours + minutes.substr(-2);
},
error: function(httpResponse) {
}
});
response.resolve(userInfos);
},
error: function(httpResponse) {
response.reject(userInfos);
}
});
return (response);
}
Any idea ?
I'm trying to parse JSON I recieved from an API call, but I keep running into the error "TypeError: Cannot read property "id" from undefined. (line 42, file "")" I'm relatively new to Apps Script. Any ideas on what's going on? I can get the payload back in JSON, but can't seem to parse it.
function getInfo() {
var url = "https://subdomain.chargify.com/subscriptions.json";
var username = "xxx"
var password = "x"
var headers = {
"Authorization": "Basic " + Utilities.base64Encode(username + ':' + password)
};
var options = {
"method": "GET",
"contentType": "application/json",
"headers": headers
};
var response = UrlFetchApp.fetch(url, options);
var data = JSON.parse(response.getContentText());
Logger.log(data);
var id = data.subscription; // kicks back an error
// var id = data; works and returns the whole JSON payload
var ss = SpreadsheetApp.getActiveSheet()
var targetCell = ss.setActiveSelection("A1");
targetCell.setValue(id);
}
According to the documentation here
https://docs.chargify.com/api-subscriptions#api-usage-json-subscriptions-list
it returns an array of subscriptions when you call the /subscriptions.json endpoint. So probably your data object should be handled like:
for (var i=0;i<data.length;i++) {
var item = data[i]; //subscription object, where item.subscription probably works
Logger.log(JSON.stringify(item));
}
function getInfo() {
var url = "https://subdomain.chargify.com/subscriptions.json";
var username = "xxx"
var password = "x"
var headers = {
"Authorization": "Basic " + Utilities.base64Encode(username + ':' + password)
};
var options = {
"method": "GET",
"contentType": "application/json",
"headers": headers
};
var response = UrlFetchApp.fetch(url, options);
var data = JSON.parse(response.getContentText());
for (var i = 0; i < data.length; i++) {
var item = data[i]; //subscription object, where item.subscription probably works
Logger.log(JSON.stringify(item));
var subscriptionid = item.subscription.id;
}
var ss = SpreadsheetApp.getActiveSheet()
var targetCell = ss.setActiveSelection("A2");
targetCell.setValue(subscriptionid);
}