【Fitbit API×Make×GAS】Notionへデータを自動集約し、ライフログを可視化する

「毎日アプリを開くのが面倒」を解決!Fitbitで計測した歩数・睡眠・体重を、MakeとGASを使ってNotionへ自動記録する方法をステップバイステップで紹介します。セルフケアを仕組み化し、客観的なデータで自分の体調や気分の波を可視化したい方必見です。

2026年02月27日
2026年04月11日
【Fitbit API×Make×GAS】Notionへデータを自動集約し、ライフログを可視化する

1. はじめに(今回作るもの)

毎日アプリを開いて入力する手間を省き、自分のライフログをNotionに自動集約して、気分の波(躁鬱)との相関を可視化するためのツールです。クレジット登録が必要なサービスもありますが、無料枠で利用するためお金はかかりません。

完成イメージ
完成イメージ

システム全体のアーキテクチャ

このシステムは、Notion、Fitbit、GAS、OpenWeather、Makeの5つのサービスを連携させています。

  • Notionのデータベースに、毎晩20:00にその日のログが1行ずつ追加されます。
  • 一度作れば「完全放置」でライフログが蓄積されます。

2. 事前準備(必要なもの)

  • Notion:フリープラン(もしうまくいかない場合はアップグレードしてください)
  • Fitbit:デバイスとアカウント(データ元)
  • Googleアカウント:Google Apps Script(GAS)作成用
  • Make (旧Integromat):サービス同士を繋ぐハブ(無料プランでOK)
  • Fitbit Developerアカウント:APIキーの取得用
  • OpenWeatherアカウント:APIキーの取得用(クレジットカードの登録が必要)

3. 実装手順

全体の流れ

Step1:Notion データベースの構築

ここで作成したデータベースにライフログが蓄積されていきます。Notionテンプレートをこちらで配布しているのでご利用ください。

Notionテンプレート

ログ記録用DB

毎晩20:00にこのDB(データベース)に記録されていきます。

  • 名前:日付が入力されます
  • 日付:こちらにも日付が入力されます。フィルター用です
  • 気分:毎日の気分を0〜10の11段階で入力します。必要に応じて入力してください
  • 数値化された気分:気分で入力したものを数値に変換しています。チャート表示をした際に気分を可視化します
  • 天気:設定マスタDB [都市名] プロパティの設定に対応した都市の天気が記録されます。
  • 最高気温:設定マスタDB [都市名] プロパティの設定に対応した都市の最高気温が記録されます
  • 最低気温:設定マスタDB [都市名] プロパティの設定に対応した都市の最低気温が記録されます。
  • 湿度:設定マスタDB [都市名] プロパティの設定に対応した都市の湿度が記録されます。
  • 歩数:Fitbitに記録された20:00時点での歩数が記録されます
  • 消費カロリー:Fitbitに記録された20:00時点での消費カロリーが記録されます
  • 睡眠時間:Fitbitに記録された昨日の睡眠時間が記録されます
  • 入眠:Fitbitに記録された昨日の入眠時間が記録されます
  • 起床::Fitbitに記録された本日の起床時間が記録されます

設定マスタDB

GASやMakeのシナリオ内に機密情報を直接書き込まず、Notion上で一括管理します。

  • 都市名: [ Tokyo,JP ] の形で都市名を入力します。OpenWeatherは全世界の気象データをカバーしているため、たいていの場所は取得が可能です。Geminiなどで確認して入力してください
  • Notion_API_Key:別ツール(今回はMake)からNotionページの読み取り・書き込みなどを行うために必要です
  • DATABASE_ID:DBの設定>リンクをコピーから取得できるURLの一部です。https://www.notion.so/から?vまでの32桁の文字列です
  • Weather_API_Key:OpenWeatherのサイトして取得する無料のAPIキーです

自分の住んでいる都市名を検索するためのプロンプト(AIへの指示)

[ ここに住所や都市名を入力 ] を、OpenWeather APIの「City,CountryCode」形式に変換してください。 もし複数の候補(同名の都市など)がある場合は、最も一般的なものを上位に3つほどリストアップしてください

Notion_API_Keyの取得方法

右上の3点リーダーより接続>インテグレーションを開発をクリック。

内部インテグレーション>新しいインテグレーションを作成をクリック。

インテグレーション名を選択し、ワークスペースを選択。

内部インテグレーションシークレットに記載されている文字列をコピーします。

右上の3点リーダーより接続をクリックし、作成したインテグレーションを接続します。
接続したら設定マスタDBのNotion_API_Keyに先ほどコピーした文字列を入力します。

DATABASE_IDの取得方法

右上の3点リーダーよりビューのリンクをコピークリック。
下記のようなURLがコピーされるので、赤文字部分(32文字)をコピーしてDATEBASE_IDに入力します。

https://www.notion.so/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX?v=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&source=copy_link

Weather_API_Keyの取得方法

OpenWeatherにアクセスにアカウントを作成します。
作成が完了したら、右上のアカウント名>My API Keysをクリック。

