Blog

How to connect the Strava API with Google Sheets and Data Studio

Editor’s Note: Strava updated their OAuth workflow (see here), which may break the code shown below.

This post looks at how to connect the Strava API with Google Sheets and create a visualization in Google Data Studio.

Strava api with google sheets and data studio

Strava is an insanely good app for athletes to track their workouts. I use it to track my running, biking and hiking, and look at the data over time.

This whole project was born out of a frustration with the Strava app.

Whilst it’s great for collecting data, it has some limitations in how it shows that data back to me. The training log shows all of my runs and bike rides, but nothing else. However, I do a lot of hiking too (especially when I’m nursing a running injury) and to me, it’s all one and the same. I want to see it all my activities on the same training log.

So that’s why I built this activity dashboard in Google Data Studio. It shows all of my activities, regardless of type, in a single view.

Connecting the Strava API with Google Sheets

To connect to the Strava API with Google Sheets, follow these steps:

Setup your Google Sheet

  1. Open a new Google Sheet (pro-tip: type sheet.new into your browser window!)
  2. Type a header row in your Google Sheet: “ID”, “Name”, “Type”, “Distance (m)” into cells A1, B1, C1 and D1 respectively
  3. Open the Script Editor (Tools > Script editor)
  4. Give the script project a name e.g. Strava Sheets Integration
  5. Create a second script file (File > New > Script file) and call it oauth.gs
  6. Add the OAuth 2.0 Apps Script library to your project (Resources > Libraries...)
  7. Enter this ID code in the “Add a library” box: 1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF
  8. Select the most recent version of the library from the drop-down (version 34 currently — September 2019) and hit “Save”

Add the code

If you’re new to API and Apps Script, check out my API Tutorial For Beginners With Google Sheets & Apps Script.

In your oauth.gs file, add this code:

var CLIENT_ID = '';
var CLIENT_SECRET = '';

// configure the service
function getStravaService() {
  return OAuth2.createService('Strava')
    .setAuthorizationBaseUrl('https://www.strava.com/oauth/authorize')
    .setTokenUrl('https://www.strava.com/oauth/token')
    .setClientId(CLIENT_ID)
    .setClientSecret(CLIENT_SECRET)
    .setCallbackFunction('authCallback')
    .setPropertyStore(PropertiesService.getUserProperties())
    .setScope('activity:read_all');
}

// handle the callback
function authCallback(request) {
  var stravaService = getStravaService();
  var isAuthorized = stravaService.handleCallback(request);
  if (isAuthorized) {
    return HtmlService.createHtmlOutput('Success! You can close this tab.');
  } else {
    return HtmlService.createHtmlOutput('Denied. You can close this tab');
  }
}

Also available in this GitHub oauth.js repo.

In your code.gs file, add this code:

// custom menu
function onOpen() {
  var ui = SpreadsheetApp.getUi();

  ui.createMenu('Strava App')
    .addItem('Get data', 'getStravaActivityData')
    .addToUi();
}

// Get athlete activity data
function getStravaActivityData() {
  
  // get the sheet
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('Sheet1');

  // call the Strava API to retrieve data
  var data = callStravaAPI();
  
  // empty array to hold activity data
  var stravaData = [];
    
  // loop over activity data and add to stravaData array for Sheet
  data.forEach(function(activity) {
    var arr = [];
    arr.push(
      activity.id,
      activity.name,
      activity.type,
      activity.distance
    );
    stravaData.push(arr);
  });
  
  // paste the values into the Sheet
  sheet.getRange(sheet.getLastRow() + 1, 1, stravaData.length, stravaData[0].length).setValues(stravaData);
}

// call the Strava API
function callStravaAPI() {
  
  // set up the service
  var service = getStravaService();
  
  if (service.hasAccess()) {
    Logger.log('App has access.');
    
    var endpoint = 'https://www.strava.com/api/v3/athlete/activities';
    var params = '?after=1546300800&per_page=200';

    var headers = {
      Authorization: 'Bearer ' + service.getAccessToken()
    };
    
    var options = {
      headers: headers,
      method : 'GET',
      muteHttpExceptions: true
    };
    
    var response = JSON.parse(UrlFetchApp.fetch(endpoint + params, options));
    
    return response;  
  }
  else {
    Logger.log("App has no access yet.");
    
    // open this url to gain authorization from github
    var authorizationUrl = service.getAuthorizationUrl();
    
    Logger.log("Open the following URL and re-run the script: %s",
        authorizationUrl);
  }
}

Also available in this GitHub code.js repo.

Note about the params variable

Have a look at the params variable:

var params = '?after=1546300800&per_page=200'

The ‘after’ parameter means my code will only return Strava activities after the date I give. The format of the date is epoch time and the date I’ve used here is 1/1/2019 i.e. I’m only returning activities from this year.

(Here’s a handy calculator to convert human dates to epoch timestamps.)

The other part of the params variable is the ‘per_page’ variable, which I’ve set to 200. This is the maximum number of records the API will return in one batch.

To get more than 200, you need to add in the ‘page’ parameter and set it to 2,3,4 etc. to get the remaining activities, e.g.

var params = '?after=1546300800&per_page=200&page=2'

Eventually, you’ll want to do that programmatically with a while loop (keep looping while the API returns data and stop when it comes back empty-handed).

Note about parsing the data

