Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
// 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 Weight for Yesterday', 'getWeight')
// see step count example at
function getWeight() {
var start = new Date();
var end = new Date();
var fitService = getFitService();
var request = {
"aggregateBy": [{
"dataTypeName": "",
"dataSourceId": ""
"bucketByTime": { "durationMillis": 86400000 },
"startTimeMillis": start.getTime(),
"endTimeMillis": end.getTime()
var response = UrlFetchApp.fetch('', {
headers: {
Authorization: 'Bearer ' + fitService.getAccessToken()
'method' : 'post',
'contentType' : 'application/json',
'payload' : JSON.stringify(request, null, 2)
var json = JSON.parse(response.getContentText());
if (json.bucket[0].dataset[0].point.length > 0) {
var weight = json.bucket[0].dataset[0].point[0].value[0].fpVal;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Weight');
sheet.appendRow([start, weight]);
// functions below adapted from Google OAuth example at
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.
// Set the client ID and secret, from the Google Developers Console.
// Set the name of the callback function in the script referenced
// above that should be invoked to complete the OAuth flow.
// Set the property store where authorized tokens should be persisted.
// Set the scopes to request (space-separated for Google services).
// see for a list of Google Fit scopes
// 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();
} 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');
function clearProps() {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment