🐥

FORMLOVAの営業メールを自動で見抜く仕組みを公開

に公開

者の体験は1ミリ秒も遅らせずに、CVR を正しく測れる状態を作る。

TL;DR

  1. フォーム送信後に非同期で LLM 分類 (Claude Haiku 4.5)。回答者の体験には一切影響しない。
  2. 判定は legitimate / sales / suspicious の3ラベル + 0-100 スコア。「迷ったら legitimate」を最優先。
  3. 分析・エクスポート・MCP・ワークフローすべてに sales 除外オプションが入り、CVR が正しく出る。

01 なぜ作ったか — 10件中8件が営業メールだった

マーケターの「目視で営業を弾く」作業を構造的に終わらせる。

FORMLOVA を作る前、クライアントのデジタルマーケティングと問い合わせフォーム運用を請け負っていた時期がありました。広告の費用対効果を計算するために、毎月手動で問い合わせ一覧を眺め、営業メールを除外して CVR を出し直していました。10件の問い合わせのうち8件が営業メール という月もありました。

⚠️ 業界の現状: 「目視で1件ずつ確認して手動で除外」が標準。それすらやらず、営業込みの数字でレポートしているマーケターも珍しくありません。丁寧にやれば工数が膨らみ、雑にやれば数字が嘘をつく。どちらも負け筋です。

従来の対処 何が起きるか
BOT対策 (CAPTCHA / Turnstile) 機械的スパムは止まるが、人間が手で送る営業メールは通る
受信メールの SPAM フィルタ フォーム経由の通知は「自社からの通知」扱いで素通り
マーケターによる目視除外 件数に比例して工数が増加。雑にやれば数字が崩れる
FORMLOVA 営業メール自動検知 送信時に非同期で分類。CVR を計測する側がボタン1つで除外できる

フォームサービスとして業界初。 AI で営業メールを分類してくれるフォームサービスは、調べた限り他に存在しません。BOT 対策は当然やった上で、その次の階層として「人間が書いた営業」を捌くのが FORMLOVA の選択です。


02 全体フロー — 送信体験はゼロ遅延

Next.js の after() API で非同期実行。タイムアウト 10 秒。失敗時はサイレント。

[同期 (回答者を待たせる経路)]

  フォーム回答 ──→ DB に保存 ──→ 通知メール送信 ──→ サンクスページ表示
   (submit)      (responses)     (即時応答)        (回答者の体験 OK)

       │ after() で fork

[非同期 (回答者を待たせない経路)]

  OpenRouter ──→ 3ラベル判定 ──→ responses 更新 ──→ ワークフロー
  (Haiku 4.5 /    (+ score        (spam_label /    (response.classified)
   temp 0)         0-100)          score)

失敗時: 分類が落ちても sales/legitimate ラベルを付けない (null のまま)。
       フォーム送信は絶対に壊さない。429/500系のみ1回リトライ。

📌 なぜ非同期か: 営業判定は「すぐ要る情報」ではない。CVR を眺めたとき / エクスポートするとき / ワークフローを発火するときに使う情報。送信時に同期で待たせる理由がない。


03 3ラベル × スコアリング — 迷ったら legitimate

LLM の判定を信用しきらない。最終判断は人間が握る。

                    ← 迷ったら legitimate

┌──────────────────────────┐ ┌──────────────┐ ┌──────────────┐
│      legitimate          │ │  suspicious  │ │    sales     │
│  正当な回答              │ │  グレーゾーン │ │  営業・売込  │
│                          │ │               │ │               │
│ • イベント参加申込       │ │ • 営業の匂い  │ │ • SEO提案     │
│ • 顧客からの問い合わせ   │ │ • 断定できない│ │ • 開発外注    │
│ • 採用エントリー         │ │ • 不自然な記述│ │ • 業務提携    │
│ • 判別不能 → ここ (既定) │ │               │ │               │
└──────────────────────────┘ └──────────────┘ └──────────────┘
0────────────────────────────────────────────────────────────100
                                      spam_score

設計思想: LLM の精度を信用しきっていません。正当な問い合わせを営業として弾いてしまうのは、絶対にやりたくない事故。だから、判別がつかなければ常に legitimate に倒します。フィルタは「AI による提案」であって、最終判断は人間が握ります。

そのために 0-100 のスコアも一緒に保存します。ダッシュボードでは「スコアの高い順」でグレーゾーンを集中的に目視レビューしたり、自分で spam_label_source = 'manual' として上書きしたりできます。手動修正したラベルは、後の自動再分類で上書きされません。

📌 プロンプト改善の歴史: 初版は3行のシンプルな判定基準でしたが、グレーゾーンの誤分類が想定より多く、3ステップ判定手順 + legitimate 正例6パターン + sales 5パターン + suspicious 厳格化 + few-shot 3例 + 「迷ったら legitimate」明文化、まで磨き込みました。


04 技術仕様と価格 — 1回答 0.03 円、全プラン無料

