ReactでGTMとGA4を使ってみた

はじめに

こんにちは、AG-Boost事業部でエンジニアとして内定者バイトをしている井上健人です。

この度、AG-Boostの事業部内管理画面(以下、管理画面)に分析用のGTMを埋め込む機会があり、 試行錯誤しつつ0から勉強しましたので、ご紹介しつつ、自分の備忘録として残したいと思います。

1. そもそもGTMって何?

GTMとは、正式名称Google Tag Manager、Google AnalyticsやWeb広告などを利用する際に埋め込む「タグ」を一元管理するものです。無料で使えます。

従来であれば、役割ごとのタグ(分析用のタグや広告用のタグ等)をWebサイトやアプリに埋め込んで、一つ一つHTMLのコード上で管理しなければその役割を果たすことは不可能でした。

そこで、「GTMのタグ」としてWebサイト上に埋め込み、そこから全てのタグを管理できるという仕組みを提供するものがGTMです。

具体的に何が変わるのか?

  • 埋め込むタグを一つのコンソールで管理できる
  • 後からタグの変更を行うときにソースコードを編集する手間がなくなる
  • プレビュー機能やバージョン管理で不具合対策もバッチリ

というとっても凄いもの

初学者で従来の分析ツールを使ったことのない私からしたらメリットがあまり分からないですが、普及率がとても高く、参考文献がいっぱい転がっているのがとても嬉しかったです。

2. そもそもGA4って何?

GA4(google analytics 4)とは、ウェブサイトとアプリの両方からイベントベースのデータを収集して表示するアナリティクスツールです。

[GA4] 次世代のアナリティクス、Google アナリティクス 4 のご紹介

簡潔にまとめると、ウェブサイトでアクションが発生したときの状況などを蓄積、グラフ形式等でビジュアライズしてくれる超優れものです。 今回はGTMから送られるデータをGA4でビジュアライズするために使用します。

3.今回の実装目標

  • 管理画面にアクセスするユーザーの動向を知る
  • 具体的に必要な情報は、閲覧ページの情報(page_view)が欲しい

4.環境構築

GA4とGTMの環境を構築するところから行います

4-1.GA4の環境構築

GA4 アカウント作成

まず上記のページからGA4のアカウントの発行を行います

今回は開発用のアカウントということで名前をdevとしましたが、基本ここには大きなプロジェクトの括りや企業名が入ります スクリーンショット 2024-07-16 14.53.25.png

続いてプロパティ名を登録します ここにはwebページの名前やアプリの名前を登録していきます スクリーンショット 2024-07-16 14.55.40.png

ここにはビジネスの業種と規模を入れます スクリーンショット 2024-07-16 14.58.18.png

そしてビジネスの目標を入れていきます
分析をすることで得たい効果を選択すると最適なテンプレートを入れてくれます スクリーンショット 2024-07-16 14.59.29.png

今回はwebページを分析するので、webを選択します スクリーンショット 2024-07-16 15.00.38.png

webサイトのURLとストリーム名を入れます

拡張計測機能とは、ユーザーのさらに詳しい動向(しっかりスクロールしてページを全て見ているのか等)を調べるためのものです
今回はそこまで必要ないと思いますので、offで始めました スクリーンショット 2024-07-16 15.02.23.png

この後データストリームの設定など出てきますが、一旦無視してGA4の設定は完了とします。

3-2.GTMの設定

GTM アカウント作成

上記のページからアカウント作成をクリックします スクリーンショット 2024-07-16 15.07.55.png

GA4と同じイメージでアカウント名、コンテナ名、使用プラットフォームを選択します スクリーンショット 2024-07-16 15.09.56.png

以上でGA4、GTMの環境構築は完了です。

3-3.react-gtm-moduleの導入

様々な技術記事を読み、 reactにgtmを導入するには大きく二つのルートがあることを知りました

  1. index.htmlにscriptを貼り付ける王道ルート
  2. ライブラリを使用するルート

参考文献を元にまとめると、

  • 基本的にGTMを単純に埋め込んで簡潔な分析をするなら前者のscriptを貼り付けるだけで大丈夫
  • dataLayerを使用して様々なパラメータを送って関係性を分析する、webアプリ内で関数を使用してeventを送信しないと埋め込みができないなど、細かいところに手が届く設定が必要ならライブラリがおすすめ

上記二つを実際に実装してみて比較したところ、今後必要になるイベントデータ取得がdataLayerを使用しないと実装できないこと、コードの可読性がライブラリを使用した方が高いことより、今回は後者で実装を行いました。

