Google Form × LINE Messaging API × GAS で、お問い合わせをLINEに自動通知する
概要
個人開発で運用しているiOSアプリ「Tateca」のユーザーからのお問い合わせ対応のオペレーションを強化する。
現在、ユーザーからのお問い合わせはGoogleフォームを通じてスプレッドシートに記録されているが、手動でシートを確認しなければならず、見落とすと返信が遅れることがある。
そこで、お問い合わせが届いたタイミングでLINEに自動通知する仕組みを構築する。
GASで完結するので、インフラ構築不要・無料枠(200通/月)で運用できます。
使用技術
- LINE Messaging API
- Google App Script(以下GAS)
LINE Notifyが2025年3月31日に提供終了とのことなので、今回はLINE Messaging APIを使用する
前提
Google Form と Google Spreadsheet の連携が済んでいること。
完成後のワークフロー
ユーザーがフォームから送信
→ スプレッドシートに追加
→ onFormSubmit トリガーでWebhook発火
→ LINEにメッセージを送信
実装手順
ステップ1. LINE公式アカウントの準備
こちらの公式ドキュメントに従ってLINE公式アカウントの作成とMessaging APIの有効化を行う
料金プランに記載がありますが、200通までは無料でメッセージが送れるようです。
ステップ2. チャネルアクセストークンを取得
取得したトークンはGAS側でのメッセージ送信に使用する。
今回は長期のチャネルアクセストークンを作成。
ステップ3. userIdを取得するWebhookを実装
LINEメッセージのPush送信には 送信先のuserIdが必要。お問い合わせがあるたびにこのuserIdへメッセージを送信します。
3-1. GASにプログラムを追加
既存のお問い合わせ対応用のスプレッドシートを開き、「拡張機能 → Apps Script」からGASエディタを開いて以下を貼り付けます。
/** 自分のLINE userIdをline_idsに保存するだけのWebhook */
function doPost(e) {
if (!e || !e.postData || !e.postData.contents) {
return ContentService.createTextOutput('no body');
}
const body = e.postData.contents;
const json = JSON.parse(body);
const events = json.events || [];
if (events.length === 0) {
return ContentService.createTextOutput('no events');
}
// Spreadsheet取得
const ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName('line_ids');
if (!sheet) {
sheet = ss.insertSheet('line_ids');
sheet.getRange(1, 1, 1, 2).setValues([['userId', 'registered_at']]);
}
const now = new Date();
const existingIds = sheet
.getRange(2, 1, Math.max(sheet.getLastRow() - 1, 0), 1)
.getValues()
.flat()
.filter(String);
// イベントからuserIdを抽出
events.forEach(ev => {
const id = ev?.source?.userId;
if (id && !existingIds.includes(id)) {
sheet.appendRow([id, now]);
}
});
return ContentService.createTextOutput('ok');
}
3-2. GASをデプロイ
| 設定項目 | 値 | Note |
|---|---|---|
| 次のユーザーとして実行 | 自分(=スクリプトの所有者) | スプレッドシートに書き込むため、自分を選択 |
| アクセスできるユーザー | 全員(匿名ユーザーを含む) | LINEサーバーはGoogleアカウントを持たないため必要 |
3-3. Webhook URLをMessaging APIに登録
LINE Official Account Managerの設定 -> Messaging API -> Webhook URLにGASのデプロイURLを設定。
これで、Bot宛てにメッセージを送るとGASが発火します。
3-4. userIdを取得
Botにメッセージを送ると、line_idsシートに userIdが保存されます。公式アカウントに対して適当なメッセージを送って下さい。
ステップ4. 問い合わせフォームの送信をLINEに通知
取得した userId を使って、問い合わせが届いたときに自分のLINEへ自動通知します。
4-1. GASのコードを上書き
上記のコードを以下の内容に置き換え、再デプロイします。
/** Push送信(userIdを環境変数から取得) */
function pushMessage_(text) {
const props = PropertiesService.getScriptProperties();
const ACCESS_TOKEN = props.getProperty('CHANNEL_ACCESS_TOKEN');
const TO_ID = props.getProperty('LINE_USER_ID');
if (!ACCESS_TOKEN || !TO_ID) throw new Error('必要なプロパティが設定されていません。');
const url = 'https://api.line.me/v2/bot/message/push';
const payload = { to: TO_ID, messages: [{ type: 'text', text }] };
const params = {
method: 'post',
contentType: 'application/json',
headers: { Authorization: 'Bearer ' + ACCESS_TOKEN },
payload: JSON.stringify(payload),
};
const res = UrlFetchApp.fetch(url, params);
if (res.getResponseCode() >= 300) {
throw new Error(`LINE push error ${res.getResponseCode()}: ${res.getContentText()}`);
}
}
function onFormSubmit(e) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheetUrl = ss.getUrl();
const named = e && e.namedValues ? e.namedValues : {};
const lines = Object.entries(named).map(([k, v]) => `・${k}: ${Array.isArray(v) ? v.join(', ') : v}`);
const text =
`【新着フォーム回答】\n` +
`受信: ${Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd HH:mm')}\n` +
`${lines.join('\n')}\n\n` +
`開く: ${sheetUrl}`;
pushMessage_(text);
}
4-2. スクリプトプロパティを設定
- CHANNEL_ACCESS_TOKEN:長期チャネルアクセストークン
- LINE_USER_ID:自分のLINE userId(前ステップで取得したもの)
4-3. トリガーを追加
GASコンソールの「トリガー」から以下を設定:
- 実行する関数を選択:onFormSubmit
- 実行するデプロイを選択:Head
- イベントのソースを選択:スプレッドシートから
- イベントの種類を選択:フォーム送信時
ステップ5. 完成
これでフォーム送信のたびにLINEに通知が届くようになりました 🎉
こんな感じ:

Discussion