Keyという項目に入力されている文字列をコピーし、設定マスタDBのWeather_API_Keyに入力します。

One Call API 3.0に登録します。クレジットカードの登録が必要になりますが、無料枠の範囲で済むので利用料金はかかりません。これで先ほどコピーした文字列(APIキー)が機能するようになります。

One Call API 3.0

Step2:GAS (Google Apps Script) の実装

新規>その他>Google App Scritpから新規ファイルを作成します。
作成したファイルに下記のコードを貼り付けます。

function fetchAndRecordWeather(params) {
  const { city, weather_key, notion_key, db_id, steps, calories, sleep_hours, sleep_start, sleep_end } = params;

  // 1. 緯度・経度の取得
  const geoUrl = `https://api.openweathermap.org/geo/1.0/direct?q=${encodeURIComponent(city)}&limit=1&appid=${weather_key}`;
  const geoResponse = JSON.parse(UrlFetchApp.fetch(geoUrl).getContentText());
  const lat = geoResponse[0].lat;
  const lon = geoResponse[0].lon;

  // 2. 本日の00:00のタイムスタンプを取得
  const now = new Date();
  const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const dt = Math.floor(startOfDay.getTime() / 1000);

  // 3. Time Machine APIで「今日」のデータを取得
  const summaryUrl = `https://api.openweathermap.org/data/3.0/onecall/day_summary?lat=${lat}&lon=${lon}&date=${Utilities.formatDate(startOfDay, "GMT", "yyyy-MM-dd")}&appid=${weather_key}&units=metric&tz=+09:00`;
  const summaryResponse = UrlFetchApp.fetch(summaryUrl);
  const summaryData = JSON.parse(summaryResponse.getContentText());

  const weatherUrl = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${weather_key}&lang=ja&units=metric`;
  const weatherResponse = UrlFetchApp.fetch(weatherUrl);
  const weatherData = JSON.parse(weatherResponse.getContentText());

  // 4. データの抽出
  if (!summaryData || !summaryData.temperature) {
    throw new Error("気象サマリーデータが取得できませんでした");
  }
  const tempMax = summaryData.temperature.max;
  const tempMin = summaryData.temperature.min;
  let weatherDescription = "不明";
  if (weatherData.weather && weatherData.weather.length > 0) {
    weatherDescription = weatherData.weather[0].description; 
  }
  const humidity = (summaryData.humidity && summaryData.humidity.afternoon) ? summaryData.humidity.afternoon : 0;
  const dateDisplay = Utilities.formatDate(now, "JST", "yyyy/MM/dd");

  // 5. Notionペイロード構築
  const payload = {
    parent: { database_id: db_id },
    properties: {
      "名前": { title: [{ text: { content: dateDisplay} }] },
      "天気": { rich_text: [{ text: { content: weatherDescription } }] },
      "日付": { date: { start: now.toISOString() } },
      "最高気温": { number: tempMax },
      "最低気温": { number: tempMin },
      "湿度": { number: humidity },
      "街": { rich_text: [{ text: { content: city } }]  },
      "歩数": { number: Number(steps || 0) },
      "消費カロリー": { number: Number(calories || 0) },
      "睡眠時間": { number: Number(sleep_hours || 0) },
      "入眠": { rich_text: [{ text: { content: sleep_start || "-" } }] },
      "起床": { rich_text: [{ text: { content: sleep_end || "-" } }] },
    }
  };

  const options = {
    method: 'post',
    headers: {
      'Authorization': `Bearer ${notion_key}`,
      'Content-Type': 'application/json',
      'Notion-Version': '2022-06-28'
    },
    payload: JSON.stringify(payload)
  };

  UrlFetchApp.fetch('https://api.notion.com/v1/pages', options);
  return { status: "success", steps: steps };
}

function doGet(e) {
  const params = {
    city: e.parameter.city,
    weather_key: e.parameter.weather_key,
    notion_key: e.parameter.notion_key,
    db_id: e.parameter.db_id,
    steps: e.parameter.steps ,
    calories: e.parameter.calories,
    sleep_hours: e.parameter.sleep_hours,
    sleep_start: e.parameter.sleep_start,
    sleep_end: e.parameter.sleep_end,
  };

  try {
    const result = fetchAndRecordWeather(params);
    return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON);
  } catch (error) {
    return ContentService.createTextOutput(JSON.stringify({status: "error", message: error.message})).setMimeType(ContentService.MimeType.JSON);
  }
}

コードを貼り付けたら、右上のデプロイ>デプロイを管理をクリック。

画像で使われいてるコードは古いものなので、貼り付けるコードを画像のコードが一致しなくても問題ありません。

デプロイメントを作成>種類の選択>ウェブアプリをクリック。

アクセスできるユーザー>全員に変更してデプロイをクリック。

Google has'nt verified this appという画面になったら左下のAdvancedをクリック。Go to XXXXX(プロジェクト名)をクリックして完了画面になったら完了です。
ウェブアプリのURLをコピーしておいてください。Makeの設定で使います。

完了画面になる前にGoogleアカウントの画面が出たら許可してください。

Step3:Make による連携フローの作成

最終的に、以下のモジュールを直線的に配置します。

  1. Notion - Search Objects
  2. HTTP - Make a request(Fitbitのアクティビティを取得)
  3. HTTP - Make a request(Fitbit睡眠ログを取得)
  4. HTTP - Make a request(GASを叩く)

画像はHTTPモジュールが4つありますが、3つ並んでいれば問題ありません。

Notion - Search Objects

画面の空いているところで右クリック>Add a module

Notionで検索をかけてSearch Objectsを追加します。

Connection>AddでNotionと接続します。

  • Connection type:Notion Internal
  • Connection name:任意の名前
  • Internal Integration Token: [ Notion_API_Key ] に入力した文字列

Data source IDSearchをクリックし、検索するDB名を入力します。今回は設定マスタDBを接続するので設定などの単語で検索をかけます。XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXの形で入力されればOKです。

HTTP - Make a request

まず、Fitbit Developerアカウントを作成し、Client IDキーClient Secretキーを取得します。

Fitbit Developer

HTTP>Make a requestを選択してモジュールを作成

Authentication type>OAuth2.0を選択し、Credentials>Addをクリックします。

下記の項目を入力します。

  • Connection name:任意の名前(例:Fitbitなど)
  • Authorize URI:https://www.fitbit.com/oauth2/authorize
  • Token URI:https://api.fitbit.com/oauth2/token
  • Scope:activity sleep
  • Client ID:Fitbit Developerに記載もの
  • Client Secret:Fitbit Developerに記載もの

下記の項目は、左下のAdvanced settingsをオンにすると入力できます。

  • Scope separator:COMMA
  • Custom Headers - item1 - Key:Authorization
  • *Custom Headers - item1 - Value:Basic 生成されたBase64文字列
  • Custom Headers - item2 - Key:Content-Type
  • Custom Headers - item2 - Value:application/x-www-form-urlencoded

Client IDClient Secret を使用して、FitbitのBasic認証に必要なBase64文字列を生成してください。

  1. Client IDとClient Secretをコロンで繋ぐ(Client ID:Client Secret)
  2. その文字列をBase64エンコードする
  3. 最終的なBasic [Base64文字列] の形式で出力してください

Base64エンコードはツールを使っても良いですが、AIに特定のフォーマットで依頼するとミスがなくて楽です。

右下のSaveを押し、表示されるFitbitの項目へのアクセスを許可してエラーが出なければ成功です。

Credentialsに、いま作成したFitbitへの認証を設定します。HTTPモジュールを1つ複製し、URLに下記をそれぞれ入力します。

  • 1つ目のHTTPモジュール:https://api.fitbit.com/1/user/-/activities/date/{{formatDate(now; "YYYY-MM-DD")}}.json
  • 2つ目のHTTPモジュール:https://api.fitbit.com/1.2/user/-/sleep/date/{{formatDate(now; "YYYY-MM-DD")}}.json

最後に作成したHTTPモジュールで右クリック、Run this module onlyを行いエラーが出ないことを絶対に確認してください。
モジュールの設定はエラーが起きやすい箇所なので、うまくいかない場合はGeminiやChatGPTなどのAIを活用してください。


  1. Notion - Search Objects
  2. HTTP - Make a request(Fitbitのアクティビティを取得)
  3. HTTP - Make a request(Fitbit睡眠ログを取得)
  4. HTTP - Make a request(GASを叩く)

最後のGASとの連携に入ります。
新しくHTTPモジュールを作成し、URLにGASのウェブアプリURLを貼り付けてください。

次にQuery parametersを設定します。Query parameterには、作成した3つのモジュールで取得したNotionとFitbitのデータが入ります。前述のRun this module onlyを行っていないとうまく取得できないので、気をつけてください。

Notionモジュールで取得した値は黒、HTTPモジュールで取得した値は青で表示されます。

全部で9つのパラメータを設定します。下記に則って設定してください。

  • city:{{num.properties_value.`都市名`[].plain_text}}
  • notion_key:{{num.properties_value.Notion_API_Key[].plain_text}}
  • weather_key:{{num.properties_value.Weather_API_Key[].plain_text}}
  • db_id:{{num.properties_value.DATABASE_ID[].plain_text}}
  • steps:{{num.data.summary.steps}}
  • calories:{{num.data.summary.caloriesOut}}
  • sleep_hours:{{round(num.data.sleep[].duration / 3600000 * 10) / 10}}
  • sleep_start:{{formatDate(num.data.sleep[].startTime; " HH:mm")}}
  • sleep_end:{{formatDate(num.data.sleep[].endTime; "HH:mm")}}

作成したGAS用のモジュールでRun this module onlyしてエラーが出なければOKです。

最後に、画面下部のトグルをクリックしてRun sceneario>Every dayTime>20:00に設定したら完了です。これで毎日20:00にNotionへライフログが蓄積されていきます。