The script above parses the response from the API and adds 4 values to the array that goes into the Google Sheet, namely: ID, Name, Type, and Distance.

You can easily add more fields, however.

Look at the Strava documentation to see what fields are returned and select the ones you want. For example, you add total elevation gain like this:

activity.total_elevation_gain

If you add extra fields to the array, don’t forget to change the size of the range you’re pasting the data into in your Google Sheet.

The array and range dimensions must match.

Setup your Strava API application

You need to create your app on the Strava platform so that your Google Sheet can connect to it.

Login to Strava and go to Settings > My API Application or type in https://www.strava.com/settings/api

This will take you to the API application settings page.

Give your application a name, and enter a website and description. You can put anything you want here, as it’s just for display.

The key to unlocking the Strava API, which took me a lot of struggle to find, is to set the “Authorization Callback Domain” as

script.google.com

(Hat tip to this article from Elif T. Kuş, which was the only place I found this.)

Strava API application setup

Next, grab your client ID and paste it into the CLIENT_ID variable on line 1 of your Apps Script code in the oauth.gs file.

Similarly, grab your client secret and paste it into the CLIENT_SECRET variable on line 2 of your Apps Script code in the oauth.gs file.

Copy these two values:

Strava API application

And paste them into your code here:

Oauth client id and secret in Apps Script

Authorize your app

Run the onOpen function from the script editor and authorize the scopes the app needs (external service and spreadsheet app):

Apps Script authorization

If your process doesn’t look like this, and you see a Warning sign, then don’t worry. Click the Advanced option and authorize there instead (see how in this Google Apps Script: A Beginner’s Guide).

Return to your Google Sheet and you’ll see a new custom menu option “Strava App”.

Click on it and select the “Get data” drop-down.

Nothing will happen in your Google Sheet the first time it runs.

Return to the script editor and open the logs (View > Logs). You’ll see the authorization URL you need to copy and paste into a new tab of your browser.

This prompts you to authorize the Strava app:

Strava API with Google Sheets authorization workflow

Boom! Now you’ve authenticated your application.

For another OAuth example, have a look at the GitHub to Apps Script integration which shows these steps for another application.

Retrieve your Strava data!

Now, the pièce de résistance!

Run the “Get data” function again and this time, something beautiful will happen.

Rows and rows of Strava data will appear in your Google Sheet!

Connect Strava To Google Sheets

The code connects to the athlete/activities endpoint to retrieve data about all your activities.

In its present setup, shown in the GIF above, the code parses the data returned by the API and pastes 4 values into your Google Sheet: ID, Name, Type, and Distance.

(The distance is measured in meters.)

Of course, you can extract any or all of the fields returned by the API.

In the data studio dashboard, I’ve used some of the time data to determine what day of the week and what week of the year the activity occurred. I also looked at fields measuring how long the activity took.

Setting a trigger to call the API automatically

Once you’ve established the basic connection above, you’ll probably want to set up a trigger to call the API once a day to get fresh data.

You’ll want to filter out the old data to prevent ending up with duplicate entries. You can use a filter loop to compare the new data with the values you have in your spreadsheet and discard the ones you already have.

Building a dashboard in Google Data Studio

Google Data Studio is an amazing tool for creating visually stunning dashboards.

I was motivated to build my own training log that had all of my activities showing, regardless of type.

First, I created some calculated fields in Apps Script to work out the day of the week and the week number. I added these four fields to my code.gs file:

(new Date(activity.start_date_local)).getDay(), // sunday - saturday: 0 - 6
parseInt(Utilities.formatDate(new Date(activity.start_date_local), SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone(), "w")), // week number
(new Date(activity.start_date_local)).getMonth() + 1, // add 1 to make months 1 - 12
(new Date(activity.start_date_local)).getYear() // get year

And I converted the distance in metres into a distance in miles with this modification in my Apps Script code.gs file:

(activity.distance * 0.000621371).toFixed(2), // distance in miles

From there, you simply create a new dashboard in Data Studio and connect it to your Google Sheet.

The activity log chart is a bubble chart with day of the week on the x-axis and week number as the y-axis, both set to average (so each appears separately). The bubble size is the Distance and the dimension is set to Name.

Bubble chart in Data Studio

Next, I added a Year filter so that I can view each year separately (I’ve got data going back to 2014 in the dataset).

To complete the dashboard, I added a Strava logo and an orange theme.

Strava api with google sheets and data studio

(Note: There’s also an open source Strava API connector for Data Studio, so you could use that to create Strava visualizations and not have to write the code yourself.)

Next steps for the Strava API with Google Sheets

This whole project was conceived as a way to explore the Strava API with Google Sheets. I’m happy to get it working and share it here.

However, I’ll be the first to admit that this project is still a little rough around the edges.

But I am excited to have my Strava data in a Google Sheet now. There are TONS of other interesting stories/trends that I want to explore when I have the time.

There is definitely room for improvement with the Apps Script code. In addition to those mentioned above, and with a little more time, I would bake the OAuth connection into the UI of the Google Sheet front end (using a sidebar), instead of needing to grab the URL from the Logs in your script editor.

And the Data Studio dashboard was rather hastily thrown together to solve the issue of not seeing all my activity data in one place. Again, there’s a lot more work you could do here to improve it.

Time for a run though!