react-gtm-module

今回使用したのはreact-gtm-module、以下を実行してインストールをします

npm install react-gtm-module --save

src配下に下記のようにgtm.tsxを作成、GTM-xxxxxxにはタグマネージャーの管理画面にあるGTMタグIDを入れます

import TagManager from 'react-gtm-module';

const GTM_ID = 'GTM-xxxxxx';
const tagManagerArgs = {
  gtmId: GTM_ID,
};
TagManager.initialize(tagManagerArgs);

スクリーンショット 2024-07-16 15.37.03.png

ここまででgtmの埋め込み自体は完了しました! とても簡単でびっくりです。

3-4.テスト

ここまで来たら、基本的なpage_viewを実装して、動くかテストしてみたいと思います!

タグマネージャー->タグから新規ボタンをクリックします スクリーンショット 2024-07-16 15.40.17.png

タグの設定->Googleアナリティクス->GoogleアナリティクスGA4イベントを選択してセットします スクリーンショット 2024-07-16 15.41.33.png

一旦GA4に戻って、 設定->データの収集と修正->データストリーム からG-から始まる測定IDを取得しました スクリーンショット 2024-07-16 15.43.48.png スクリーンショット 2024-07-16 15.47.46.png

測定IDを貼り付け、トリガーにAll Pagesを選択します スクリーンショット 2024-07-16 15.51.42.png

イベント名はpage_viewとしておきます スクリーンショット 2024-07-16 16.02.10.png

同時に、このコンテナにGoogleタグはありませんの隣のボタンからgoogleタグも作成します
タグIDにGA4の測定IDが自動的に挿入されます スクリーンショット 2024-07-16 15.57.58.png

ここまで来たら、二つのタグを適切な名前を付けて保存します
以下のようになりました スクリーンショット 2024-07-16 16.05.30.png

早速しっかり動いているかチェックしてみます!
画面右上のプレビューをクリックします スクリーンショット 2024-07-16 16.07.36.png

Your website's URLにwebサイトのURLを入れます
開発環境のlocalhostでも大丈夫です スクリーンショット 2024-07-16 16.11.10.png

このような画面が表示され、初期化などの処理が走っており、しっかりタグが働いていることを確認できました スクリーンショット 2024-07-16 16.15.00.png

しかし、ここまで来てセットしたpage_view(閲覧ページ情報取得)が動かないことに気づきました...

どうやらReactなどにおけるGTMの動作は少し違うらしく、動かすには工夫が必要そうです。

4.SPAにおけるGTM+GA4の利用方法

page_viewが機能せず少ししょんぼりしましたが、これは管理画面がSPAだからだと知りました。

SPAとは、Single Page Applicationの略でReact、Angular、Vue等が挙げられます。 SPAはURLやサイトがユーザー目線で切り替わってるように見えて、中身は一つのhtmlファイル上でjavascriptファイルが踊ってるだけ。 デフォルトのpage_viewには切り替わってる判定をされないってわけです。

ではそれをGA4は対応しないか?

実は対応している(GA4拡張計測)のですが、以下のようなデメリットがあります

  • 計測時のカスタムディメンションの値を更新しない
  • SPAの切り替え時に送信されたpage_viewイベントが過去の値を引き継いでいる
  • URLで元いた位置などを取得する際に任意の動作とならない可能性がある

つまり、拡張機能をonにすることで、元々自動取得ができていた値が潰れてしまうのです。

では、SPAの罠を回避してpage_viewを設計してみます

二つほど考えて実装してみましたので、紹介させていただきます。

1. カスタムdataLayerを使用して直接データを送る

以下のように関数を追加してmoduleをimportし、dataLayerでeventを送ってあげます もしどのページを見ているかの情報を含めたい場合はそのURL情報等もdataLayerに含めば大丈夫です

import TagManager from 'react-gtm-module';

const page_view = () => {
  TagManager.dataLayer({
    dataLayer: {
      event: 'page_view',
    }
  });
};

後はこのpage_view関数をページが読み込まれるタイミングで呼び出すだけです。

簡単で何をしているかも一目でわかるので、ベストプラクティスだと思います。

2. GTMデフォルトで取得できるデータを使用して判定する

デフォルトでURL切り替えが発生すると送信されるデータを利用します。

gtm.newUrlgtm.oldUrlを取得、比較して切り替わったタイミングをpage_viewとしました

