お問い合わせフォームに届く営業メール、AIで自動振り分けしてみた
はじめに
毎月数社クライアントのWEBサイト運用を担当しています。 その中に、アクセス解析と問い合わせ分析の月次レポートを作成している製造業のクライアントがいます。
WEBサイトからの問い合わせデータはGAS(Google Apps Script)経由でスプレッドシートに自動記録し、そこから集計してレポートに反映する流れです。
しかしながら、この問い合わせには皆様の会社も同様かと思いますが、営業メールがまあまあ届きますよね…
担当のクライアントは月に約100〜150件届くお問い合わせメールのうち、約半分以上がSEO対策の提案、広告運用の売り込み、人材紹介、システム開発の営業…。これが「お問い合わせ件数」としてカウントされてしまうので、レポートの数字が実際とは異なる結果となってしまっていました。
レポートの信頼性を上げるには、営業メールにフラグを立てて集計から除外する必要があります。毎月手作業で1件ずつ「これは営業、これは本物」と仕分けていましたが、ただ、手動で仕分けるのは見落としもあるかもしれないし、手間がかかります。 そこで昨今の賢いAIに文脈を読み取らせて自動判定できないか?と常々考えていました。
最初の試み:Gemini API × GAS
データがスプレッドシートにあるなら、GASからAI APIを呼んで、シートにある備考欄のテキストから営業かどうかを判定すればいいのでは?という発想で、最初に試したのはGoogle Gemini APIでした。無料枠もあり、GASとの相性も良さそうかなと。
やってみてわかった問題
① 無料枠が思ったより使えない…
当時のGemini APIの無料枠では、実質的に1日あたり数十回程度で制限にかかる状況でした。月100件程度なら十分…のはずが、GAS側での自動実行が頻繁に失敗。気づいた時に手動で再実行すると、あっという間に1日の上限に到達してしまい…「無料で使える」はずが、実際は安定して回りませんでした。
② レスポンスが遅く不安定
GASからの呼び出しで何故かレスポンスが返ってこないことがあり、タイムアウトで失敗するケースも頻発。PHP側から呼んでも同様にGASの実行制限や外部API呼び出しの特性もあり、当時の構成では安定運用が困難な状況に陥りました。
結局、コストと安定性の両面でGeminiでの運用は断念しました。
方針転換:フォーム送信にフックする
Geminiでの失敗を経て、2つの方針転換を試みました。
① APIをOpenAIに変更
安定性とコストのバランスでOpenAI APIに切り替えました。
- レスポンスが安定して速い(PHPから呼んでもメール送信に影響しないレベル)
- Structured OutputsでJSON形式の判定結果を確実に返せる
gpt-4.1-miniなら月100件程度でも十分許容できるコスト- 1Mトークン: input=0.4ドル, output=1.6ドル (2026/02時点)
※ 1ヶ月運用で247回の呼び出しで約7.5円($0.05)程度だった(2026年2月時点、1ドル≒150円換算)
② 判定タイミングをフォーム送信時に変更!
GASでスプレッドシート記録後に判定するのではなく、PHPのフォーム送信処理にフックして、メール送信前にリアルタイムで判定する方式に変えました。
なるべく実運用に影響が出ないようにと考え尻込みしていたんですが、クライアントとMTGで話し合い実施することになりました。
フォーム送信時に判定できるなら、判定結果を使ってメールの送信先も切り替えられる利点も。
当初の目的は「レポート集計のための営業フラグ付け」でしたが、フォーム送信にフックすることでメールの振り分けまでできるようになりました。
実現した仕組み
最終的な仕組みはこうなりました。
WEBサイトからフォーム送信
↓
PHPで受け取る
↓
AI判定
↓
判定結果に応じてメール送信先を切り替え
- 営業確定 → sales@ に送信(件名に【AI営業判定】)
- 判断つかない → info@ に送信(件名に【要確認】)
- 通常問い合わせ → info@ に送信(変更なし)
↓
GAS経由でスプレッドシートにログ記録(判定結果込み)
クライアントにとっては、営業メールがsales@に自動で飛ぶようになったことで、info@では真のお問い合わせだけに集中できるようになりました。
自分にとっては、スプレッドシートに判定結果が自動記録されるので、レポート集計で営業メールをフィルタリングするだけでよくなりました。
判定ロジック:安全側に倒す設計
AIの判定は完璧ではありません。特に怖いのは「本物のお問い合わせを営業と誤判定して、担当者の目に触れない」ケース。
そこで、下記のような設計にしました。
3つのラベル + 確信度の二重チェック
AIの返すラベルは3種類:
| ラベル | 意味 | メール送信先 |
|---|---|---|
sales | 営業メール | sales@ |
not_sales | 通常の問い合わせ | info@ |
unsure | 判断つかない | info@ |
さらに、salesと判定されても確信度が閾値未満なら念のためinfo@に送るように。
- 営業確定 =
salesかつ 確信度 ≥ 0.90 の場合のみ - それ以外はすべて
info@
迷ったら通常の問い合わせとして扱い、AI APIが失敗した場合もinfo@に送信することで、お問い合わせが消えることは絶対にない設計にしました。
AIに送る情報と個人情報の配慮
AIに送る情報は最小限にしてます。
Company: 株式会社○○
Inquiry type: 見積もり
Product: ○○
Email domain: example.co.jp
Message:
(お問い合わせ本文)
名前・電話番号・メールアドレス本体は送らず、メールドメインだけ送ることで「フリーメールからの営業」といった判断材料にしつつ、個人情報の流出リスクを抑えています。
また、クライアントの取扱製品リストを短文にまとめた「取扱範囲ブロック」を判定のプロンプトに含めています。これによってAIが「この問い合わせは取扱範囲内か?範囲外の営業か?」を正しく判断できるようにしています。
さらに今後は何回も送信してくる会社名をリスト化して、AI営業判定前に除外するようにしてAPIコストを削減することも検討しています。 これは自動化しても良いのですが、もしいきなりリスト化してしまうと、その会社の他の担当者が営業ではなく本来の問い合わせになる可能性も否定できないため、クライアントとのMTGにより確定した会社のみをリスト化するようにする予定です。
ログと改善サイクル
判定して終わりではなく、精度を改善していく仕組みも用意しました。
GAS経由でスプレッドシートに以下を自動記録しています:
- お問い合わせリスト:営業判定カラムに「営業」「問い合わせ」「要確認」を自動入力(← レポート集計で活用)
- 営業メールリスト:
sales判定のものだけを一覧化 - 学習データ:AI判定+本文の抜粋を記録し、後から人が「最終ラベル」を入れて精度検証に使う
- AI利用ログ:モデル名、トークン量などを1判定1行で記録
やってみて感じたこと
Geminiでの失敗は無駄じゃなかった
Geminiで「GAS上での後処理」を試したことで、「フォーム送信時のリアルタイム判定」というより良いアプローチにたどり着けました。
「完璧」を目指さない設計が大事
AI判定の精度は100%にはならないという前提で「間違えた時に被害が最小限になる設計」が重要だと感じました。
クライアントと自分、両方の課題が解決した
もともとは「レポート集計の手間を減らし精度を上げたい」という自分側の課題でしたが、結果的にクライアントも「営業メールに埋もれて真の問い合わせを見落とすリスクが減った」という価値を得られました。
判定データの活用の広がり
この仕組みで蓄積されたデータは、営業メールの振り分けだけでなく、別の用途にも使い始めています。
GASでスプレッドシートに記録している問い合わせの備考欄や、見積もりフォームの依頼内容をAIで分析し、自分でも内容を精査した上で毎月のアクセス解析レポートに活かすようになりました。「どんな製品に需要があるのか」「どんな用途で問い合わせが来ているのか」といったテキストデータから見える傾向は、アクセス数やCV数だけではわからない情報を補ってくれます。
まだレポートに反映し始めたところなので、今後どういった傾向が見えてくるか楽しみです。
もう少しAIを使ったアクセス解析レポートの知見や自動化が進んだら、また記事にしようと思います。