Add A Google Sheets Button To Run Scripts

Learn how to add a Google Sheets button to run your Google Apps Script functions.

Let’s see how this works with a simple example.

Imagine you have an invoice template you use on a regular basis, but it’s a pain to clear out all the values each time you need to start over. Well, you can add a button to Google Sheets so you can run scripts and clear your invoice with a single button click.

Google Sheets button

Let’s start by creating a basic invoice template with placeholders to hold information:

Add button to Google Sheets invoice example

The user can enter information into cells B5, B8, E5 and E6 (shown in yellow).

In the script editor, accessed through Tools > Script Editor, add a very simple script to clear these specific cells out:

function clearInvoice() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const invoiceNumber = sheet.getRange("B5").clearContent();
  const invoiceAmount = sheet.getRange("B8").clearContent();
  const invoiceTo = sheet.getRange("E5").clearContent();
  const invoiceFrom = sheet.getRange("E6").clearContent(); 
}

You can run this function from the script editor and it will clear out the contents of the invoice.

But that’s a pain.

You don’t want to have to open up the script editor every time. You want to do that directly from your Google Sheet.

To do that, add a Google Sheets button.

You add a button via the Insert > Drawing menu.

This brings up the drawing editor where you can easily add a box and style it to look like a button:

Google Sheets button drawing

When you click Save and Close, this drawing gets added to your Google Sheet. You can click on it to resize it or drag it around to reposition it.

To assign a script, click the three little dots in the top right of the drawing and select Assign Script:

Google Sheets button assign script

Then type in the name of the function you want to run from your Apps Script code. In this example, choose the clearInvoice function (i.e. like the code above!).

Now, when you click the button it will clear out the invoice for you!

Button with apps script in google sheets

Note: to edit or move the button after you’ve assigned it to a script, you now need to right-click on it.

See Create, insert & edit drawings in the Google Documentation for more info on the Drawing feature.

API Tutorial For Beginners With Google Sheets & Apps Script

In this API tutorial for beginners, you’ll learn how to connect to APIs using Google Apps Script, to retrieve data from a third-party and display it in your Google Sheet.

Example 1 shows you how to use Google Apps Script to connect to a simple API to retrieve some data and show it in Google Sheets:

API tutorial for beginners: Random math facts from Numbers API in Google Sheet

In Example 2, we’ll use Google Apps Script to build a music discovery application using the iTunes API:

Itunes API with Google Sheets

Finally, in example 3, I’ll leave you to have a go at building a Star Wars data explorer application, with a few hints:

Star Wars API explorer in Google Sheets using Google Apps Script

API tutorial for beginners: what is an API?

You’ve probably heard the term API before. Maybe you’ve heard how tech companies use them when they pipe data between their applications. Or how companies build complex systems from many smaller micro-services linked by APIs, rather than as single, monolithic programs nowadays.

API stands for “Application Program Interface”, and the term commonly refers to web URLs that can be used to access raw data. Basically, the API is an interface that provides raw data for the public to use (although many require some form of API authentication).

As third-party software developers, we can access an organization’s API and use their data within our own applications.

The good news is that there are plenty of simple APIs out there, which we can cut our teeth on. We’ll see three of them in this beginner api tutorial.

We can connect a Google Sheet to an API and bring data back from that API (e.g. iTunes) into our Google Sheet using Google Apps Script. It’s fun and really satisfying if you’re new to this world.

API tutorial for beginners: what is Apps Script?

In this API tutorial for beginners, we’ll use Google Apps Script to connect to external APIs.

Google Apps Script is a Javascript-based scripting language hosted and run on Google servers, that extends the functionality of Google Apps.

If you’ve never used it before, check out my post: Google Apps Script: A Beginner’s Guide

Does coding fill you with dread? In that case, you can still achieve your goals using a no-code option to sync live data into Google Sheets. Check out Coefficient’s sidebar extension that offers Google Sheets connectors for CRMs, BI tools, databases, payment platforms, and more.

Example 1: Connecting Google Sheets to the Numbers API

We’re going to start with something super simple in this beginner api tutorial, so you can focus on the data and not get lost in lines and lines of code.

Let’s write a short program that calls the Numbers API and requests a basic math fact.

Step 1: Open a new Sheet

Open a new blank Google Sheet and rename it: Numbers API Example

Step 2: Go to the Apps Script editor

Navigate to Tools > Script Editor...

Access script editor through toolbar

Step 3: Name your project

A new tab opens and this is where we’ll write our code. Name the project: Numbers API Example

Step 4: Add API example code

Remove all the code that is currently in the Code.gs file, and replace it with this:

function callNumbers() {
  
  // Call the Numbers API for random math fact
  var response = UrlFetchApp.fetch("http://numbersapi.com/random/math");
  Logger.log(response.getContentText());
  
}

We’re using the UrlFetchApp class to communicate with other applications on the internet to access resources, to fetch a URL.

Now your code window should look like this:

Numbers API Google Apps Script code

Step 5: Run your function

Run the function by clicking the play button in the toolbar:

Run Apps Script button

Step 6: Authorize your script

This will prompt you to authorize your script to connect to an external service. Click “Review Permissions” and then “Allow” to continue.

Apps Script Review Permissions

Apps Script authorization

Step 7: View the logs

Congratulations, your program has now run. It’s sent a request to a third party for some data (in this case a random math fact) and that service has responded with that data.

