I Thought He Came With You is Robert Ellison’s blog about software, marketing, politics, photography and time lapse.

Export Google Fit Daily Steps to a Google Sheet

Google Fit Daily Step Export

Google Fit is a great way to keep track of your daily step count without needing to carry a Fitbit or other dedicated tracker. It's not easy to get that data out though, as far as I can tell the only way is Google Takeout which is not made for automation. Luckily there is an API and you can do almost anything with Google Sheets.

If you're looking to export your step count this post has everything you need, just follow the instructions below to get your spreadsheet up and running. This is also a good primer on using OAuth2 with Google Apps Script and should be a decent starting point for a more complex Google Fit integration. If you have any questions or feedback please leave a comment below.

To get started you need a Google Sheet, an apps script project attached to the sheet and a Google API Project that will provide access to the Fitness API. That might sound intimidating but it should only take a few minutes to get everything up and running.

In Google Drive create a new spreadsheet and call it whatever you like. Rename the first tab to 'Steps'. Enter 'Date' in cell A1 and 'Steps' in cell B1. Next select 'Script editor...' from the Tools menu which will open a new apps script project.

Give the apps script project a name and then select 'Libraries...' from the Resources menu. Next to 'Add a library' enter 1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF ad click Add. This will find the Google OAuth2 library. Choose the most recent version (24 at the time of writing) and click Save. Then select 'Project properties' from the File menu and make a note of the Script ID (a long series of letters and numbers).

Open the Google API Console. Create a new project and name it something like 'Google Fit Sheet'. From the Dashboard click Enable APIs and Services and find and select the Fitness API. Then go to Keys and create an OAuth Client ID. You'll be asked to create a consent screen, the only field you need to enter is the product name (i.e. 'My Fit App'). Then choose Web Application as the application type. You need to set the name and the authorized redirect URL. The redirect URL is https://script.google.com/macros/d/{SCRIPTID}/usercallback replacing {SCRIPTID} with the actual Script ID you made a note of above. After adding this make a note of the Client ID and Client Secret.

Go back to the apps script project and paste the code below into the Code.gs window:

// add your Google API Project OAuth client ID and client secret here
var ClientID = '';
var ClientSecret = '';

function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Google Fit')
      .addItem('Authorize if needed (does nothing if already authorized)', 'showSidebar')
      .addItem('Get Steps for Yesterday', 'getSteps')
      .addToUi();
}

// see step count example at https://developers.google.com/fit/scenarios/read-daily-step-total
function getSteps() {
  var start = new Date();
  start.setHours(0,0,0,0);
  start.setDate(start.getDate()-1);

  var end = new Date();
  end.setHours(23,59,59,999);
  end.setDate(end.getDate()-1);
  
  var fitService = getFitService();
  
  var request = {
    "aggregateBy": [{
      "dataTypeName""com.google.step_count.delta",
      "dataSourceId""derived:com.google.step_count.delta:com.google.android.gms:estimated_steps"
    }],
    "bucketByTime": { "durationMillis": 86400000 },
    "startTimeMillis": start.getTime(),
    "endTimeMillis": end.getTime()
  };
  
  var response = UrlFetchApp.fetch('https://www.googleapis.com/fitness/v1/users/me/dataset:aggregate', {
    headers: {
      Authorization: 'Bearer ' + fitService.getAccessToken()
    },
    'method' : 'post',
    'contentType' : 'application/json',
    'payload' : JSON.stringify(request, null, 2)
  });
  
  var json = JSON.parse(response.getContentText());
  var steps = json.bucket[0].dataset[0].point[0].value[0].intVal;
  
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('Steps');
  sheet.appendRow([start, steps]);
}

// functions below adapted from Google OAuth example at https://github.com/googlesamples/apps-script-oauth2

function getFitService() {
  // Create a new service with the given name. The name will be used when
  // persisting the authorized token, so ensure it is unique within the
  // scope of the property store.
  return OAuth2.createService('fit')

      // Set the endpoint URLs, which are the same for all Google services.
      .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
      .setTokenUrl('https://accounts.google.com/o/oauth2/token')

      // Set the client ID and secret, from the Google Developers Console.
      .setClientId(ClientID)
      .setClientSecret(ClientSecret)

      // Set the name of the callback function in the script referenced
      // above that should be invoked to complete the OAuth flow.
      .setCallbackFunction('authCallback')

      // Set the property store where authorized tokens should be persisted.
      .setPropertyStore(PropertiesService.getUserProperties())

      // Set the scopes to request (space-separated for Google services).
      // see https://developers.google.com/fit/rest/v1/authorization for a list of Google Fit scopes
      .setScope('https://www.googleapis.com/auth/fitness.activity.read')

      // Below are Google-specific OAuth2 parameters.

      // Sets the login hint, which will prevent the account chooser screen
      // from being shown to users logged in with multiple accounts.
      .setParam('login_hint', Session.getActiveUser().getEmail())

      // Requests offline access.
      .setParam('access_type', 'offline')

      // Forces the approval prompt every time. This is useful for testing,
      // but not desirable in a production application.
      //.setParam('approval_prompt', 'force');
}

