0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WordPress + WPForms + Site Kitで、BtoB問い合わせを「CTA→フォーム開始→送信完了」まで計測する

0
Posted at

検証日: 2026-08-17
構成: WordPress / SWELL / WPForms Lite / Site Kit by Google / GA4

コーポレートサイトの問い合わせ改善では、フォーム送信数だけ見ても、どこで離脱しているか分かりません。

今回、自社サイトで次の導線を計測できるようにしました。

サービスページ閲覧
  └─ CTAクリック
       └─ フォーム開始
            └─ 送信完了

この記事では、WPFormsとSite Kitの既存計測を残しながら、CTAクリック、フォーム開始、相談種別付きの送信完了イベントを追加する方法を紹介します。

最初に決めたイベント設計

イベント 発火条件 主なパラメータ
cta_click 問い合わせページへのリンクをクリック CTA文言、相談種別、遷移元ページ
lead_form_start 対象フォームを初めて操作 フォームID、相談種別、ページ
lead_form_completed WPFormsのAjax送信が成功 フォームID、相談種別、ページ

Site Kitのプラグインコンバージョントラッキングが有効な環境では、WPFormsの送信成功時に submit_lead_form が送信されます。今回はこれを総問い合わせ件数の基準として残し、lead_form_completed は相談種別別の分析用に追加しました。

同じ「完了」を二つ作るのは一見冗長ですが、役割を分けると安全です。

  • submit_lead_form: Site Kitが管理する総完了数
  • lead_form_completed: 自社の相談種別を持たせた分析用イベント

個人情報はGA4へ送らない

GA4のイベントパラメータには、次の情報を含めません。

  • 氏名
  • 会社名
  • メールアドレス
  • 問い合わせ本文
  • 役職・立場
  • 同意チェックの内容

送るのは、あらかじめ用意した相談種別、フォームID、CTA文言、ページパスなど、導線分析に必要な値だけです。

実装コード

以下は、実装したコードを汎用化したものです。FORM_ID、相談種別フィールドのセレクタ、serviceMap は自分のフォームに合わせて変更してください。