変数より、追加をクリックします スクリーンショット 2024-07-19 11.09.16.png

変数タイプより、データレイヤーの変数を選択します スクリーンショット 2024-07-19 11.10.49.png

変数名にgtm.newUrlを入れます
名前も同じにしました スクリーンショット 2024-07-19 11.12.19.png

同じように、gtm.oldUrlを変数に登録します スクリーンショット 2024-07-19 11.14.42.png

もう一個変数を追加
カスタムJavaScriptというものを使います スクリーンショット 2024-07-19 11.15.56.png

コードは以下のようにして、名前を「切り替え発生」としました

function(){
  return {{gtm.newUrl}} !== {{gtm.oldUrl}};
}

スクリーンショット 2024-07-19 11.18.14.png

続いて、トリガータブからトリガーの新規追加を行います スクリーンショット 2024-07-19 11.19.43.png

トリガータイプは履歴の変更 スクリーンショット 2024-07-19 11.21.07.png

設定から、先ほど設定したカスタム変数がtrueのとき、トリガーされるように設定して保存します スクリーンショット 2024-07-19 11.22.15.png

ここまで来たら、page_viewのトリガーを先ほど作成したトリガーに変更します スクリーンショット 2024-07-19 11.24.15.png

設定を保存してプレビューしてみます
ページを移動してURLが変わると、historyというものが表示されるようになりました スクリーンショット 2024-07-19 12.00.40.png

詳細を確認すると、しっかり判定が動いていることもわかります!!! スクリーンショット 2024-07-19 11.58.50.png

まとめると、

  • 自動的にpage_viewと認識されないだけで、URLが切り替わるとgtmからoldUrlnewUrl等のデータは送られる
  • それらを元にカスタムJavaScript内でpage_viewのイベントを再定義してあげる

これでweb上のコード変更無しにSPAからのpage_viewイベントの送信ができましたね!すごい!

5. ユーザーの識別子を追加する

最後に、ふとGA4のリアルタイム画面を見ていて思いました

「これweb画面を複数開いたら、ユーザーも複数いると認識されてしまうのでは...?」と。

調べてみると、上記のことで測定値がおかしくならないように、GA4ではCookieやUser-ID、位置情報やユーザー特性からユーザーを区別する機能までついているらしいです。 凄い!!!

管理画面ではユーザーにuuidが割り当てられているので、uuidを識別子にしてみようと思います。

先ほどoldUrlnewUrlを設定したときと同じように、user_idをデータレイヤーの変数から取得するように追加します スクリーンショット 2024-07-19 13.51.24.png

page_viewのタグを開き、プロパティ名にuser_id、値に使用する変数を入れます

プロパティ名のuser_idは予約語なので、user_idはタイポミスしないようにします スクリーンショット 2024-07-19 13.54.26.png

最後に、webアプリ側でuser_idをdataLayerで送ってあげます

単純にdataLayerで配列にpushしても大丈夫ですが、user_idを毎回のイベントに紐付けることが決まっているのであれば初期化に組み込むのがベストであると思います。

import TagManager from 'react-gtm-module';

const GTM_ID = 'GTM-xxxxxx';
const tagManagerArgs = {
  gtmId: GTM_ID,
  dataLayer: {
    user_id: uid,
  }
};
TagManager.initialize(tagManagerArgs);

注意:user_id等のユーザー識別子はアクセスした個人が特定できないものを選んでください

ここまでできたら、いつも通りプレビューします
user_propertyというものが追加されていれば完璧です! スクリーンショット 2024-07-19 14.06.07.png

長文でしたが読んでいただきありがとうございます!

参考文献に感謝!!!!!

参考文献

GTM(Googleタグマネージャー)とは?設定・導入・連携方法を解説

Next.js で GTM + GA4を利用する

[GTM] GA4によるSPA計測の罠と対策

GA4のスクロール計測イベントをカスタマイズして分析する方法を紹介

Google Analytics4のUserIDについて

GA4でユーザープロパティを設定する方法は?

SPAのウェブサイトをGA4でアクセス解析する方法を解説

Googleタグマネージャ基礎 初心者でもわかるデータレイヤー

ユーザーIDがうまく計測できない!GTMで設定する方法は?~GA4よくある質問シリーズ(4)

React(SPA構成)でGA4+GTMを本番導入した時の気付きやトラブルシューティング

Google Analytics4(GA4)の設定をSPA(React)で行ったら2重にPVがカウントされた件