function showSidebar() {
  var fitService = getFitService();
  if (!fitService.hasAccess()) {
    var authorizationUrl = fitService.getAuthorizationUrl();
    var template = HtmlService.createTemplate(
        '<a href="<?= authorizationUrl ?>" target="_blank">Authorize</a>. ' +
        'Close this after you have finished.');
    template.authorizationUrl = authorizationUrl;
    var page = template.evaluate();
    SpreadsheetApp.getUi().showSidebar(page);
  } else {
  // ...
  }
}

function authCallback(request) {
  var fitService = getFitService();
  var isAuthorized = fitService.handleCallback(request);
  if (isAuthorized) {
    return HtmlService.createHtmlOutput('Success! You can close this tab.');
  } else {
    return HtmlService.createHtmlOutput('Denied. You can close this tab');
  }
}

Right at the top of the code there are spaces to enter the Client ID and Client Secret from the API Console. Enter these and save the project.

Switch back to your Google Sheet and reload. After reloading there will be a Google Fit menu item. First select Authorize... You'll get a screen to authorize the script and then a sidebar with a link. Click the link to authorize the script to access your Google Fit data. You can then close the sidebar and select Get Steps for Yesterday from the Google Fit menu. You should see a new row added to the spreadsheet with yesterday's date and step count.

The final step is to automate pulling in the data. Go back to the apps script project and select Current project's triggers from the Edit menu. Add a trigger to run getSteps() as a time driven day timer - I recommend between 5 and 6am. You can also click notifications to add an email alert if anything goes wrong, like your Google Fit authorization expiring (in which case you just need to come back and authorize from the Google Fit menu again.

At this point you're all set. Every day the spreadsheet will automatically update with your step count from the day before. You can add charts, moving averages, export to other systems, pull in your weight or BMI, etc. I want to add a seven day moving average step count to this blog somewhere as a semi-public motivational tool... watch this space.

Comments

Dan

This is great! Everything worked up until the end... I get the sidebar with the "Authorize" link, which I click and get a "sign in" page listing my google account name. I click ALLOW, only to receive a new page with just the following:

Google Apps Script

Authorization is required to perform that action

Also, is it correct that you put the header "Steps" in B2? Or should it be B1?

Finally, is there a way to make it go back and get a week of historical steps? I'm trying to pull the last week of step count, and the web UI and app don't seem to have a way to do this easily, so I was hoping your script would help.

Robert Ellison

Hi Dan - you probably need to authorize the script as well as the API access to your Google Fit data. If you can't get it working send a screenshot of where you're getting stuck to [email protected]t and I'll see if I can figure it out.

Steps should be in B1. Thanks for pointing this out, I've fixed this in the instructions above.

When I set this up I copied historical data from the app. Click the menu and go to Timeline and at the top pick Day view and Steps. Should be easy to copy out the data this way. Alternatively in the code at the top of getSteps() there are two dates for the start and end of the period, both of which have a -1 to get to yesterday. You could change this to -2 to get the date before and so on.

Gustavo El Khoury Seoane

This is great! I'll be playing with Google Fit data on my spare time and this is super helpful. Thanks for sharing!

A quick thing: could you share the link to the Reference guide for the Google Fit API that you're using, in case we need to explore further? I couldn't find it in the Google Apps Script reference material

Rob

I'm having trouble at the same point as Dan. Everything works until clicking 'Authorize' in the sidebar in Google sheets - after clicking 'Allow' I get a page stating 'Authorization is required to perform that action.'

I should note that I don't have a GCP account - though that didn't stop me from authorizing the API.

I did note that there is a Google Sheets Add on called 'Fit Sync' that looks very similar and worked for me. I haven't had a chance to dig into the difference.

Rob

Robert Ellison

Gustavo, the API is linked to in the comment right above the getSteps() function in the code sample.

Robert Ellison

Rob, you do need the Google Fit API to be enabled in the API console. I'm not clear if you've done this or not from the mention of not having a GCP account. If you happen to come back to this and need help feel free to email me at [email protected] and let me know where you're getting stuck.

Josiah Vorst

Very helpful, works great for me. Thanks for taking time to post this!!

Add Comment

All comments are moderated. Your email address is used to display a Gravatar and optionally for notification of new comments and to sign up for the newsletter.