<script>
(function () {
  'use strict';

  var FORM_ID = '158';
  var FORM_SELECTOR = '#wpforms-form-' + FORM_ID;
  var SERVICE_SELECTOR = '#wpforms-' + FORM_ID + '-field_7';
  var lastServiceInterest = '';
  var formStarted = false;

  var serviceMap = {
    'ai-dx': 'AI導入の費用と進め方を相談したい',
    'ai-assessment': 'AI業務診断',
    'ai-poc': 'AI PoC',
    'ai-implementation': '本格実装',
    'ai-advisor': 'AI顧問',
    'pmo': 'PM・PMO支援',
    'development': 'Web・システム開発'
  };

  function track(eventName, params) {
    window.dataLayer = window.dataLayer || [];
    window.gtag = window.gtag || function () {
      window.dataLayer.push(arguments);
    };
    window.gtag('event', eventName, params || {});
  }

  function queryServiceInterest(url) {
    try {
      return new URL(url, window.location.href)
        .searchParams.get('service_interest') || '';
    } catch (error) {
      return '';
    }
  }

  function selectedService() {
    var field = document.querySelector(SERVICE_SELECTOR);
    return field && field.value ? field.value : lastServiceInterest;
  }

  function preselectService() {
    var key = queryServiceInterest(window.location.href);
    var field = document.querySelector(SERVICE_SELECTOR);
    var label = serviceMap[key] || '';

    if (!field || !label || field.value) return;

    var optionExists = Array.prototype.some.call(
      field.options,
      function (option) {
        return option.value === label;
      }
    );

    if (!optionExists) return;

    field.value = label;
    lastServiceInterest = label;
    field.dispatchEvent(new Event('change', { bubbles: true }));
  }

  function onContactLinkClick(event) {
    var link = event.target.closest('a[href*="/contact/"]');
    if (!link) return;

    track('cta_click', {
      cta_text: (link.textContent || '')
        .trim()
        .replace(/\s+/g, ' ')
        .slice(0, 80),
      service_interest:
        queryServiceInterest(link.href) || 'general',
      link_url: link.href,
      source_page: window.location.pathname
    });
  }

  function onFormInteraction(event) {
    if (formStarted || !event.target.closest(FORM_SELECTOR)) return;

    formStarted = true;
    lastServiceInterest = selectedService();

    track('lead_form_start', {
      form_id: FORM_ID,
      service_interest:
        lastServiceInterest ||
        queryServiceInterest(window.location.href) ||
        'unselected',
      source_page: window.location.pathname
    });
  }

  function onServiceChange(event) {
    if (event.target.matches(SERVICE_SELECTOR)) {
      lastServiceInterest = event.target.value || '';
    }
  }

  function onWpformsSuccess() {
    track('lead_form_completed', {
      form_id: FORM_ID,
      service_interest: selectedService() || 'unselected',
      source_page: window.location.pathname
    });
  }

  function init() {
    preselectService();
    lastServiceInterest = selectedService();

    document.addEventListener('click', onContactLinkClick, true);
    document.addEventListener('focusin', onFormInteraction, true);
    document.addEventListener('change', onServiceChange, true);

    if (window.jQuery) {
      window.jQuery(document.body).on(
        'wpformsAjaxSubmitSuccess',
        onWpformsSuccess
      );
    }
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
})();
</script>

CTAから相談種別を引き継ぐ

CTAのURLに service_interest を付けます。

<a href="/contact/?service_interest=ai-poc">
  AI PoCの費用と進め方を相談する
</a>

問い合わせページを開くと、URLの値に対応する選択肢を自動選択します。

これは計測のためだけではありません。ユーザーがフォームで同じ内容を選び直す手間も減らせます。

なぜ focusin でフォーム開始を取るのか

フォーム開始は、入力欄を初めて操作した時点で一度だけ送信します。

click だけにすると、キーボード操作でフォーカスしたケースを拾えません。focusin を使うと、入力方法にかかわらずフォームの利用開始を検知できます。

formStarted で二重送信を防いでいるため、一度のページ表示で lead_form_start は一回だけです。

Ajax送信の成功後だけ完了にする

送信ボタンのクリックを完了扱いにすると、入力エラーや通信エラーもコンバージョンに含まれます。

WPFormsでは、Ajax送信成功後の wpformsAjaxSubmitSuccess を受けて完了イベントを送るようにしました。

これにより、次の状態を分けられます。

  • CTAは押したがフォームを始めていない
  • フォームは始めたが送信していない
  • 送信に成功した

実装後に確認したこと

自社サイトでは、公開後に次を確認しました。

  1. 公開HTMLに計測コードが含まれている
  2. サービスページのCTAから service_interest 付きで遷移する
  3. 問い合わせフォームの相談種別が自動選択される
  4. JavaScriptの構文エラーがない
  5. イベントパラメータに個人情報が含まれていない

GA4への到達は、RealtimeまたはDebugViewで確認します。独自パラメータを通常のレポートで使う場合は、GA4側でカスタムディメンションの登録も必要です。

計測して終わりにしない

この計測の目的はイベント数を増やすことではなく、問い合わせ導線の詰まりを特定することです。

例えば、次のように改善箇所を判断できます。

状態 仮説 次の改善
CTAクリック率が低い オファーが曖昧 CTAを「30分で費用と進め方を整理」など具体化
CTA後のフォーム開始率が低い 入力項目が多い、期待と違う ファーストビューと項目数を見直す
フォーム開始後の完了率が低い 必須項目・エラー・不安が障壁 項目削減、説明文、エラー表示を改善
特定相談種別だけ完了率が低い サービス説明とフォームが不一致 サービスページと選択肢を揃える

公式ドキュメント


この記事は、株式会社Root onの自社サイトで実装・検証した内容を、再利用できる形に整理したものです。

生成AI・DXの業務整理、PoC、PM・PMO、実装支援については、Root onのAI・DX支援で紹介しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?