But wait, where is it? How do we see that data?

Well, you’ll notice line 5 of our code above was Logger.log(....) which means that we’ve recorded the response text in our log files.

So let’s check it out.

Go to menu button Execution Log

You’ll see your answer (you may of course have a different fact):

[17-02-03 08:52:41:236 PST] 1158 is the maximum number of pieces a torus can be cut into with 18 cuts.

which looks like this in the popup window:

Apps script logger output

Great! Try running it a few times, check the logs and you’ll see different facts.

Next, try changing the URL to these examples to see some different data in the response:

http://numbersapi.com/random/trivia
http://numbersapi.com/4/17/date
http://numbersapi.com/1729

You can also drop these directly into your browser if you want to play around with them. More info at the Numbers API page.

So, what if we want to print the result to our spreadsheet?

Well, that’s pretty easy.

Step 8: Add data to Sheet

Add these few lines of code (lines 7, 8 and 9) underneath your existing code:

function callNumbers() {
  
  // Call the Numbers API for random math fact
  var response = UrlFetchApp.fetch("http://numbersapi.com/random/math");
  Logger.log(response.getContentText());
  
  var fact = response.getContentText();
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.getRange(1,1).setValue([fact]);
  
}

Line 7 simply assigns the response text (our data) to a variable called fact, so we can refer to it using that name.

Line 8 gets hold of our current active sheet (Sheet1 of Numbers API Example spreadsheet) and assigns it to a variable called sheet, so that we can access it using that name.

Finally in line 9, we get cell A1 (range at 1,1) and set the value in that cell to equal the variable fact, which holds the response text.

Step 9: Run & re-authorize

Run your program again. You’ll be prompted to allow your script to view and manage your spreadsheets in Google Drive, so click Allow:

Apps Script Review Permissions

Apps script spreadsheet authorization

Step 10: See external data in your Sheet

You should now get the random fact showing up in your Google Sheet:

Random math fact from Numbers API in Google Sheet

How cool is that!

To recap our progress so far in this API Tutorial for Beginners: We’ve requested data from a third-party service on the internet. That service has replied with the data we wanted and now we’ve output that into our Google Sheet!

Step 11: Copy data into new cell

The script as it’s written in this API Tutorial for Beginners will always overwrite cell A1 with your new fact every time you run the program. If you want to create a list and keep adding new facts under existing ones, then make this minor change to line 9 of your code (shown below), to write the answer into the first blank row:

function callNumbers() {
  
  // Call the Numbers API for random math fact
  var response = UrlFetchApp.fetch("http://numbersapi.com/random/math");
  Logger.log(response.getContentText());
  
  var fact = response.getContentText();
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.getRange(sheet.getLastRow() + 1,1).setValue([fact]);
  
}

Your output now will look like this:

Random math facts from Numbers API in Google Sheet

One last thing we might want to do with this application is add a menu to our Google Sheet, so we can run the script from there rather than the script editor window. It’s nice and easy!

Step 12: Add the code for a custom menu

Add the following code in your script editor:

function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Custom Numbers API Menu')
      .addItem('Display random number fact','callNumbers')
      .addToUi();
}

Your final code for the Numbers API script should now match this code on GitHub.

Step 13: Add the custom menu

Run the onOpen function, which will add the menu to the spreadsheet. We only need to do this step once.

Add custom apps script menu

Step 14: Run your script from the custom menu

Use the new menu to run your script from the Google Sheet and watch random facts pop-up in your Google Sheet!

Use custom apps script menu

Alright, ready to try something a little harder?

Let’s build ourselves a music discovery application in Google Sheets.

Example 2: Music Discovery Application using the iTunes API

This application retrieves the name of an artist from the Google Sheet, sends a request to the iTunes API to retrieve information about that artist and return it. It then displays the albums, song titles, artwork and even adds a link to sample that track:

Google Sheets and iTunes API using Apps Script

It’s actually not as difficult as it looks.

Getting started with the iTunes API Explorer

Start with a blank Google Sheet, name it “iTunes API Explorer” and open up the Google Apps Script editor.

Clear out the existing Google Apps Script code and paste in this code to start with:

function calliTunes() {
  
  // Call the iTunes API
  var response = UrlFetchApp.fetch("https://itunes.apple.com/search?term=coldplay");
  Logger.log(response.getContentText());
}

Run the program and accept the required permissions. You’ll get an output like this:

iTunes API output

Woah, there’s a lot more data being returned this time so we’re going to need to sift through it to extract the bits we want.

Parsing the iTunes data

So try this. Update your code to parse the data and pull out certain bits of information:

function calliTunes() {
  
  // Call the iTunes API
  var response = UrlFetchApp.fetch("https://itunes.apple.com/search?term=coldplay");
  
  // Parse the JSON reply
  var json = response.getContentText();
  var data = JSON.parse(json);
  
  Logger.log(data);
  Logger.log(data["results"]);
  Logger.log(data["results"][0]);
  Logger.log(data["results"][0]["artistName"]);
  Logger.log(data["results"][0]["collectionName"]);
  Logger.log(data["results"][0]["artworkUrl60"]);
  Logger.log(data["results"][0]["previewUrl"]);
  
}

Line 4: We send a request to the iTunes API to search for Coldplay data. The API responds with that data and we assign it to a variable called response, so we can use that name to refer to it.

