問い合わせや申し込みを Typeform で受けていると、回答に気づくまでの時間がそのまま返事の遅れになります。かといって、回答をそのまま Slack へ流すと、設問の ID が並んだ読めない文になりがちです。
この記事では、Typeform の回答を「設問: 回答」の形に整えて Slack のチャンネルへ送る手順を説明します。
結論
Samurai App のワークフローに「サービス連携」で Typeform をつなぎ、出来事「New Form Response」(TYPEFORM_NEW_RESPONSE)で起動します。Typeform 側から届く方式なので、確認の間隔を待たずに動きます。
ワークフローは「コード」と「通知先へ送る」の 2 ステップです。どちらもモデルを呼びません。
できること・できないこと
- 起動するのは、回答が送信されたときだけです。 途中までの回答では動きません
- フォームは登録 1 件につき 1 つです。 登録時にフォームの ID を指定します。有効にできるサービス連携は 20 個までです
- 費用は 1 件受けるごとに約 0.5 円かかります。 実行が何も走らなかったときも同じです
- Slack に表示されるのは「本文」だけです。 「一緒に送る値(任意)」は Slack に表示されません
- 回答を順番で読むことはできません。 Typeform の公式資料には、
answersの並びはfieldsと同じとは限らず、未回答の設問はanswersに入らないと書かれています。answers.0を「1 問目」として本文に書くと、別の設問の回答が入ったり、通知が失敗したりします
届く回答はおおよそ次の形です。
| 項目 | 中身 |
|---|---|
form_response.definition.title |
フォームの名前 |
form_response.definition.fields |
設問の一覧。id と title を持つ |
form_response.answers |
回答の一覧。field.id で設問と結び付ける |
form_response.submitted_at |
送信日時。UTC なので日本時間より 9 時間前の表記になる |
form_response.hidden |
隠しフィールド。フォームで使っているときだけ入る |
回答の値が入る項目名は、回答の type で変わります。短文は text、メールアドレスは email、単一選択は choice.label、複数選択は choices.labels です。
用意するもの
- Typeform のアカウントと、通知したいフォーム
- 投稿先チャンネルの Slack の Incoming Webhook の URL
- Samurai App のマネージャー以上の権限(ワークフローにサービス連携を付けるために必要です)
手順
完成すると、次のようなワークフローになります。

1. Slack の Webhook の URL を作る
Slack のアプリ設定で「Incoming Webhooks」を有効にし、「Add New Webhook to Workspace」からチャンネルを選んで「Authorize」を押します。URL は選んだチャンネル専用です。
2. 通知先を登録する

Samurai App の「設定」→「通知」の「通知先」に、名前と URL を登録します。「テスト送信」で Slack に届くことを確認します。登録した URL は後から表示されないので、控えが必要なら先に保管します。
3. Typeform を接続する
「コネクタ」画面の「コネクタ」タブで Typeform の「追加」を押し、「標準連携アプリで追加」を選んでサインインします。
4. フォームの ID を控える
フォームの公開 URL に含まれる英数字の文字列が ID です。
5. ワークフローを作る
「ワークフロー」の「作成」から「新規作成」を選びます。ステップを選んでいない状態の「設定」にある「ワークフローの入力」で「入力の項目を追加」を押し、名前を event、種類を「項目の組」にします。
次に「コード」のステップを置きます。「渡す値」に 2 行足します。
answers:input.event.form_response.answersfields:input.event.form_response.definition.fields
「コード」の欄には次を書きます。回答の type と同じ名前の項目から値を取り、設問の名前と組にしています。
const lines = inputs.answers.map((answer) => {
const field = inputs.fields.find((f) => f.id === answer.field.id);
const value = answer[answer.type];
const text = value?.labels?.join("、") ?? value?.label ?? value?.other ?? value?.url ?? value?.text ?? value;
return (field?.title ?? "(設問名なし)") + ": " + (typeof text === "object" ? JSON.stringify(text) : text);
});
return lines.join("\n");
続けて「通知先へ送る」を置き、手順 2 の通知先を選びます。「本文」の 1 行目に {{input.event.form_response.definition.title}} に回答がありました と書き、2 行目に「/」からコードのステップの値を入れます。
6. 保存して公開する
「保存」を押し、「バージョン」タブで「バージョン N を公開」を押します。自動実行で動くのは公開したバージョンだけです。
7. サービス連携を付ける
「トリガー」タブの「サービス連携を追加」を押します。「どのサービスを監視するか」で Typeform の接続を選び、「どうなったら動かすか」で「New Form Response」を選びます。「絞り込み」の form_id に手順 4 の ID を入れて登録します。
8. 回答して確認する
フォームに回答を 1 件送ります。Slack に届いたら、「実行」タブの「最近の実行」で「出来事で起動」の行を開き、実際に届いた入力を確認します。隠しフィールドなどを本文に足すときは、ここに出ている項目名を写します。
動かないとき
実行が失敗し、「$ref '…' の値がありません」と出る
本文に書いた項目が、届いた回答に入っていません。任意の設問や隠しフィールドを {{input.event…}} で直接書くと、未回答の回で通知ごと失敗します。空欄で送られるわけではありません。回答は手順 5 のコードから読み、毎回必ず入る項目だけを本文に直接書きます。
何も起動しない
「最近の実行」に行が増えていないときは、公開の漏れと form_id の間違いを確認します。公開していないバージョンでは起動しません。
Typeform 側で Webhook が無効になった
Typeform は、宛先が 404 か 410 を返すと再試行せずに Webhook を無効にします。失敗が続いた場合も無効になり、所有者へ通知が届きます。その通知を受けたら、Typeform のフォームの Webhook の状態を確認してください。
Slack に届かない
「通知先へ送る」の実行の記録を開きます。URL が違うと、通知先の行に「宛先の URL が見つかりません。URL を確かめてください(404)」と出ます。「編集」から新しい URL を入れ直します。
よくある質問
特定の回答のときだけ通知できますか
できます。「通知先へ送る」の前に「条件分岐」を置きます。条件には毎回必ず入る項目を使ってください。単一選択の設問で分けるときは、先にコードで値を取り出して、その結果を条件にします。
通知の直後に回答の画面を開いても見つからないのはなぜですか
Typeform の公式資料によると、Webhook は回答がデータベースに入る数秒前に届くことがあります。少し待ってから開き直してください。
複数のフォームをまとめて通知できますか
同じワークフローに、フォームごとのサービス連携を追加します。ワークフローの中身は共通で使えます。