[GTM]data属性を使用したGA4の自動イベント計測
2023年07月18日
ライター:春山 勇悟

Google アナリティクス 4(以下GA4)は、様々なユーザーアクションをイベントとして計測できます。

その中でも、以下の2つのアクションはどのサイトでも計測する可能性が高いものです。

  • 何をクリックしたか(リンクやボタンなど)
  • 何が表示されたか(バナーなど)

この記事では、上記2つのユーザーアクションをHTMLタグの属性である「data属性」とGoogle タグマネージャ(以下、GTM)を活用して、半自動で計測する方法を紹介します。

この設定により、タグやトリガーの数を大幅に減らすことができ、管理の面でもメリットが大きいですので、参考なれば幸いです。

それでは、さっそく見ていきましょう!

  1. data属性とは何か
  2. なぜIDやclass属性ではなくdata属性を使うのか
  3. 【設定手順①】data属性の準備
  4. 【設定手順②】GTMの設定
    1. カスタムHTMLタグを作成する
    2. データレイヤーの変数を作成する
    3. カスタムイベントのトリガーを作成する
    4. GA4のイベントタグを作成する
  5. 自動イベント計測内容の解説
  6. 【参考】なぜカスタムテンプレート変数を使用するのか
  7. わりに

data属性とは何か

「data属性」は、HTMLのタグに設定できる属性の一つです。属性とは、HTMLの要素に情報を付け足すものです。リンクを作るときには、「この文字をクリックするとこのページに飛ぶ」という情報を付け足します。これが属性です。

その中で、data属性は少し特別な属性で、好きな情報を付け足すために使います。通常の属性は、たとえば「このリンクはどこに飛ぶか」のような、Webページがちゃんと動くための重要な情報を持っています。

しかし、data属性の情報はユーザーには見えませんし、Webページにも直接影響しません。

つまり、data属性はページの中にカスタム情報を埋め込むための属性であり、ユーザーやWebページへの直接影響がないことから、比較的安全で実装も簡単です。

次に、data属性の書き方について説明します。

data属性は、「属性名」と「属性値」で構成されるキーと値のペアで入力されます。

属性名:

  • 「data-」ではじまり、任意の名前を付けることができます。
  • 一般的には英字を使い、単語間の区切りにはハイフン(-)が使われます。
  • 大文字は使えません。

属性値:

  • 任意の文字列 (数値も文字列として扱われます)。

data属性についての詳しい情報はこちらをご参照ください。

なぜIDやclass属性ではなくdata属性を使うのか

よくあるケースとして、既存のIDやclass属性をトリガーなどの条件に使用することがあります。これはHTMLを変更する必要がなく、GTM側の対応だけで済むため、data属性にはないメリットがあります。

しかし、デメリットもあります。主なものは以下の通りです。

※以下内容はスタイルと分析を兼ねて管理できている場合はこの限りではありません。

サイトの更新で計測できなくなる恐れがある:

IDやclass属性は主にスタイルのために使用される属性であり、分析のために設定されるものではありません。そのため、サイトが更新されると属性が変更または削除される可能性が高く、計測が停止する恐れがあります。

データ取得が困難 :

IDやclass属性は分析に適した属性ではないため、必要な情報を取得するためには、GTM側で複数の設定が必要になる場合があります。たとえば、計測箇所ごとにタグやトリガーを分けたり、JavaScriptを使用してデータを取得する必要があることがあります。

そのため、HTML、CSS、JavaScriptなどのプログラミング言語の理解が必要になることがあります。

上記点を考慮すると、HTMLを改修することができる場合は、data属性を利用することを強くお勧めします。

さて、ここまででdata属性の概要とメリットについて説明しました。ここからは、実際の設定方法について説明します。

【設定手順①】data属性の準備

ここから、「何をクリックされたか」と「何が表示されたか」を半自動で計測する方法について説明します。

GA4のイベント計測には、イベント名が必ず必要であり、必要に応じてイベントパラメータを取得します。今回は、data属性を使用して以下の3つの情報をすべて取得します。

  • イベント名
  • イベントパラメータ名
  • イベントパラメータの値

まず、イベント名は以下のコードになります。

※本記事の計測設定においては、属性名は固定です。

クリック計測の場合:

data-gtm-event-click="{{任意のイベント名}}" 
(例)data-gtm-event-click="banner_click"

表示計測の場合:

 data-gtm-event-imp="{{任意のイベント名}}" 