Lines 7 and 8: We get the context text out of the response data and then parse the JSON string response to get the native object representation. This allows us to extract out different bits of the data.

So, looking first at the data object (line 10):

iTunes api data packet

You can see it’s an object with the curly brace at the start {

The structure is like this:

{
resultCount = 50,
results = [ ....the data we're after... ] }

iTunes api data packet

Line 11: we extract the “results”, which is the piece of data that contains the artist and song information, using:

data["results"]

Line 12: There are multiple albums returned for this artist, so we grab the first one using the [0] reference since the index starts from 0:

data["results"][0]

This shows all of the information available from the iTunes API for this particular artist and album:

iTunes api data results

Lines 13 – 16: Within this piece of data, we can extract specific details we want by referring to their names:

e.g. data["results"][0]["collectionName"]

to give the following output:

iTunes api details

Use comments (“//” at the start of a line) to stop the Logger from logging the full data objects if you want. i.e. change lines 10, 11 and 12 to be:

// Logger.log(data);
// Logger.log(data[“results”]);
// Logger.log(data[“results”][0]);

This will make it easier to see the details you’re extracting.

Putting this altogether in an application

If we want to build the application that’s showing in the GIF at the top of this post, then there are a few steps we need to go through:

  • Setup the Google Sheet
  • Retrieve the artist name from the Google Sheet with Google Apps Script
  • Request data from iTunes for this artist with Google Apps Script
  • Parse the response to extract the relevant data object with Google Apps Script
  • Extract the specific details we want (album name, song title, album artwork, preview url)
  • Clear out any previous results in the Google Sheet before showing the new results
  • Display the new results in our Google Sheet
  • Add a custom menu to run the program from the Google Sheet, not the script editor

It’s always a good idea to write out a plan like this before you commit to writing any lines of code.

That way you can think through the whole application and what it’s going to do, which allows you to make efficient choices with how you setup your code.

So the first thing to do is setup a Google Sheet. I’ll leave this up to you, but here’s a screenshot of my basic Google Sheet setup:

iTunes Google Sheet

The important thing to note is the location of the cell where a user types in the artist name (11th row, 2nd column) as we’ll be referring to that in our code.

iTunes API Explorer code

And here’s the Google Apps Script code for our application:

// --------------------------------------------------------------------------------------------------
//
// iTunes Music Discovery Application in Google Sheets
//
// --------------------------------------------------------------------------------------------------

// custom menu
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Custom iTunes Menu')
      .addItem('Get Artist Data','displayArtistData')
      .addToUi();
}

// function to call iTunes API
function calliTunesAPI(artist) {
  
  // Call the iTunes API
  var response = UrlFetchApp.fetch("https://itunes.apple.com/search?term=" + artist + "&limit=200");
  
  // Parse the JSON reply
  var json = response.getContentText();
  return JSON.parse(json);
  
}


function displayArtistData() {
  
  // pick up the search term from the Google Sheet
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  
  var artist = sheet.getRange(11,2).getValue();
  
  var tracks = calliTunesAPI(artist);
  
  var results = tracks["results"];
  
  var output = []
  
  results.forEach(function(elem,i) {
    var image = '=image("' + elem["artworkUrl60"] + '",4,60,60)';
    var hyperlink = '=hyperlink("' + elem["previewUrl"] + '","Listen to preview")';
    output.push([elem["artistName"],elem["collectionName"],elem["trackName"],image,hyperlink]);
    sheet.setRowHeight(i+15,65);
  });
  
  // sort by album
  var sortedOutput = output.sort( function(a,b) {
    
    var albumA = (a[1]) ? a[1] : 'Not known';  // in case album name undefined 
    var albumB = (b[1]) ? b[1] : 'Not known';  // in case album name undefined
    
    if (albumA < albumB) { return -1; } else if (albumA > albumB) {
      return 1;
    }
    // names are equal
    return 0;
  });
  
  // adds an index number to the array
  sortedOutput.forEach(function(elem,i) {
    elem.unshift(i + 1);
  });
  
  var len = sortedOutput.length;
  
  // clear any previous content
  sheet.getRange(15,1,500,6).clearContent();
  
  // paste in the values
  sheet.getRange(15,1,len,6).setValues(sortedOutput);
  
  // formatting
  sheet.getRange(15,1,500,6).setVerticalAlignment("middle");
  sheet.getRange(15,5,500,1).setHorizontalAlignment("center");
  sheet.getRange(15,2,len,3).setWrap(true);
  
}

Here’s the iTunes API script file on GitHub.

How it works:

Let’s talk about a few of the key lines of code in this program:

Lines 16 – 25 describe a function that takes an artist name, calls the API with this artist name and then returns the search results from the API. I’ve encapsulated this as a separate function so I can potentially re-use it elsewhere in my program.

The main program starts on line 28.

On line 34, I retrieve the name of the artist that has been entered on the Google Sheet, and we call our API function with this name on line 36.

On lines 42 – 47, I take the results returned by the API, loop over them and pull out just the details I want (artist name, album name, song title, album artwork and preview track). I push all of this into a new array called output.

Next I sort and add an index to the array, although both of these are not mandatory steps.

On line 68, I clear out any previous content in my sheet.

Then on line 71, I paste in the new data, starting at row 15.

Finally, lines 74 – 76 format the newly pasted data, so that the images have space to show properly.

Run the onOpen() function from the script editor once to add the custom menu to your Google Sheet. Then you’ll be able to run your iTunes code from the Google Sheet:

Custom iTunes API menu

Now you can run the program to search for your favorite artist!

More details on the iTunes API:

Documentation for searching the iTunes Store.

Documentation showing the search results JSON packet.

Example 3: Star Wars data explorer using the Star Wars API

This one is a lot of fun! Definitely the most fun example in this API Tutorial for Beginners.

The Star Wars API is a database of all the films, people, planets, starships, species and vehicles in the Star Wars films. It’s super easy to query and the returned data is very friendly.

Star Wars API in Google Sheet

It’s a little easier than the iTunes API because the data returned is smaller and more manageable, and therefore easier to parse when you first get hold of it.

Getting started with the Star Wars API

As with both the previous APIs, start with a simple call to see what the API returns:

/*
 * Step 1:
 * Most basic call to the API 
 */
function swapi() {
  
  // Call the Star Wars API
  var response = UrlFetchApp.fetch("http://swapi.dev/api/planets/1/");
  Logger.log(response.getContentText());
}

The data returned looks like this:

API Tutorial for Beginners: Star Wars API data

So, it’s relatively easy to get the different pieces of data you want, with code like this:

/*
 * Step 2:
 * Same basic call to the API 
 * Parse the JSON reply
 */
function swapi() {
  
  // Call the Star Wars API
  var response = UrlFetchApp.fetch("http://swapi.dev/api/planets/1/");
  
  // Parse the JSON reply
  var json = response.getContentText();
  var data = JSON.parse(json);
  Logger.log(data);
  Logger.log(data.name);
  Logger.log(data.population);
  Logger.log(data.terrain);
}

Well, that should be enough of a hint for you to give this one a go!

Some other tips

In addition to custom menus to run scripts from your Google Sheet, you can add Google Sheets buttons and connect them to a script to run the script when they are clicked. That’s what I’ve done in this example.

On the menu, Insert > Drawing...

Google Sheets insert drawing

Create a button using the rectangle tool:

Google Sheet drawing tool

Finally, right click the drawing when it’s showing in your sheet, and choose Assign Script and type in the name of the function you want to run:

Google Sheet drawing assign script

What else?

Use this CHAR formula to add stars to your Google Sheet:

=CHAR(9734)

I used the font “Orbitron” across the whole worksheet and, whilst it’s not a Star Wars font, it still has that space-feel to it.

The big Star Wars logo is simply created by merging a bunch of cells and using the IMAGE() formula with a suitable image from the web.

Finally, here’s my SWAPI script on GitHub if you want to use it.

API Tutorial for Beginners: Other APIs to try

Here are a few other beginner-friendly APIs to experiment with:

> Giphy API. Example search endpoint: Funny cat GIFs

> Pokémon API. Example search endpoint: Pokemon no. 1

> Open Movie Database API. Example search endpoint: Batman movies

> International Space Station Current Location. Example search endpoint: ISS current location

Also, here’s the official Google documentation on connecting to external APIs.

Finally, here’s a syntax guide for the common forms of API Authentication using Apps Script.

Let me know in the comments what you do with all these different APIs!

Disclosure: Some of the links in this post are affiliate links, meaning I’ll get a small commission if you click the link and subsequently signup to use that vendor’s service. I only do this for tools I use myself and wholeheartedly recommend.

Google Sheets Formula Clock

Behold the Google Sheets Formula Clock, a working analog clock built with a single Google Sheets formula:

Google Sheets Formula Clock
Google Sheets Formula Clock sped up to show several hours

It’s a working analog clock built with a single Google Sheets formula.

That’s right, just a single formula. No Apps Script code. No widgets. No hidden add-ons.

Just a plain ol’ formula in Google Sheets!

Google Sheets Formula Clock

Google Sheets Formula Clock Template

Click here to open the Google Sheets Formula Clock Template

(Click to open the template. Feel free to create your own copy through the File menu: File > Make a copy...)

It might take a moment to update to the current time.

Part 1: Build your own Google Sheets Formula Clock

Step 1

Open a blank Google Sheet or create a new Google Sheet

(Pro-tip: type sheet.new into your browser address bar to do this instantly)

Step 2

Copy the Google Sheets Formula Clock formula below and paste it into the formula bar for cell A1 of your new Sheet:

=SPARKLINE(
ArrayFormula({
QUERY(ArrayFormula({
0, 0, 1 + N("See Comment 1");
0, 0, 0.8 + N("See Comment 2") ;
SEQUENCE(37,1,0,10),
SIN(RADIANS(SEQUENCE(37,1,0,10))),
COS(RADIANS(SEQUENCE(37,1,0,10))) + N("See Comment 3") ;
SEQUENCE(12,1,30,30),
0.9 * SIN(RADIANS(SEQUENCE(12,1,30,30))),
0.9 * COS(RADIANS(SEQUENCE(12,1,30,30))) + N("See Comment 4") ;
SEQUENCE(12,1,30,30),
SIN(RADIANS(SEQUENCE(12,1,30,30))),
COS(RADIANS(SEQUENCE(12,1,30,30))) + N("See Comment 5") ;
SEQUENCE(4,1,90,90),
0.8 * SIN(RADIANS(SEQUENCE(4,1,90,90))),
0.8 * COS(RADIANS(SEQUENCE(4,1,90,90))) + N("See Comment 6") ;
SEQUENCE(4,1,90,90),
SIN(RADIANS(SEQUENCE(4,1,90,90))),
COS(RADIANS(SEQUENCE(4,1,90,90))) + N("See Comment 7")
}),
"SELECT Col2, Col3 ORDER BY Col1",
0 + N("See Comment 8")
) ;
IF(
MINUTE(NOW()) = 0,
0,
SIN(RADIANS(SEQUENCE(MINUTE(NOW())/60*360,1,1,1)))
),
IF(
MINUTE(NOW())=0,
1,
COS(RADIANS(SEQUENCE(MINUTE(NOW())/60*360,1,1,1)))
) + N("See Comment 9");
0, 0 + N("See Comment 10") ;
0.75 * SIN(RADIANS((MOD(HOUR(NOW()),12)/12 * 360) + MINUTE(NOW())/60 * 30)),
0.75 * COS(RADIANS((MOD(HOUR(NOW()),12)/12 * 360) + MINUTE(NOW())/60 * 30)) + N("See Comment 11")
}),
{"linewidth",2 + N("See Comment 12")
+ N("
Comments:
1: Initial (0,1) coordinate at top of circle. Extra 0 included for sort.
2: Coordinates to create mark at 12 o'clock.
3: Coordinates to draw initial circle. Joins markers every 10 degrees starting from 0 at top of circle, e.g. 0, 10, 20, 30,...360
4: Sequence of coordinates every 30 degrees to create small markers for hours 1, 2, 4, 5, 7, 8, 10, 11
5: Sequence of coordinates to connect the 30 degree small markers. Needed to place them correctly on circle.
6: Sequence of coordinates every 90 degrees to create large markers for hours 12, 3, 6, 9
7: Sequence of coordinates to connect the 90 degree large markers. Needed to place them correctly on circle.
8: QUERY function used to sort the circle data by the degrees column, then select just the (x,y) coordinate columns (numbers 2 and 3) to use.
9: Coordinates to create the minute hand. Includes an IF statement to avoid an error when the minute hand arrives at the 12 mark.
10: Coordinates to return to centre of clock at (0,0) after minute hand, to be ready to draw hour hand.
11: Coordinates to create the hour hand.
12: Set linewidth of the Sparkline to 2.
.
.
Google Sheets Formula Clock
June 2019
Created by Ben Collins, Google Developer Expert and Founder of The Collins School Of Data
Website: benlcollins.com
Twitter: @benlcollins
"
)}
)

Initially it will look like this:

Paste Google Sheets Formula Clock in cell A1

Step 3

Make row 1 wider by hovering between rows 1 and 2 and using the grab hand to drag the row boundary down. Make the cell wide enough to create a circle:

Make the formula bar wider in Google Sheets

Step 4

This is the step that makes the clock tick!

Under File > Spreadsheet settings set the spreadsheet calculation settings to be “On change and every minute”, like so:

Google Sheet spreadsheet settings

This ensures that the NOW function is refreshed every minute, so our clock hands move around the circle. That’s it!

You should see the hands of your clock moving around the face.

Tick-tock! Tick-tock!

Part 2: How Does It Work?

So there are a few things going on here.

We need a way to get the current hour and minute values and have them update automatically.

Then somehow we need to draw a clock face with hands using…formulas?

Let’s run through the building blocks…

Create A Circle With The Sparkline Function

The SPARKLINE function is used to create miniature charts inside a single cell. That’s its modus operandi.

However, we can also supply it with a range of x- and y-coordinates to create 2-d shapes, like a circle for example.

Use the following five steps to create a circle with a sparkline:

1) Start with this function in cell A1:

= SEQUENCE ( 37, 1, 0, 10 )

The SEQUENCE function creates 37 rows in a single column, starting from 0 and increasing in increments of 10 each.

I.e. it outputs a column of numbers representing every 10 degrees of a circle, up to 360 degrees.

2) In column B, we add this Array Formula in cell B1:

= ArrayFormula ( SIN ( RADIANS ( $A$1:$A$37 ) ) )

3) And in column C, this one in cell C1:

