Googleアナリティクスで同一URLでフォーム遷移する場合のページビュー計測

計測URLを正規化する、1ページは1URLに集約してページビュー計測することが望ましいことはhttps://www.marketechlabo.com/send-ga-pageview-canonicalized-url/で取り上げたが、この「1ページで複数URL」とは逆に「複数のページで1URL」になるパターンの対応法を取り上げる。

よくあるのはフォームの遷移などで、同一URLで異なる内容のページが表示されることがある。

入力フォーム→確認画面→完了画面

これらが画面遷移はあるものの1URLで完結しているケースである。ひどい場合は完了画面までもが同一URLになるため、コンバージョンの計測すらできない。

これをステップごとに異なる仮想URLを発行して計測する(ga('send', 'pageview', {'page': 'ステップの仮想URL'}))のだが、中にはフォームのシステム側で仮想URLを発行させ、それをGoogleアナリティクスのトラッキングコードに挿入する実装指示書もある。

そうなるとシステムの改修のコスト、手間がかかってしまうため、システムの改修は極力回避したい。

今回は純粋にHTMLの範囲だけでこの問題を解決する方法を取り上げる。通常

  1. ステップに応じてtitleタグの内容が異なる場合と、
  2. ステップに応じて見出しの内容が異なる場合と、
  3. URLもtitleタグの内容も同じだが、ページ内で表示している画像が異なる場合

のいずれかに当てはまることが多いので、これらのパターンを想定してユニバーサルアナリティクスの生タグで実装する方法を説明する。

ステップに応じてtitleタグの内容が異なる場合

あらかじめ

  • 共通になるURL(パス名)と
  • titleのテキストと付ける仮想URL(パス名)の組み合わせ

を設定しておく。

// トラッカーの呼び出し(デフォルトのトラッキングコード)
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXXXX-Y', 'auto');

// 設定
// 共通になるパス
var strCommonPath = '/service/form.php';
// 仮想パス名をキー、titleのテキストを値にとる連想配列
var steps = {
  '/service/form/1_input': '会員情報入力フォーム',
  '/service/form/2_confirm': '登録内容の確認',
  '/service/form/3_thanks': '登録ありがとうございました',
};

// 処理
// パス名が共通の場合
if (window.location.path == strCommonPath){
  // stepの中からtitleがマッチするものを抽出
  var paths = Object.keys(steps).filter(function(path) { return steps[path]==document.getElementsByTagName('title')[0].innerText });
  if (paths.length > 0) {
    // マッチした場合に仮想パス名をsend pageviewする。
    ga('send', 'pageview', {'page': paths[0]});
  } else {
    // どれにもマッチしない場合、仕方なく共通のパス名を採用
    ga('send', 'pageview');
  }
// パス名が共通でなければデフォルトの動作を採用
}else{
  ga('send', 'pageview');
}

ステップに応じて見出し(<h1>)の内容が異なる場合

あらかじめ以下を設定しておく。

  • 共通になるURL(パス名)と
  • 各ステップの見出し(<h1>)に固有に含まれるテキストと付ける仮想URL(パス名)の組み合わせ

たとえば見出しが

  • 会員情報入力画面
  • 会員情報確認画面
  • 会員登録完了

という場合、

  • 入力
  • 確認
  • 登録完了

などが固有のテキストとなる。

// トラッカーの呼び出し(デフォルトのトラッキングコード)
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXXXX-Y', 'auto');

// 設定
// 共通になるパス
var strCommonPath = '/service/form.php';
// 仮想パス名をキー、h1に含まれる固有のテキストを値にとる連想配列
var steps = {
  '/service/form/1_input': '入力',
  '/service/form/2_confirm': '確認',
  '/service/form/3_thanks': '完了',
};

// 処理
// パス名が共通の場合
if (window.location.path == strCommonPath){
  // DOMから値を取得するのでDOM取得完了を待つ必要がある
  document.addEventListener('DOMContentLoaded', function(){
    // stepの中からh1の内容が部分一致するものを抽出
    var paths = Object.keys(steps).filter(function(path) { return document.getElementsByTagName('h1')[0].innerText.indexOf(steps[path]) > -1 });
    if (paths.length > 0) {
      // マッチした場合に仮想パス名をsend pageviewする。
      ga('send', 'pageview', {'page': paths[0]});
    } else {
      // どれにもマッチしない場合、仕方なく共通のパス名を採用
      ga('send', 'pageview');
    }
  }, false);
// パス名が共通でなければデフォルトの動作を採用
}else{
  ga('send', 'pageview');
}

<title>と同じ。document.getElementsByTagName()の引数が違うだけ。
今回は<h1>に含まれる固有のテキストで部分一致を探したが、それは<title>でも可能。

URLもtitleタグの内容も同じだが、ページ内で表示している画像が異なる場合

前提条件

  • URLが共通となるフォームの遷移にはクラス名「form」を持つ<div>が含まれる
  • 上記の<div class="form">直下の<img>タグがステップによって固有である
  • 画像ファイル名の拡張子を除いた部分を仮想URLとして付ける(拡張子は.jpg

というルールにする。

// トラッカーの呼び出し(デフォルトのトラッキングコード)
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXXXX-Y', 'auto');

// DOMから値を取得するのでDOM取得完了を待つ必要がある
document.addEventListener('DOMContentLoaded', function(){
  // <div class="form">の直下に<img>が来るパターンをdocument.querySelector()で探す
  var imgStep = document.querySelector('div.form > img');
  // そのパターンがあれば(フォーム遷移であれば)
  if (imgStep !== null){
    // 画像ファイル名の拡張子(.jpg)を除いた部分を取得
    var imgMatched = imgStep.src.match(/([^/]+)\.jpg$/);
    if (imgMatched) {
      // 画像ファイル名の拡張子を除いた部分をパス名に付加してsend pageview
      if (imgMatched[1]) {
        ga('send', 'pageview', {'page': location.pathname + '/' + imgMatched[1]});
      // 例外(imgMatched[1]がない):仕方なく共通のパス名を採用
      } else {
        ga('send', 'pageview');
      }
    // 例外(画像ファイル名の拡張子が.jpgでない):仕方なく共通のパス名を採用
    } else {
      ga('send', 'pageview');
    }
  // それ以外のページであればデフォルトの動作を採用
  } else {
    ga('send', 'pageview');
  }
}, false);

Googleアナリティクス関連Tips

イベント計測

ページビュー計測

eコマース計測

Google の記事一覧