サーバー側で LLM を呼ぶ唯一の例外。コストはユーザーに転嫁しない。

項目 仕様
モデル anthropic/claude-haiku-4.5 (OpenRouter 経由)
パラメータ temperature: 0 / max_tokens: 256 (判定文字数は短い)
1回答あたりコスト $0.0002 ≒ 約 0.03 円
提供範囲 全プラン無料 (Free プランでも使える)
実行タイミング Next.js after() API で回答送信後に非同期実行
タイムアウト 10 秒。429/500系のみ1回だけ指数バックオフでリトライ
プロンプトインジェクション対策 system メッセージと user メッセージを分離。回答テキスト内の指示は分類基準を上書きできない
プライバシー 回答テキスト最大 2000 文字。メールアドレスは ドメイン部分のみ マスクして送信 (***@example.com)
失敗時の挙動 サイレントに null を返し、フォーム送信は壊さない
有料イベント (Stripe Connect) スキップ (有料申込に営業メールが混ざる可能性が低いため)

⚠️ FORMLOVA のコスト思想: 通常 LLM コストはユーザー側 (MCP クライアント) が負担する設計です。営業検知はその唯一の例外。それでも全プラン無料で提供できるのは、Haiku 4.5 のレートカードがそこまで安くなったから。「お客さんから見たら、それが裏で AI かどうかは関係ない」がスタンスです。

※ 出典: lib/spam-classification/openrouter.ts, lib/spam-classification/engine.ts, docs/SPEC.md 営業メール自動検知セクション (取得日 2026-05-21)


05 公開時のサーバー側ゲート — 「設定し忘れ」をゼロに

クライアント側 LLM の判断に依存しない。サーバーがブロックする。

クライアント LLM ──→ ┌────────────────────────────────────────┐ ──→ 未設定なら ──→ missing_requirements
publish_form          │       サーバー側チェック                │                        公開ブロック
呼び出し              │  • 重複防止設定                         │
                      │  • プライバシーポリシー                  │
                      │  • 営業メール検知: 有効 / 不要 ← 必須化  │
                      │  • サンクスページ確認 / 自動返信確認    │
                      └────────────────────────────────────────┘

                              全要件 OK ↓
                            ┌────────────────────────┐
                            │ confirmation_token 発行 │
                            │      5 分 TTL          │
                            └────────────────────────┘

                            ┌────────────────────────┐
                            │    フォーム公開 OK     │
                            └────────────────────────┘

テキスト入力フィールド (text / textarea / email / url / phone) を持つフォームを公開しようとすると、publish_form ツールがサーバー側のチェックリストに「営業メール検知: 有効 / 不要」を必須項目として組み込みます。回答者からの自由記述があり得るフォームほど、営業が混ざる可能性が高いからです。

これは「クライアント側 LLM が忘れたかどうか」に依存しません。サーバーが missing_requirements を返し、選択するまで confirmation_token を発行しない設計です。重複防止やプライバシーポリシーと同じレベルのゲート。

📌 使い方は1行: 「営業メールを除いて分析して」「営業メール検知を ON にして」「この回答を営業に分類して」。チャットでそのまま指示できます。get_responsesexport_responses には exclude_sales パラメータが入っていて、MCP 横断のワークフローからも除外できます。


06 拡張性 — インテント分類への足場

スパム判定は入口。正当な回答の中の「種類」を分けられれば、その先のワークフローが豊かになる。

外部スパムを判定できるということは、正当な回答の中でも種類を分類できる ということです。「料金問い合わせ」「採用」「導入相談」「クレーム」「単なるアンケート」を自動でラベルしたら、FORMLOVA の MCP と他の SaaS の MCP を組み合わせて、ラベルごとに別ワークフローへ流せます。

  • 料金問い合わせ → HubSpot に Hot リードとして登録、Slack に通知
  • 採用エントリー → ATS に転送、自動返信で次のステップ案内
  • 営業 → 何もしない (もしくは別フォルダに飛ばす)
  • クレーム → カスタマーサポート専用 Slack に escalate

フォームサービス側でやることで、最初からリストとして取れる。受信側の SPAM フィルタや CRM の手動タグ付けに比べて、圧倒的に時間とコストが下がります。これは「フォームを集める器」ではなく「フォーム回答を最初にハンドリングする層」としての FORMLOVA の立ち位置から自然に出てくる発想です。


結論

  1. CVR が正しく出る。 営業を除いた数字でレポートできるので、広告の費用対効果が嘘をつかない。
  2. マーケターの時間が戻る。 目視で1件ずつ確認していた工数が消える。グレーゾーンだけ集中レビューすれば良い。
  3. AI は提案、人間が判断。 迷ったら legitimate に倒す設計と、手動修正の上書き保護で、正当な回答を弾く事故を構造的に防ぐ。

FORMLOVA は MCP クライアント(Claude/ChatGPT/Gemini 等)から接続してフォームを操作できるサービスです。営業メール分類は全プラン無料で使えるようになりました。実装の参考になれば幸いです。

Discussion