= ArrayFormula ( COS ( RADIANS ( $A$1:$A$37 ) ) )

Columns B and C now give you the coordinates of a circle.

4) Let’s plug them into the SPARKLINE function in cell D1 with this function:

= SPARKLINE ( B:C )

5) Lastly, make row 1 wider to show the circle.

Boom!

The SPARKLINE function draws a circle for us:

Sparkline Circle in Google Sheets

Then, we need to create a time that automatically updates every minute. Thankfully that’s relatively easy to do with the NOW function:

NOW Function + Spreadsheet Settings

(Feel free to type these formulas in to the side of your sparkline workings in column B, C and D.)

= NOW()

The NOW Function in Google Sheets outputs a timestamp with a time to the nearest second. It’s a volatile function, which means it recalculates every time a change is made to the Sheet. In other words, it gives a new timestamp.

Per the Step 4 in Part 1 above, we can set the Sheet to update every minute, so the NOW function updates every minute.

Get The MINUTE And HOUR From NOW

It’s relatively easy to extract the minute and hour from the timestamp, with these two functions:

= MINUTE( NOW() )

and

= HOUR ( NOW() )

We need to convert these to degrees on a circle to show how far round the hands have gone.

The formulas become:

= MINUTE( NOW() ) / 60 * 360

and