(例)data-gtm-event-imp="banner_imp"

次に、イベントパラメータ名と値は、以下のコードになります。

data-gtm-param-{{任意のパラメータ名}}="{{任意のパラメータ値}}"

「data-gtm-param-」までが固定です。そして、{{任意のパラメータ名}}の部分がパラメータ名となります。単語が複数ある場合はハイフン(-)でつなげます。

例えば、バナーの情報を取得したい場合は以下のコードになります。

data-gtm-param-banner-name="バナー1" 
data-gtm-param-banner-type="A"

以下はイベント名とイベントパラメータを組み合わせたサンプルコードです。同じ要素でクリックも表示も計測したい場合は、イベント名のdata属性を2つとも同じ要素内に追加してください。

サンプルコード:

<h2>バナー1</h2>
<a
  href="https://ayudante.jp/"
  data-gtm-event-click="banner_click"
  data-gtm-event-imp="banner_imp"
  data-gtm-param-banner-name="バナー1"
  data-gtm-param-banner-type="A"
>
  <img
    src="https://ayudante.jp/wp-content/uploads/2021/08/ayu_logo_stuffpage.png"
    alt="サンプル画像1"
  />
  <p>リンク先はこちら</p>
</a>

これで、data属性の準備が整いました。
次に、GTM側の設定を行います。

【設定手順②】GTMの設定

GTM側の設定には以下の4点があります。

  • カスタムHTMLタグを作成する
  • データレイヤーの変数を作成する
  • カスタムイベントのトリガーを作成する
  • GA4のイベントタグを作成する

それぞれの詳細を説明します。

カスタムHTMLタグを作成する

まずは、カスタムHTMLタグを作成します。
以下のコードをカスタムHTMLタグに入力してください。
■タグ>カスタムHTMLタグ

<script>
  (function() {
      var unCamelCase = function(str, separator) {
          separator = separator || '_';
          return str
              .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2')
              .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2')
              .toLowerCase();
      };

      var gtmParamRegex = new RegExp('gtmParam(.+)');

      var pushToDataLayer = function(target, eventType) {
          // Check if this element has already been processed for imp events
          if (eventType === 'gtmEventImp' && target.dataset.processed) return;

          var dataLayerObject = {};
          dataLayerObject['event'] = target.dataset[eventType];
          // Always add data_trigger key with value true
          dataLayerObject['data_trigger'] = true;

          Object.entries(target.dataset).forEach(function(dataEntry) {
              var key = dataEntry[0];
              var value = dataEntry[1];
              var match = key.match(gtmParamRegex);
              if (match && match[1]) {
                  dataLayerObject[unCamelCase(match[1], '_')] = value;
              }
          });

          window.dataLayer.push(dataLayerObject);

          // Mark this element as processed if it's an imp event
          if (eventType === 'gtmEventImp') {
              target.dataset.processed = true;
          }
      };

      var handleIntersection = function(entries, observer) {
          entries.forEach(function(entry) {
              if (entry.isIntersecting) {
                  pushToDataLayer(entry.target, 'gtmEventImp');
              }
          });
      };

      var handleClick = function(event) {
          pushToDataLayer(event.currentTarget, 'gtmEventClick');
      };

      var intersectionObserver = new IntersectionObserver(handleIntersection, { threshold: 0 });

      var addObserverAndListener = function(element) {
          if (element.dataset.gtmEventImp) {
              intersectionObserver.observe(element);
          }
          if (element.dataset.gtmEventClick) {
              element.addEventListener('click', handleClick);
          }
      };

      document.querySelectorAll('[data-gtm-event-imp], [data-gtm-event-click]').forEach(addObserverAndListener);

      // Add a MutationObserver to listen for new nodes being added to the DOM
      var mo = new MutationObserver(function(mutations) {
          mutations.forEach(function(mutation) {
              if (mutation.type === 'childList') {
                  mutation.addedNodes.forEach(function(node) {
                      if (node.nodeType === Node.ELEMENT_NODE) {
                          if (node.dataset.gtmEventImp || node.dataset.gtmEventClick) {
                              addObserverAndListener(node);
                          }
                          // Check if any child elements have the required data attributes
                          node.querySelectorAll('[data-gtm-event-imp], [data-gtm-event-click]').forEach(addObserverAndListener);
                      }
                  });
              }
          });
      });
      mo.observe(document.body, { childList: true, subtree: true });

  })()
</script>

