BLUEBETA

Google スプレッドシート連携ガイド

Blue で作ったアプリから Google スプレッドシートに保存・メール送信する手順とサンプルコード

1. 概要

Blue で作るアプリは、Google Apps Script(GAS)の WebApp 機能を使って Google スプレッドシートや Gmail と連携できます。Blue は中継せず、アプリのフロントエンドから GAS の URL に直接送信します。新しいアカウント開設や追加課金は不要で、お持ちの Google アカウントだけで始められます。

主なユースケース: 問い合わせフォーム → スプシ保存/申し込みフォーム → スプシ保存 + 確認メール/スプシのデータをアプリで一覧表示/アンケート集計。

2. WebApp の作り方(基本手順)

Step 1. スプレッドシートを用意する

  1. Google Drive でスプレッドシートを新規作成
  2. 1 行目にカラム名を入れる(例: タイムスタンプ / 名前 / メールアドレス / お問い合わせ内容
  3. 共有設定は 「制限付き(自分のみ)」のまま にする(変更不要)

Step 2. GAS スクリプトを作成する

  1. スプシのメニュー「拡張機能」→「Apps Script」を開く
  2. エディタの Code.gs に、下の「3. サンプルコード」から該当パターンを貼り付ける
  3. 保存(Ctrl / Cmd + S)

Step 3. WebApp としてデプロイする

  1. 右上の「デプロイ」→「新しいデプロイ」
  2. 歯車アイコン →「ウェブアプリ」を選択
  3. 設定 —— 次のユーザーとして実行:「自分」/アクセスできるユーザー:「全員」(社外公開フォーム)。社内限定なら「(あなたのドメイン) 内の全員」
  4. 「デプロイ」→ 初回は権限承認(「詳細」→「(プロジェクト名) に移動」→「許可」。自分のスクリプトを自分で認可する操作で安全です)
  5. 表示された WebApp URLhttps://script.google.com/macros/s/AKfycbz.../exec)をコピーし、Blue で作ったアプリのコードに貼る

Step 4. 動作確認

ブラウザで WebApp URL を直接開き、エラーが出ずにレスポンス(doGet を定義していれば JSON)が返れば OK です。

3. サンプルコード(GAS 側)

パターン 1: フォーム送信 → スプシに保存(最頻出)

function doPost(e) {
  try {
    const data = JSON.parse(e.postData.contents);
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
    sheet.appendRow([new Date(), data.name || "", data.email || "", data.message || ""]);
    return ContentService
      .createTextOutput(JSON.stringify({ ok: true }))
      .setMimeType(ContentService.MimeType.JSON);
  } catch (err) {
    return ContentService
      .createTextOutput(JSON.stringify({ ok: false, error: String(err) }))
      .setMimeType(ContentService.MimeType.JSON);
  }
}

パターン 2: スプシのデータを読み取る

function doGet(e) {
  try {
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
    const rows = sheet.getDataRange().getValues();
    const headers = rows[0];
    const items = rows.slice(1).map(row => {
      const obj = {};
      headers.forEach((h, i) => { obj[h] = row[i]; });
      return obj;
    });
    return ContentService
      .createTextOutput(JSON.stringify({ ok: true, items: items }))
      .setMimeType(ContentService.MimeType.JSON);
  } catch (err) {
    return ContentService
      .createTextOutput(JSON.stringify({ ok: false, error: String(err) }))
      .setMimeType(ContentService.MimeType.JSON);
  }
}

パターン 3: スプシ保存 + 確認メール送信

function doPost(e) {
  try {
    const data = JSON.parse(e.postData.contents);
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
    sheet.appendRow([new Date(), data.name || "", data.email || "", data.message || ""]);
    if (data.email) {
      const ownerEmail = Session.getActiveUser().getEmail();
      MailApp.sendEmail({ to: ownerEmail, subject: "新しいお問い合わせ", body: `名前: ${data.name}\nメール: ${data.email}\n\n${data.message}` });
      MailApp.sendEmail({ to: data.email, subject: "お問い合わせを受け付けました", body: `${data.name} 様\n\nお問い合わせありがとうございます。改めてご連絡いたします。` });
    }
    return ContentService.createTextOutput(JSON.stringify({ ok: true })).setMimeType(ContentService.MimeType.JSON);
  } catch (err) {
    return ContentService.createTextOutput(JSON.stringify({ ok: false, error: String(err) })).setMimeType(ContentService.MimeType.JSON);
  }
}

メール送信のクォータ: 個人 Gmail は 1 日 100 通、Workspace は 1 日 1500 通(2026 年時点)。

パターン 4: Workspace ドメイン制限版

コードはパターン 1〜3 と同じで構いません。違いはデプロイ時に「アクセスできるユーザー」を 「(あなたのドメイン) 内の全員」 にする点だけです。社外には見せず、社内では Google ログインの手間なく使いたい場合の中間解で、シートの ACL も尊重されます。

4. アプリ側のコード(Blue 上で動くアプリ)

CORS 回避のため、POST は Content-Type: text/plain で送ります(application/json だとブラウザが preflight を投げて失敗します)。

const GAS_URL = "https://script.google.com/macros/s/AKfycbz.../exec";

document.getElementById("contact-form").addEventListener("submit", async (e) => {
  e.preventDefault();
  const formData = {
    name: document.getElementById("name").value,
    email: document.getElementById("email").value,
    message: document.getElementById("message").value,
  };
  try {
    const res = await fetch(GAS_URL, {
      method: "POST",
      headers: { "Content-Type": "text/plain;charset=utf-8" },
      body: JSON.stringify(formData),
    });
    const data = await res.json();
    alert(data.ok ? "送信しました" : "送信に失敗しました: " + data.error);
  } catch (err) {
    alert("通信エラー: " + err.message);
  }
});

静的アプリ(HTML + JS)では URL をコード内に直書きします。バックエンド付きアプリ(Python / Node.js / PHP)では Blue の 設定 の「汎用 Secrets」に保存した名前を環境変数として参照します。

5. データの機微度と推奨モード

データの種類推奨モード
連絡先・問い合わせ・予約URL-as-token(既定)
社内に閉じた業務データURL-as-token、または Workspace ドメイン制限
社外秘の業務データWorkspace ドメイン制限
第三者のセンシティブ個人情報(健康・財務)OAuth + Sheets API 直接
決済情報・パスワードGAS 連携は使わない(Stripe 等の専用 SaaS)
GAS の「全員」公開 URL は、Google の設計上「半公開トークン」として扱われます。ブラウザ履歴・拡張機能・Referer・スクリーンショット等で漏れうるため、漏洩しても許容できる機微度のデータに限定し、URL を Git や SNS・公開ドキュメントに貼らないでください。機微度が高い場合はドメイン制限版または OAuth 経路に切り替えます。

6. 制約事項(GAS 側のクォータ)

項目個人 GmailWorkspace
スクリプト実行時間 / 日90 分6 時間
メール送信数 / 日100 通1500 通
URL Fetch 呼び出し / 日20,000 回100,000 回
Cold start最初の呼び出し時に数秒

これらの制約はユーザー側で管理します。スケール時にボトルネックになる場合は Cloud Run / Cloudflare Workers 等への移行を検討してください。

7. エンドユーザーへの通知

運営者側で個人情報保護法 / GDPR 上の通知義務が生じることが多いため、フォーム下部に以下のような通知を入れることを推奨します。

<p class="privacy-notice">
  このフォームに入力された情報は Google サービスに送信され、本ページの運営者が管理します。
  Google のデータ取り扱いは Google プライバシーポリシーに従います。
</p>
サポートに戻る AI Build を開く 用語集