= MOD( HOUR( NOW() ), 12 ) / 12 * 360

respectively.

Later we’ll need to convert these to RADIANS and then into coordinates for the sparkline function.

That’s the mechanics of the clock-tick-tock part, but we still need to add them to our sparkline clock.

Add The Clock Hands

The middle of our circle is represented by the coordinates (0,0).

Currently, our sparkline has positioned us at the 12 o’clock position, represented by (0,1).

To add the minute hand, we need to draw another arc around the circle to travel around the edge of the circle to the current minute value, e.g. if it’s half past the hour then we need to draw another half circle to position ourselves at the bottom of the circle.

Then we can simply draw a line back to the center of the circle, and that’s our minute hand!

So, add this function to cell B38:

=ArrayFormula( SIN ( RADIANS ( SEQUENCE ( MINUTE ( NOW( ) ) / 60 * 360 , 1 , 1 , 1 ) ) ) )

And add this one to cell C38:

=ArrayFormula( COS ( RADIANS ( SEQUENCE ( MINUTE ( NOW( ) ) / 60 * 360 , 1 , 1 , 1 ) ) ) )

Essentially, what these two formulas are doing is working out how many degrees around the circle we need to go, and calculating the coordinates.

Finally, let’s return to the center of our circle, thereby drawing the minute hand.

