Use JIRA webhook data in Google Script Project - json
I am trying to get the following to work: A JSON is sent to my Google Script - Now I want to get specific values from that JSON Message and store them into specific rows of one specific Google Spreadsheet. So far so good, this is what I have :
function doPost(response) {
var sheets = SpreadsheetApp.openById('MY SHEET ID');
var dataAll = JSON.parse(response.getContentText());
var nR = getNextRow(sheets) + 1;
// RECORD DATA IN SPREADSHEET
sheets.getRangeByName('timestamp').getCell(nR,1).setValue(new Date());
sheets.getRangeByName('ticket_id').getCell(nR,1).setValue(dataAll);
}
function getNextRow(sheets) {
var timestamps = sheets.getRangeByName("timestamp").getValues();
for (i in timestamps) {
if(timestamps[i][0] == "") {
return Number(i);
break;
}}}
It should store the response and put it into a blank cell of the range "timestamp". But nothing happens at this point.
This is the JSON ( Body ) from JIRA:
{"timestamp":1483576902984,"webhookEvent":"jira:issue_created","issue_event_type_name":"issue_created","user":{"self":"https://xxx.atlassian.net/rest/api/2/user?username=admin","name":"admin","key":"admin","emailAddress":"test#mail.at","avatarUrls":{"48x48":"https://secure.gravatar.com/avatar/3d238d8be45bd26982fa09ae2f891c3f?d=mm&s=48","24x24":"https://secure.gravatar.com/avatar/3d238d8be45bd26982fa09ae2f891c3f?d=mm&s=24","16x16":"https://secure.gravatar.com/avatar/3d238d8be45bd26982fa09ae2f891c3f?d=mm&s=16","32x32":"https://secure.gravatar.com/avatar/3d238d8be45bd26982fa09ae2f891c3f?d=mm&s=32"},"displayName":"Max Mustermann [Administrator]","active":true,"timeZone":"Europe/Berlin"},"issue":{"id":"10057","self":"https://xxx.atlassian.net/rest/api/2/issue/10057","key":"TA-58","fields":{"issuetype":{"self":"https://xxx.atlassian.net/rest/api/2/issuetype/10104","id":"10104","description":"A problem which impairs or prevents the functions of the product.","iconUrl":"https://xxx.atlassian.net/secure/viewavatar?size=xsmall&avatarId=10303&avatarType=issuetype","name":"Bug","subtask":false,"avatarId":10303},"timespent":null,"project":{"self":"https://xxx.atlassian.net/rest/api/2/project/10000","id":"10000","key":"TA","name":"Test Area","avatarUrls":{"48x48":"https://xxx.atlassian.net/secure/projectavatar?avatarId=10324","24x24":"https://xxx.atlassian.net/secure/projectavatar?size=small&avatarId=10324","16x16":"https://xxx.atlassian.net/secure/projectavatar?size=xsmall&avatarId=10324","32x32":"https://xxx.atlassian.net/secure/projectavatar?size=medium&avatarId=10324"}},"customfield_10110":null,"fixVersions":[],"customfield_10111":null,"aggregatetimespent":null,"customfield_10112":"Not started","resolution":null,"customfield_10113":null,"customfield_10114":null,"customfield_10104":null,"customfield_10105":null,"customfield_10106":null,"customfield_10107":null,"customfield_10108":null,"customfield_10109":null,"resolutiondate":null,"workratio":-1,"lastViewed":null,"watches":{"self":"https://xxx.atlassian.net/rest/api/2/issue/TA-58/watchers","watchCount":0,"isWatching":false},"created":"2017-01-05T01:41:42.903+0100","priority":{"self":"https://xxx.atlassian.net/rest/api/2/priority/3","iconUrl":"https://xxx.atlassian.net/images/icons/priorities/medium.svg","name":"Medium","id":"3"},"customfield_10100":null,"customfield_10101":null,"customfield_10102":null,"customfield_10103":null,"labels":[],"timeestimate":null,"aggregatetimeoriginalestimate":null,"versions":[],"issuelinks":[],"assignee":null,"updated":"2017-01-05T01:41:42.903+0100","status":{"self":"https://xxx.atlassian.net/rest/api/2/status/10000","description":"","iconUrl":"https://xxx.atlassian.net/","name":"To Do","id":"10000","statusCategory":{"self":"https://xxx.atlassian.net/rest/api/2/statuscategory/2","id":2,"key":"new","colorName":"blue-gray","name":"To Do"}},"components":[],"timeoriginalestimate":null,"description":"super alles neu","timetracking":{},"customfield_10005":null,"attachment":[],"aggregatetimeestimate":null,"summary":"super alles neu","creator":{"self":"https://xxx.atlassian.net/rest/api/2/user?username=admin","name":"admin","key":"admin","emailAddress":"test#mail.at","avatarUrls":{"48x48":"https://secure.gravatar.com/avatar/3d238d8be45bd26982fa09ae2f891c3f?d=mm&s=48","24x24":"https://secure.gravatar.com/avatar/3d238d8be45bd26982fa09ae2f891c3f?d=mm&s=24","16x16":"https://secure.gravatar.com/avatar/3d238d8be45bd26982fa09ae2f891c3f?d=mm&s=16","32x32":"https://secure.gravatar.com/avatar/3d238d8be45bd26982fa09ae2f891c3f?d=mm&s=32"},"displayName":"Max Mustermann [Administrator]","active":true,"timeZone":"Europe/Berlin"},"subtasks":[],"reporter":{"self":"https://xxx.atlassian.net/rest/api/2/user?username=admin","name":"admin","key":"admin","emailAddress":"test#mail.at","avatarUrls":{"48x48":"https://secure.gravatar.com/avatar/3d238d8be45bd26982fa09ae2f891c3f?d=mm&s=48","24x24":"https://secure.gravatar.com/avatar/3d238d8be45bd26982fa09ae2f891c3f?d=mm&s=24","16x16":"https://secure.gravatar.com/avatar/3d238d8be45bd26982fa09ae2f891c3f?d=mm&s=16","32x32":"https://secure.gravatar.com/avatar/3d238d8be45bd26982fa09ae2f891c3f?d=mm&s=32"},"displayName":"Max Mustermann [Administrator]","active":true,"timeZone":"Europe/Berlin"},"customfield_10000":"{}","aggregateprogress":{"progress":0,"total":0},"customfield_10001":null,"customfield_10115":null,"customfield_10116":"0|i0005r:","environment":null,"duedate":null,"progress":{"progress":0,"total":0},"comment":{"comments":[],"maxResults":0,"total":0,"startAt":0},"votes":{"self":"https://xxx.atlassian.net/rest/api/2/issue/TA-58/votes","votes":0,"hasVoted":false},"worklog":{"startAt":0,"maxResults":20,"total":0,"worklogs":[]}}}}
However, I don't want to have the whole JSON in my cell, I only want to have specific obejcts/id from within the JSON. How do I call them ?
After tons of research, this is a solution that works for me (in my case):
function doPost(response) {
var sheets = SpreadsheetApp.openById('SHEET_ID');
// retrieve data from JIRA Payload and store them into "data"
var json = response.postData.contents;
var data = JSON.parse(json);
// index values from "data" and store them into seperate variables
// for example:
var ticket_id = data.issue.key;
var priority_name = data.issue.fields.priority.name;
var summary = data.issue.fields.summary;
This two lines:
var json = response.postData.contents;
var data = JSON.parse(json);
Made it possible to read the body and index all the specific parameters I want.
Here is an example:
/*
* webhookHandler: JIRA webhook callback function
*/
function webhookHandler(response) {
var data = response.getAs("application/json");
//logs out data in dev console
console.log(data);
var spreadsheet = SpreadsheetApp.openById("<spreadsheet id>");
var cellRange = spreadsheet.getRangeByName("<some range name>");
var cell = cellRange.getCell(0 /*row index*/, 0/*column index*/);
cell.setValue(data.ticket_id/*index the JSON object returned by response*/);
}
UrlFetchApp Documentation
SpreadsheetApp Documentation
Related
Apps Script custom function working in script editor but not in Google Sheet custom function
I have built a simple custom function in Apps Script using URLFetchApp to get the follower count for TikTok accounts. function tiktok_fans() { var raw_data = new RegExp(/("followerCount":)([0-9]+)/g); var handle = '#charlidamelio'; var web_content = UrlFetchApp.fetch('https://www.tiktok.com/'+ handle + '?lang=en').getContentText(); var match_text = raw_data.exec(web_content); var result = (match_text[2]); Logger.log(result) return result } The Log comes back with the correct number for followers. However, when I change the code to; function tiktok_fans(handle) { var raw_data = new RegExp(/("followerCount":)([0-9]+)/g); //var handle = '#charlidamelio'; var web_content = UrlFetchApp.fetch('https://www.tiktok.com/'+ handle + '?lang=en').getContentText(); var match_text = raw_data.exec(web_content); var result = (match_text[2]); Logger.log(result) return result } and use it in a spreadsheet for example =tiktok_fans(A1), where A1 has #charlidamelio I get an #ERROR response in the cell TypeError: Cannot read property '2' of null (line 6). Why does it work in the logs but not in the spreadsheet? --additional info-- Still getting the same error after testing #Tanaike answer below, "TypeError: Cannot read property '2' of null (line 6)." Have mapped out manually to see the error, each time the below runs, a different log returns "null". I believe this is to do with the ContentText size/in the cache. I have tried utilising Utilities.sleep() in between functions with no luck, I still get null's. code var raw_data = new RegExp(/("followerCount":)([0-9]+)/g); //tiktok urls var qld = UrlFetchApp.fetch('https://www.tiktok.com/#thisisqueensland?lang=en').getContentText(); var nsw = UrlFetchApp.fetch('https://www.tiktok.com/#visitnsw?lang=en').getContentText(); var syd = UrlFetchApp.fetch('https://www.tiktok.com/#sydney?lang=en').getContentText(); var tas = UrlFetchApp.fetch('https://www.tiktok.com/#tasmania?lang=en').getContentText(); var nt = UrlFetchApp.fetch('https://www.tiktok.com/#ntaustralia?lang=en').getContentText(); var nz = UrlFetchApp.fetch('https://www.tiktok.com/#purenz?lang=en').getContentText(); var aus = UrlFetchApp.fetch('https://www.tiktok.com/#australia?lang=en').getContentText(); var vic = UrlFetchApp.fetch('https://www.tiktok.com/#visitmelbourne?lang=en').getContentText(); //find folowers with regex var match_qld = raw_data.exec(qld); var match_nsw = raw_data.exec(nsw); var match_syd = raw_data.exec(syd); var match_tas = raw_data.exec(tas); var match_nt = raw_data.exec(nt); var match_nz = raw_data.exec(nz); var match_aus = raw_data.exec(aus); var match_vic = raw_data.exec(vic); Logger.log(match_qld); Logger.log(match_nsw); Logger.log(match_syd); Logger.log(match_tas); Logger.log(match_nt); Logger.log(match_nz); Logger.log(match_aus); Logger.log(match_vic);
Issue: From your situation, I remembered that the request of UrlFetchApp with the custom function is different from the request of UrlFetchApp with the script editor. So I thought that the reason for your issue might be related to this thread. https://stackoverflow.com/a/63024816 In your situation, your situation seems to be the opposite of this thread. But, it is considered that this issue is due to the specification of the site. In order to check this difference, I checked the file size of the retrieved HTML data. The file size of HTML data retrieved by UrlFetchApp executing with the script editor is 518k bytes. The file size of HTML data retrieved by UrlFetchApp executing with the custom function is 9k bytes. It seems that the request of UrlFetchApp executing with the custom function is the same as that of UrlFetchApp executing withWeb Apps. The data of 9k bytes are retrieved by using this. From the above result, it is found that the retrieved HTML is different between the script editor and the custom function. Namely, the HTML data retrieved by the custom function doesn't include the regex of ("followerCount":)([0-9]+). By this, such an error occurs. I thought that this might be the reason for your issue. Workaround: When I tested your situation with Web Apps and triggers, the same issue occurs. By this, in the current stage, I thought that the method for automatically executing the script might not be able to be used. So, as a workaround, how about using a button and the custom menu? When the script is run by the button and the custom menu, the script works. It seems that this method is the same as that of the script editor. The sample script is as follows. Sample script: Before you run the script, please set range. For example, please assign this function to a button on Spreadsheet. When you click the button, the script is run. In this sample, it supposes that the values like #charlidamelio are put to the column "A". function sample() { var range = "A2:A10"; // Please set the range of "handle". var raw_data = new RegExp(/("followerCount":)([0-9]+)/g); var sheet = SpreadsheetApp.getActiveSheet(); var r = sheet.getRange(range); var values = r.getValues(); var res = values.map(([handle]) => { if (handle != "") { var web_content = UrlFetchApp.fetch('https://www.tiktok.com/'+ handle + '?lang=en').getContentText(); var match_text = raw_data.exec(web_content); return [match_text[2]]; } return [""]; }); r.offset(0, 1).setValues(res); } When this script is run, the values are retrieved from the URL and put to the column "B". Note: This is a simple script. So please modify it for your actual situation. Reference: Related thread. UrlFetchApp request fails in Menu Functions but not in Custom Functions (connecting to external REST API) Added: About the following additional question, whilst this works for 1 TikTok handle, when trying to run a list of multiple it fails each time, with the error TypeError: Cannot read property '2' of null. After doing some investigating and manually mapping out 8 handles, I can see that each time it runs, it returns "null" for one or more of the web_content variables. Is there a way to slow the script down/run each UrlFetchApp one at a time to ensure each returns content? i've tried this and still getting an error. Have tried up to 10000ms. I've added some more detail to the original question, hope this makes sense as to the error. It is always in a different log that I get nulls, hence why I think it's a timing or cache issue. In this case, how about the following sample script? Sample script: In this sample script, when the value cannot be retrieved from the URL, the value is tried to retrieve again as the retry. This sample script uses the 2 times as the retry. So when the value cannot be retrieved by 2 retries, the empty value is returned. function sample() { var range = "A2:A10"; // Please set the range of "handle". var raw_data = new RegExp(/("followerCount":)([0-9]+)/g); var sheet = SpreadsheetApp.getActiveSheet(); var r = sheet.getRange(range); var values = r.getValues(); var res = values.map(([handle]) => { if (handle != "") { var web_content = UrlFetchApp.fetch('https://www.tiktok.com/'+ handle + '?lang=en').getContentText(); var match_text = raw_data.exec(web_content); if (!match_text || match_text.length != 3) { var retry = 2; // Number of retry. for (var i = 0; i < retry; i++) { Utilities.sleep(3000); web_content = UrlFetchApp.fetch('https://www.tiktok.com/'+ handle + '?lang=en').getContentText(); match_text = raw_data.exec(web_content); if (match_text || match_text.length == 3) break; } } return [match_text && match_text.length == 3 ? match_text[2] : ""]; } return [""]; }); r.offset(0, 1).setValues(res); } Please adjust the value of retry and Utilities.sleep(3000).
This works for me as a Custom Function: function MYFUNK(n=2) { const url = 'my website url' const re = new RegExp(`<p id="un${n}.*\/p>`,'g') const r = UrlFetchApp.fetch(url).getContentText(); const v = r.match(re); Logger.log(v); return v; } I used my own website and I have several paragraphs with ids from un1 to un7 and I'm taking the value of A1 for the only parameter. It returns the correct string each time I change it.
Google Sheets Scraping Options Chain from Yahoo Finance, Incomplete Results [duplicate]
This question already has answers here: Scraping data to Google Sheets from a website that uses JavaScript (2 answers) Closed last month. I'm attempting to scrape options pricing data from Yahoo Finance in Google Sheets. Although I'm able to pull the options chain just fine, i.e. =IMPORTHTML("https://finance.yahoo.com/quote/TCOM/options?date=1610668800","table",2) I find that it's returning results that don't completely match what's actually shown on Yahoo Finance. Specifically, the scraped results are incomplete - they're missing some strikes. i.e. the first 5 rows of the chart may match, but then it will start returning only every other strike (aka skipping every other strike). Why would IMPORTHTML be returning "abbreviated" results, which don't match what's actually shown on the page? And more importantly, is there some way to scrape complete data (i.e. that doesn't skip some portion of the available strikes)?
In Yahoo finance, all data are available in a big json called root.App.main. So to get the complete set of data, proceed as following var source = UrlFetchApp.fetch(url).getContentText() var jsonString = source.match(/(?<=root.App.main = ).*(?=}}}})/g) + '}}}}' var data = JSON.parse(jsonString) You can then choose to fetch the informations you need. Take a copy of this example https://docs.google.com/spreadsheets/d/1sTA71PhpxI_QdGKXVAtb0Rc3cmvPLgzvXKXXTmiec7k/copy edit if you want to get a full list of available data, you can retrieve it by this simple script // mike.steelson let result = []; function getAllDataJSON(url = 'https://finance.yahoo.com/quote/TCOM/options?date=1610668800') { var source = UrlFetchApp.fetch(url).getContentText() var jsonString = source.match(/(?<=root.App.main = ).*(?=}}}})/g) + '}}}}' var data = JSON.parse(jsonString) getAllData(eval(data),'data') var sh = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet() sh.getRange(1, 1, result.length, result[0].length).setValues(result); } function getAllData(obj,id) { const regex = new RegExp('[^0-9]+'); for (let p in obj) { var newid = (regex.test(p)) ? id + '["' + p + '"]' : id + '[' + p + ']'; if (obj[p]!=null){ if (typeof obj[p] != 'object' && typeof obj[p] != 'function'){ result.push([newid, obj[p]]); } if (typeof obj[p] == 'object') { getAllData(obj[p], newid ); } } } }
Here's a simpler way to get the last market price of a given option. Add this function to you Google Sheets Script Editor. function OPTION(ticker) { var ticker = ticker+""; var URL = "finance.yahoo.com/quote/"+ticker; var html = UrlFetchApp.fetch(URL).getContentText(); var count = (html.match(/regularMarketPrice/g) || []).length; var query = "regularMarketPrice"; var loc = 0; var n = parseInt(count)-2; for(i = 0; i<n; i++) { loc = html.indexOf(query,loc+1); } var value = html.substring(loc+query.length+9, html.indexOf(",", loc+query.length+9)); return value*100; } In your google sheets input the Yahoo Finance option ticker like below =OPTION("AAPL210430C00060000")
I believe your goal as follows. You want to retrieve the complete table from the URL of https://finance.yahoo.com/quote/TCOM/options?date=1610668800, and want to put it to the Spreadsheet. Issue and workaround: I could replicate your issue. When I saw the HTML data, unfortunately, I couldn't find the difference of HTML between the showing rows and the not showing rows. And also, I could confirm that the complete table is included in the HTML data. By the way, when I tested it using =IMPORTXML(A1,"//section[2]//tr"), the same result of IMPORTHTML occurs. So I thought that in this case, IMPORTHTML and IMPORTXML might not be able to retrieve the complete table. So, in this answer, as a workaround, I would like to propose to put the complete table parsed using Sheets API. In this case, Google Apps Script is used. By this, I could confirm that the complete table can be retrieved by parsing the HTML table with Sheet API. Sample script: Please copy and paste the following script to the script editor of Spreadsheet, and please enable Sheets API at Advanced Google services. And, please run the function of myFunction at the script editor. By this, the retrieved table is put to the sheet of sheetName. function myFunction() { // Please set the following variables. const url ="https://finance.yahoo.com/quote/TCOM/options?date=1610668800"; const sheetName = "Sheet1"; // Please set the destination sheet name. const sessionNumber = 2; // Please set the number of session. In this case, the table of 2nd session is retrieved. const html = UrlFetchApp.fetch(url).getContentText(); const section = [...html.matchAll(/<section[\s\S\w]+?<\/section>/g)]; if (section.length >= sessionNumber) { if (section[sessionNumber].length == 1) { const table = section[sessionNumber][0].match(/<table[\s\S\w]+?<\/table>/); if (table) { const ss = SpreadsheetApp.getActiveSpreadsheet(); const body = {requests: [{pasteData: {html: true, data: table[0], coordinate: {sheetId: ss.getSheetByName(sheetName).getSheetId()}}}]}; Sheets.Spreadsheets.batchUpdate(body, ss.getId()); } } else { throw new Error("No table."); } } else { throw new Error("No table."); } } const sessionNumber = 2; means that 2 of =IMPORTHTML("https://finance.yahoo.com/quote/TCOM/options?date=1610668800","table",2). References: Method: spreadsheets.batchUpdate PasteDataRequest
API to Google sheets - unable to fetch data
I am trying to fetch data via API to Google sheets, I am able to get "NewConfirmed" and other few fields but not able to get "Countries" data. Please help. function Covid19() { // Call the COVID19 API var response = UrlFetchApp.fetch("https://api.covid19api.com/summary"); // Parse the JSON reply var json=response.getContentText(); var data=JSON.parse(json); var sheet = SpreadsheetApp.getActiveSheet(); var i = 2; for each (var info in data) { sheet.getRange(i,1).setValue([info['NewConfirmed']]); sheet.getRange(i,2).setValue([info['Country']]); i = i + 1; }
If you log data, you will see {Countries=[{CountryCode=AX, TotalRecovered=0.0, NewDeaths=0.0, Slug=ala-aland-islands, Country=ALA Aland Islands, NewRecovered=0.0, Date=2020-04-21T12:32:01Z, NewConfirmed=0.0, ... Thus, in order to retrieve Country and NewConfirmed you need to define var data=JSON.parse(json).Countries and then you have to iterate through all entries within a loop. Sample based on your code: function Covid19() { var response = UrlFetchApp.fetch("https://api.covid19api.com/summary"); var json=response.getContentText(); var data=JSON.parse(json).Countries; var sheet = SpreadsheetApp.getActiveSheet(); for(var i = 0; i < data.length; i++) { sheet.getRange(i+2,1).setValue([data[i]['NewConfirmed']]); sheet.getRange(i+2,2).setValue([data[i]['Country']]); } } Sidenote: It is ot good practive to use getRange(...).setValue(..) during each loop iteration. It would be better to write the data into an array and assign the array with all the data to the sheet after finishing iteration.
Apps Script Error - Cannot find method getRange(number,number,(class),number)
I've written a custom Google Apps Script that will pull some data (2 columns wide, 50-100 rows long but this varies)in an array 2 from an API, parse it into JSON and then paste into a google sheet. I can run the script from the editor and it works ok. But when I try to run it from a custom menu or when I run the debugger I get the following error: 'Cannot find method getRange(number,number,(class),number) (line 43)' Line 43 is the last line of the code. sheet.getRange(3,1,dataSet.length,2).setValues(rows); It seems that the issue is that getRange is not able to use the variable of length of the dataset (number of rows) to set the number of rows to use in the range in which the data is to be pasted. I cannot work out how to fix this - can anyone else see what I am doing wrong? Thanks for taking a look. //custom menu function onOpen() { var ui = SpreadsheetApp.getUi(); ui.createMenu('XXXX Data') .addItem('Credit Limits','CREDITLIMITS') .addToUi(); } function CREDITLIMITS() { var ss = SpreadsheetApp.getActiveSpreadsheet(); //get active spreadsheet var sheet = ss.getActiveSheet(); // var sheet = ss.getSheetByName('data'); //get sheet by name from active spreadsheet // URL and params for the API var USERNAME = 'XXXXXXX'; var PASSWORD = 'XXXXXXXXXXXXX'; var url = 'https://api.XXXX.com/api/v1/XXX/?where=type=%27XXXXXXX%27'; // var url="http://example.com/feeds?type=json"; // Paste your JSON URL here var authHeader = 'Basic ' + Utilities.base64Encode(USERNAME + ':' + PASSWORD); var params = {'method': 'GET','muteHttpExceptions': true,'headers': {'Authorization': authHeader,} }; //call the XXXX API var response = UrlFetchApp.fetch(url, params); // get api endpoint var json = response.getContentText(); // get the response content as text var dataAll = JSON.parse(json); //parse text into json var dataSet = dataAll; //create empty array to hold data points var rows=[], data; //loop over the retrun events for (i=0; i < dataSet.length; i++) { data = dataSet[i]; //push a row of data as 2d array rows.push([data.company, data.creditLimit]); } // clear any previous content sheet.getRange(1,1,500,10).clearContent(); // write data to sheet sheet.getRange(3,1,dataSet.length,2).setValues(rows); }
Reading key-value json data into google sheet cells
I am looking to bring in the "bid" values from each "ticker" from this API call https://api.etherdelta.com/returnTicker into Google Sheet cells. An example cell value will have something like: =crypt("PPT). Here is the code I have so far, but I am having a hard time figuring out how I can get the data for each ticker (I know I haven't declared "ticker" anywhere in the code). function crypt(ticker) { var url = "https://api.etherdelta.com/returnTicker"; var response = UrlFetchApp.fetch(url); var text = response.getContentText(); var json = JSON.parse(text); var price = json[bid]; return parseFloat(bid); }
How about the following modifications? Modification points : Each ticker name has a header of ETH_. ETH_ + ticker is a key of the object. When =crypt("PPT") is used, the key is ETH_PPT and "bid" you want is in the value of ETH_PPT. The modified script which was reflected above is as follows. Modified script : function crypt(ticker) { var url = "https://api.etherdelta.com/returnTicker"; var response = UrlFetchApp.fetch(url); var text = response.getContentText(); var json = JSON.parse(text); var price = json["ETH_" + ticker].bid; // Modified return parseFloat(price); // Modified } This modified script retrieves the value of bid for each ticker by putting =crypt("PPT") to a cell in the spreadsheet. Note : It seems that an error response is sometimes returned from the URL. If I misunderstand your question, I'm sorry.