■設定画面

トリガーは、「DOM Ready」にします。
(適宜計測範囲は調整してください)

上記のコードが何をしているかを端的に説明します:

  • クリックと要素の表示イベントを検知
  • イベントを検知した場合、data属性の内容をデータレイヤーにプッシュ(追加)

プッシュされる内容は以下の通りです:

  • イベント名:{{任意のイベント名}}で設定したイベント名
  • パラメータ名: {{任意のパラメータ名}}で設定したパラメータ名
  • パラメータ値: {{任意のパラメータ値}}で設定したパラメータの値

上記に合わせて、キーが「data_trigger」で、値が「true」の変数も合わせてプッシュします。
※これは後述のトリガー作成時に使用します。

※データレイヤーについては、弊社コラムもご参照ください。
Googleタグマネージャ基礎 初心者でもわかるデータレイヤー

先ほどのサンプルコードの場合、以下のような内容がプッシュされます。

クリックイベント:data-gtm-event-click

dataLayer.push({
 event: "banner_click",
 data_trigger: true,
 banner_name: "バナー1",
 banner_type: "A"
})

要素の表示イベント:data-gtm-event-imp

dataLayer.push({
 event: "banner_imp",
 data_trigger: true,
 banner_name: "バナー1",
 banner_type: "A"
})

注:プッシュされたイベントパラメータ名の変数名が、ハイフン(-)からアンダーバー(_)に変換されているため、ご注意ください。

注:カスタムHTMLタグは、タグの内容をHTML内に追加する機能です。そのため、既存の設定と競合したり、サイト表示が崩れたりする可能性があります。必ず検証を行ったうえで公開してください。

データレイヤーの変数を作成する

ここではSimo Ahava氏のカスタムテンプレート変数「Data Layer Picker」を使用します。

詳細についてはSimo氏のコラムを参照ください。

既存で用意されているデータレイヤーの変数を使用しない理由は、後半に解説していますので、ご興味のある方はそちらをご覧ください。

まず、カスタムテンプレート変数を追加します。

テンプレート>検索ギャラリーをクリック

■検索ボックスに「Data Layer Picker」で絞り込み>変数をクリック

■「ワークスペースに追加」をクリック

■権限内容に問題なければ、追加をクリック
注:カスタムテンプレート変数はサードパーティ製であるため、権限内容に問題ないのを確認してから追加をしてください。

これでカスタムテンプレート変数を使う準備ができました。
今回はサンプルとして、以下の3つのデータレイヤー変数を作成します。

  • banner_name
  • banner_type
  • data_trigger(必須)

パラメータ名に含まれるハイフン(-)はアンダーバー(_)に変換しています。

たとえば、data属性が「data-gtm-param-bannername」の場合は、変数名は「banner_name」になります。

それでは作成をしていきましょう。

■変数>ユーザー定義変数の新規をクリック>「Data Layer Picker」を選択

  • 「Specific Property」を選択します。
  • 「Property name」に「banner_name」と入力します。

同じ要領で、「banner_type」と「data_trigger」の変数を作成します。

カスタムイベントのトリガーを作成する

カスタムイベントのトリガー作成をします。
以下設定を行います。

トリガー>カスタムイベントを選択

  • イベント名には「.*」と入力します。
  • 「正規表現を使用」のオプションをチェックします。
  • トリガーの発生場所は「data_trigger」で作成した変数名で、条件は「true」に等しいにします。

この設定を行うことで、今回の自動計測設定のイベント全てに対応できます。

GA4のイベントタグを作成する

GA4のイベントタグを1つ作成します。

■タグ>Google アナリティクス: GA4 イベントを選択

  • 任意の設定タグを選択します。
  • イベント名には変数{{event}}を入力します。
  • イベントパラメータ名は必要に応じて変更可能ですが、data属性で指定したものをそのまま使用するのを推奨します。
  • パラメータの値には、作成したデータレイヤーの変数を入力します。
  • 最後に、作成したカスタムイベントトリガーを紐づけます。

お疲れ様です!設定は以上で完了です。
次はサンプルページを見ながら解説をしていきます。

自動イベント計測内容の解説

サンプルページのコードは以下になります。

このページには2つのバナーがあり、共通して要素の表示とクリックのイベント用data属性があります。一方で、イベントパラメータ用のdata属性は値は異なっています。

GTMのプレビューモードで計測内容を見てみましょう。