In cell B398 put a 0.

In cell C398 put a 0.

They need to be on row 398 to give the array formula for the minutes enough space to expand (max 360 rows).

The “clock” now looks like this, and if you’ve set your spreadsheet to update every minute (see Step 4 in Part 1 above) then you’ll see this hand move around the clock.

Google Sheets sparkline minute hand

To add the hour hand, it’s a case of drawing a line from the centre coordinate (0,0) — where we are now — back out to the edge, again, going as far around the circle as needed to represent the current hour.

Add this formula to cell B399:

= 0.75 * SIN ( RADIANS ( ( MOD ( HOUR ( NOW( ) ) , 12 ) / 12 * 360 ) ) )

And this formula to cell C399:

= 0.75 * COS ( RADIANS ( ( MOD ( HOUR ( NOW( ) ) , 12 ) / 12 * 360 ) ) )

This adds the hour hand.

The 0.75 multiplier at the front of the formula shortens the hour hand a little to distinguish it from the second hand.

Boom!

Now you have a working clock:

Sparkline clock hour hand

Click here to view the template of this intermediary step.

Fix The Hour Issue

Unfortunately, in it’s current state, the formula breaks down at the top of the hour:

Google Sheets error message

This is easily solved by wrapping the minute hand calculation with an IF statement to set it to zero at the top of the hour. This IF statement tests to see if the minute component of NOW is equal to zero and sets the value to 0 if it is, otherwise we just proceed with the full SEQUENCE function.

Change the formula in cell B38 to

=ArrayFormula( IF( MINUTE( NOW() ) = 0 , 0 , SIN( RADIANS( SEQUENCE( MINUTE( NOW() ) / 60*360 , 1 , 1 , 1 )))))

and the formula in cell C38 to

=ArrayFormula( IF( MINUTE( NOW() ) = 0 , 0 , COS( RADIANS( SEQUENCE( MINUTE( NOW() ) / 60*360 , 1 , 1 , 1 )))))

It won’t look any different but you’ll avoid that error when the minute hand goes past the hour mark.

This formula is demonstrated in tab 2 of the intermediary template.

The clock will now look something like this:

Sparkline clock version 1

So what’s left?

Improvements

You might consider the following improvements, but I’ll leave these as a challenge for you:

  • Smoothing the hour hand, so it doesn’t jump in discrete steps from hour to hour but instead moves smoothly between the hours in proportion to the number of minutes passed. (See the GIF image at the start of this post.)
  • Adding tick marks at each of the 12 hour marks around the clock face.
  • Combining all the separate formulas into a single array formula. Hint: you need to make use of array literals with the constituent formulas.
  • Add comments to explain the parts of the formula (see adding comments using the N function)

Implementing all of these is a little tricky, not the least because the formula gets rather long!

The best approach is to build in steps, employing the Onion Method technique to avoid frustrating errors.

Hickory, dickory, dock.
The mouse ran up the sparkline clock.
The sparkline clock struck one,
The mouse ran down,
Hickory, dickory, dock. 🐁 ⏱️

US Timezone Map

Combining many of these analog sparkline clocks onto a tile map, you can create this timezone map of the US:

US timezone map in Google Sheets

Digital Clock?

See also this impressive digital clock built in Google Sheets by Robin Lord.

What Else Can You Draw With Sparklines?

Your imagination is the only limit with the sparkline function.

How about an Etch-A-Sketch clone built using a sparkline formula?

Etch A Sheet Game In Google Sheets
Etch A Sheet Game In Google Sheets

Etch A Sheet in Google Sheets

Or how about an outline of the Saturn V rocket?

Google Sheets sparkline Saturn V rocket

Or a pie chart built with a single sparkline array formula?

Google Sheets sparkline pie chart

This pie chart actually inspired the analog clock…you can probably see why!