フォーム計測の仕組みをつくる3(Laravel)

2025.11.25 09:00
2025.10.22 11:01
フォーム計測の仕組みをつくる3(Laravel)

前回は Contact Form 7 で、公式イベントを使ってフォーム送信を計測しました。
WordPressだとあんなに簡単だったのに、Laravelで自作フォームを作ると当然そんなイベントはありません。

というわけで今回は、Laravelフォームで同じように form_start / form_submit / form_error を計測する までをやってみた話です。

そもそも何を取りたいのか?

やりたいのは前回と同じく、3ステップの可視化です。

  1. 入力が始まった(form_start)
  2. 送信が完了した(form_submit)
  3. エラーが発生した(form_error)

WordPressみたいな便利なイベントがないぶん、
GTMの「トリガー」を工夫して取る形にしました。

実装1:入力開始(form_start)

まずは「誰かが入力を始めたか」を取る部分。
GTMで「要素のフォーカス」トリガーを使いました。

  • トリガータイプ:要素のフォーカス
  • CSSセレクタform.contact-form input:first-child
  • イベント名form_start

これで、「ページを見ただけ」ではなく「実際に入力し始めた人」を計測できます。
単純だけど、ここがあるだけで分析の粒度が一気に上がります。

実装2:送信完了(form_submit)

ここがポイント。
Laravelでは、フォーム送信後にページが遷移するパターンと、
Ajaxで完結するパターンの2つがあります。

パターンA:サンクスページ型

フォーム送信後に /thanks にリダイレクトしている場合、
GTMの「ページビュー」トリガーでURLを指定します。

  • トリガータイプ:ページビュー
  • 条件Page URL/thanks を含む
  • イベント名form_submit

これが一番簡単で安定します。
実際のフォーム構成がシンプルなら、これで十分です。

パターンB:Ajax送信型

最近は非同期送信(Ajax)も増えてきたので、
その場合は「成功メッセージの出現」を検知する必要があります。

私は MutationObserver を使って、
.contact-complete という要素が出たタイミングで form_submit を発火させました。

<script>
document.addEventListener('DOMContentLoaded', () => {
  const observer = new MutationObserver(() => {
    if (document.querySelector('.contact-complete')) {
      dataLayer.push({'event': 'form_submit'});
    }
  });
  observer.observe(document.body, { childList: true, subtree: true });
});
</script>

これでAjaxでも確実に送信完了を検知できます。

実装3:エラー発生(form_error)

バリデーションでエラーになったときも、
.error-message.invalid-feedback が出たタイミングを拾うようにしました。

<script>
document.addEventListener('DOMContentLoaded', () => {
  const observer = new MutationObserver(() => {
    if (document.querySelector('.error-message')) {
      dataLayer.push({'event': 'form_error'});
    }
  });
  observer.observe(document.body, { childList: true, subtree: true });
});
</script>

GTM側で form_error を拾えるようにしておけばOKです。

GA4での確認

設定が完了したら、
GA4のイベント一覧に form_start, form_submit, form_error が並ぶようになります。
form_submit をコンバージョンに指定し、
「探索 → ファネル探索」で流れを見てみると

ステップ到達率
form_start120100%
form_submit4033%
form_error108%

といった具合に、入力開始→完了までの歩留まりが一目で見えます。

やってみて気づいたこと

1. Ajax型は意外とトリガーが難しい

ページ遷移がないぶん、どの瞬間を「送信完了」とみなすかが難しかったです。
最初はボタンクリックで取っていたけど、エラー時も反応してしまうのでやめました。
成功メッセージを監視するのが結局いちばん確実でした。

2. バリデーションエラーの多さに驚く

form_error を入れて初めて、
「半角数字じゃない」「メールが必須で抜けてる」など、
細かいエラーで止まっている人が多いことに気づきました。
地味ですが、UI改善の方向性が数字で見えるのはすごく助かります。

3. Laravelでも結局やることは同じ

フォームの種類が違っても、やることは結局「トリガーで状態を検知してGA4に送る」。
Contact Form 7 のような便利イベントがない分、
どの瞬間をどう拾うかを意識するようになって理解が深まりました。

まとめ

Laravelのフォームでも、
GTMを使えば form_start, form_submit, form_error をしっかり取ることができます。

サンクスページ型ならURL、
Ajax型なら成功メッセージのDOM出現でトリガーを切るのがコツ。

そして、数字を見て気づくのは
「フォームを送らない人の行動こそ改善のヒントになる」ことでした。

結局どの環境でも共通して大事なのは、
入力開始 → 送信完了 → エラー」の3つをセットで取ること。

これだけで、コンバージョンの「質」がまるで違って見えるようになりました。

今回は以上です!