まず、ページ表示のタイミングで、画面内に2つのバナーが表示されているので、「banner_imp」イベントが2回計測されています。

それぞれの表示イベントの計測内容を見てみましょう。

バナー①(要素の表示)

バナー②(要素の表示)

それぞれ、イベントパラメータの値が変更されて、イベント計測されていることがわかります。

また、各要素は一度のみ発火するようにしていますので、画面内を上下にスクロールしても複数発火することはありません。

次にクリックイベントを見ていきましょう。バナーをそれぞれクリックします。

バナー①(クリック)

バナー②(クリック)

同じように、「banner_click」イベントが2回計測され、イベントパラメータの値が変更されていることがわかります。

要素の表示イベントとは異なり、同じ要素を複数回クリックした場合は都度計測されます。


無事に、data属性の内容に応じてクリックと要素の表示が計測されていることが確認できました!

この設定をすることで、今後HTML側にdata属性を追加するだけで、GTMは変更を加えずに自動でイベント計測が可能となります。

また、データレイヤーの変数を増やしたくなったら、新規にGA4イベントタグを作成する必要はなく、既存のイベントタグに追加することが可能です。

【参考】なぜカスタムテンプレート変数を使用するのか

「データレイヤーの変数」ではなく、カスタムテンプレート変数の「Data Layer Picker」を使用する理由について説明します。

データレイヤーの仕様として、プッシュされた情報は、ページ遷移などでGTMが再読み込みされるか、値を上書きされるか、あるいはオブジェクトごとnullで初期化されるまで、保持されます。

この仕様が今回の計測設定にどのような影響を与えているのか具体例を見ていきましょう。カスタムテンプレート変数ではなく、通常のデータレイヤー変数を2つ作成します。

  • banner_name
  • banner_type

変数>ユーザー定義変数の新規をクリック>「データレイヤーの変数」を選択

同様に、「banner_type」のデータレイヤーの変数も作成します。

次に、検証用にGA4イベントを一つ作成し、上記の2つの変数をイベントパラメータの値として入力します。

準備ができましたので、GTMのプレビューモードで見てみます。

バナー①では、以下の情報がデータレイヤーにプッシュされました。

dataLayer.push({
 event: "banner_imp",
 data_trigger: true,
 banner_name: "バナー1",
 banner_type: "A"
})

バナー②では、以下の情報がデータレイヤーにプッシュされました。

「banner_type」 はプッシュされていません。

dataLayer.push({
 event: "banner_imp",
 data_trigger: true,
 banner_name: "バナー2",
 //banner_typeはなし
})

それぞれのイベント計測の内容を見てみましょう。

バナー①

バナー

ここで、「おや?」と思った方もいらっしゃるかもしれません。

バナー②には「banner_type」をデータレイヤーにプッシュしていないにもかかわらず、パラメータとして追加されてしまっています。これは誤りではなく、データレイヤーの仕様によるものです。

前述したとおり、データレイヤーは値を保持するため、バナー①で送信した情報が残っています。そのため、バナー②のイベントのときにも送信されるという動作となります。

通常は、各イベントごとに適切なイベントパラメータをセットすればよいので気にしなくてもいいのですが、今回のように汎用的なイベントタグの場合は、不要なイベントパラメータの値が含まれないように注意する必要があります。

「Data Layer Picker」は、過去にプッシュされたデータレイヤーに影響をうけず、プッシュされたタイミングの情報に限定することができます。そのため、不要なイベントパラメータを計測されないようにすることができます。

おわりに

いかがでしょうか?

data属性とGTMを巧みに活用することで、GA4の計測を半自動化し、効率的に行うことが可能です。また、GTMにおけるタグとトリガーの量を削減できるため、管理が容易になります。

さらに、データレイヤーを利用してカスタムイベントを送信することで、他の広告タグなどへのトリガーの適用もスムーズに行えます。

本記事の内容はやや複雑かもしれませんが、何度も目を通しながら、ぜひ実装に挑戦していただきたいと思います。

たとえ実装が困難であっても、data属性がこんなにも可能性を秘めていることに気付くきっかけになれば、大変嬉しいです。

採用情報はこちら

この記事を書いた人
$uname
春山 勇悟
デジタルマーケティングエンジニア
前職では主にGoogleタグマージャを用いたGoogleアナリティクスの導入支援や、Looker Studioでのダッシュボード構築、データ利活用の支援などを担当。趣味は愛犬との散歩とサウナ。
最近書いた記事