[[🦉nuxt2-vuetify2-playwright-sandbox]]に[[GA4]]を導入してみた記録。 ## 目的 - 仕事で[[SPA]]に対して[[GA4]]を入れる必要があったので素振りのため - [[Minerva]] ([[Obsidian Publish]]) を[[ユニバーサルアナリティクス]]から[[GA4]]に移行する必要があるため (準備運動) ## なぜ[[🦉nuxt2-vuetify2-playwright-sandbox]]? - 利用技術が似ている - 最近作ったのでコードに手を入れやすい - 多分あまり人気がない...けど誰がアクセスしているかちょっと気になる ## [[GA4]]のアカウント作成 以下を参考に。 <div class="link-card"> <div class="link-card-header"> <img src="https://blog.siteanatomy.com/wp-content/uploads/2023/01/icon.jpg" class="link-card-site-icon"/> <span class="link-card-site-name">やさしいGoogleアナリティクスブログ</span> </div> <div class="link-card-body"> <div class="link-card-content"> <div> <p class="link-card-title">GA4のプロパティとは?プロパティの作成、設定方法|UAとの違いも解説 | Googleアナリティクス</p> </div> <div class="link-card-description"> Googleアナリティクスのプロパティは、収集するアクセスデータを定義する役割を持ちます。クロスドメイントラッキングなど、アクセスデータ取得の土台となる設定です。この記事では、Googleアナリティク... </div> </div> <img src="https://blog.siteanatomy.com/wp-content/uploads/2020/06/anatomy_ogp-2.png" class="link-card-image" /> </div> <a href="https://blog.siteanatomy.com/google-analytics-property/#outline__4"></a> </div> ![[Pasted image 20230604171827.png]] ![[Pasted image 20230604171934.png]] ``` <!-- Google tag (gtag.js) --> <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-XXXXXXXXXX'); </script> ``` ## [[🦉nuxt2-vuetify2-playwright-sandbox]]に仕込む [[@nuxtjs.google-gtag]]を使う。 ### インストール ```console npm i @nuxtjs/google-gtag ``` ### 設定 [[nuxt.config]]の`modules`に追加。 ```js modules: [ [ "@nuxtjs/google-gtag", { id: "G-XXXXXXXXXX", config: { send_page_view: false, }, debug: true, disableAutoPageTrack: false, }, ], ], ``` ### [[Composable]]の作成 `composable/gtag.ts`を作る。[[Composition API]]と[[Options API]]どちらでも使えるように。[[Options API]]だと[[Composable]]は使いにくいけど、`composable`配下なのでそこは妥協してもらう。 ```ts import { getCurrentInstance } from "vue"; type EventName = "001_Top"; const useGoogleAnalytics = (): boolean => { const a = process.env.USE_GOOGLE_ANALYTICS; return a != null && !["no", "false"].includes(a.toLowerCase()); }; export function useGtag() { const gtag = (getCurrentInstance()?.proxy as any)["$gtag"]; const recordEvent = (eventName: EventName) => { if (!useGoogleAnalytics()) { return; } gtag("event", eventName); }; return { recordEvent, }; } export function useGtagInOptionsAPI(instance: any) { const recordEvent = (eventName: EventName) => { if (!useGoogleAnalytics()) { return; } instance["$gtag"]("event", eventName); }; return { recordEvent, }; } ``` ### 計測 `recordEvent`をuseして... ```ts <script setup lang="ts"> import { useGtag } from "~/composable/gtag"; const { recordEvent } = useGtag(); </script> ``` 仕込む。 ```html <v-btn class="ma-2" depressed small @click="recordEvent('show_github_source')" > <v-icon color="gray"> mdi-github </v-icon> GitHubで開く </v-btn> ``` 環境変数 `USE_GOOGLE_ANALYTICS` は `true` である必要があるため、一旦[[nuxt.config]]にベタで設定。最終的には`process.env.NODE_ENV`の値で出しわけるたり、コマンドで出し分けたりした方がいい。 ```js export default { env: { USE_GOOGLE_ANALYTICS: "yes", }, ``` これでトップページからクリック。 ![[Pasted image 20230604180125.png]] [[Chrome devtools]]から`verbose`にて[[GA4]]のイベントが作動したことが確認できる。 ![[Pasted image 20230604180149.png]] [[GA4]]のリアルタイム画面を見ると、イベントが作動したことを確認できる。 ![[Pasted image 20230604180259.png]] ## [[カスタムディメンション]]を仕込む デフォルトの[[ディメンション]]だけでは解析に必要な要件を満たさないこともあるので、[[カスタムディメンション]]を作る。 設定からカスタム定義を選択。 ![[Pasted image 20230604180457.png]] ![[Pasted image 20230604180524.png]] とりあえず[[Vuetify2]]のコンポーネント名を測定可能にする。ディメンション名には表示用の名称を、イベントパラメータにはコーディング用の名称を設定。 ![[Pasted image 20230604180643.png]] `composable/gtag.ts`も[[ディメンション]]を受け付けるように改修。 ```ts import { getCurrentInstance } from "vue"; type EventName = "show_github_source"; interface Dimensions { component: string; } const useGoogleAnalytics = (): boolean => { const a = process.env.USE_GOOGLE_ANALYTICS; return a != null && !["no", "false"].includes(a.toLowerCase()); }; export function useGtag() { const gtag = (getCurrentInstance()?.proxy as any)["$gtag"]; const recordEvent = (eventName: EventName, dimensions?: Dimensions) => { if (!useGoogleAnalytics()) { return; } gtag("event", eventName, dimensions); }; return { recordEvent, }; } export function useGtagInOptionsAPI(instance: any) { const recordEvent = (eventName: EventName, dimensions?: Dimensions) => { if (!useGoogleAnalytics()) { return; } instance["$gtag"]("event", eventName, dimensions); }; return { recordEvent, }; } ``` [[GitHub]]ソースへのリンクは`components/refer.vue`で実装しているので、Vueファイルへジャンプするリンクに先ほどと同じように仕込む。 ```html <a :href="pageUrl" target="_blank" class="button-link"> <v-btn color="green" class="ma-2 white--text" text small @click="recordEvent('show_github_source', { component: componentName })" > Vueファイル <v-icon right> mdi-vuejs </v-icon> </v-btn> </a> ``` `pages/index.vue`も書き換えておく。 ```html <a :href="item.url" target="_blank" class="button-link"> <v-btn class="ma-2" depressed small @click=" recordEvent('show_github_source', { component: item.path }) " > <v-icon color="gray"> mdi-github </v-icon> GitHubで開く </v-btn> </a> ``` 実際にクリックして[[GA4]]の管理画面を確認する。 ![[Pasted image 20230604181738.png]] しっかり取れてそう。 ![[Pasted image 20230604181800.png]] 設定などにも追加した[[カスタムディメンション]]が反映されていることを確認できた。 ![[Pasted image 20230604182116.png]] > [!caution] > 作成から48時間以内は[[カスタムディメンション]]の値が反映されないことがあるらしい。期待通り動作しない場合は時間を置くのも大事。 > [!warning] > フリーワードのような[[高基数のカスタムディメンションを設定すべきではない]]。その場合は事前に定義されている[[ディメンション]]を利用すること。 ## 本番環境でのみ計測する ここまでのコードでは独自の環境変数 `USE_GOOGLE_ANALYTICS` を使って制御しようとしていたが、これには問題があることが分かった。 - イベントしか制御できていない - そもそもベストプラクティスじゃない 調べたところ[[データフィルタ (GA4)|データフィルタ]]という仕組みを使うのがよさそう。 <div class="link-card"> <div class="link-card-header"> <img src="https://support.google.com/favicon.ico" class="link-card-site-icon"/> <span class="link-card-site-name">support.google.com</span> </div> <div class="link-card-body"> <div class="link-card-content"> <div> <p class="link-card-title">[GA4] デベロッパーのトラフィックを除外する - アナリティクス ヘルプ</p> </div> <div class="link-card-description"> デバッグモードを使用しているデベロッパーのアクティビティを除外してレポートに表示されないようにする方法デバッグモードを使用している内 </div> </div> </div> <a href="https://support.google.com/analytics/answer/13296662?sjid=12193036350109212086-AP"></a> </div> ### データフィルタの設定 管理画面から設定する。 ![[Pasted image 20230604191134.png]] 実際にトラフィックから除外するときは『フィルタの状態』を`有効`にしなければいけない。ただ、まずは実際にフィルタの対象となったかを確認するため『テスト』にした。 [[nuxt.config]]にて、`env`の項目は削除し、`NODE_ENV`の値を見て`config.debug_mode`の設定を変える。==`debug`ではないので注意。== ```js export default { modules: [ [ "@nuxtjs/google-gtag", { id: "G-XXXXXXXXXX", config: { send_page_view: false, debug_mode: process.env.NODE_ENV !== "production", }, debug: process.env.NODE_ENV !== "production", disableAutoPageTrack: false, }, ], ], ``` イベントの[[ディメンション]]に`debug_mode`がついていればOK。 ![[Pasted image 20230604192255.png]] テストは完了したので実際に除外するため、設定を変更。 ![[Pasted image 20230604192511.png]] [[DebugView (GA4)|DebugView]]を見ると、『無効』以外のケースはこうなる。 ![[Pasted image 20230604194700.png]] 『無効』だと`show_github_source`のイベントが発生しない。 ![[Pasted image 20230604194731.png]] ので `debug_mode` は効いてそう。 > [!question] > > リアルタイムでは、無効にしても`debug_mode`の[[ディメンション]]ついたまま送られてくるし、設定変えてもすべて計測される。これは期待通り? ### リアルタイムでは比較対象でフィルタリングする どうやら記録自体がされないわけでなく、あくまでメタデータがつくだけらしい。以下のサイトの説明見てもそんな気がする。 <div class="link-card"> <div class="link-card-header"> <img src="https://denorm.jp/wp-content/uploads/2022/05/cropped-denorm-800-x-800-32x32.png" class="link-card-site-icon"/> <span class="link-card-site-name">Denorm</span> </div> <div class="link-card-body"> <div class="link-card-content"> <div> <p class="link-card-title">【2022年度版】GA4の初期設定+コンバージョン設定方法 (図解付き) - Denorm</p> </div> <div class="link-card-description"> Googleによると、2023年の7月に従来のユニバーサルアナリティクス(GA3)の終了が発表されました。 2023年の7月以降はユニバーサルアナリティクスでのデータ計測ができなくなり、6ヶ月後の20... </div> </div> <img src="https://denorm.jp/wp-content/uploads/2022/05/ga4-initial-setups-head.jpg" class="link-card-image" /> </div> <a href="https://denorm.jp/ga4-initial-setups/"></a> </div> 代わりにリアルタイムで `デバッグフィルタ` に一致するリクエストをフィルタすればよさそう。比較対象を追加する。 ![[Pasted image 20230604222210.png]] [[ディメンション]]には`テストデータのフィルタ名`を選択。これは[[#データフィルタの設定]]で作成したフィルタで、フィルタの状態が『テスト』になっているものと思われる... が何も表示されない。反映に時間がかかるのか? ![[Pasted image 20230604222309.png]] 仕方ないので直接データフィルタ名を入力する。つまり `デバッグフィルタ` と。そして②の部分をクリック。 ![[Pasted image 20230604222714.png]] 画面一番右下にある『適用』ボタンを押す。これの存在に気づかず地味にはハマった。。 ![[Pasted image 20230604222816.png]] フィルタが効いている右側に何も表示されなければおそらくOKだろう。つまり、開発者のトラフィックが除外された結果のはずだ。本番で確認するともっと分かりやすそうだが。 ![[Pasted image 20230604222900.png]] > [!warning] > 本番デプロイ後に確認したが、依然として表示されなかったので、そもそもこれが間違っている気がする... フィルタの状態は`有効`にしておく。`テスト`の状態でも見た感じ変わらなかったのは謎だが、48時間以内に反映されるってだけかもしれない。 ### ソースコードの変更 `gtag.ts`の内容も変更しておく。コードレベルで[[GA4]]の利用可否を設定する必要がなくなったと思うので。 ```ts import { getCurrentInstance } from "vue"; type EventName = "show_github_source"; interface Dimensions { component?: string; fileKind?: "vue" | "test" | "test-helper" | "util"; } export function useGtag() { const gtag = (getCurrentInstance()?.proxy as any)["$gtag"]; const recordEvent = (eventName: EventName, dimensions?: Dimensions) => { gtag("event", eventName, dimensions); }; return { recordEvent, }; } export function useGtagInOptionsAPI(instance: any) { const recordEvent = (eventName: EventName, dimensions?: Dimensions) => { instance["$gtag"]("event", eventName, dimensions); }; return { recordEvent, }; } ``` ### 本番デプロイするもうまくいかない デプロイしてサイトを確認したところ `debug_mode` の[[ディメンション]]が引き続き送られてくる。つまり `debug_mode: false` が効いてなさそう。[[Chrome devtools]]にてデバッグログは出ていないため、`debug: false` は効いてそう。 公式サイトを見てみた。 <div class="link-card"> <div class="link-card-header"> <img src="https://www.gstatic.com/devrel-devsite/prod/v8384ce39f720e001fb8bd2a6f94b1084300273daaf700bffd864da68ae2d9c21/developers/images/favicon-new.png" class="link-card-site-icon"/> <span class="link-card-site-name">Google for Developers</span> </div> <div class="link-card-body"> <div class="link-card-content"> <div> <p class="link-card-title">デバッグモードを有効にする  |  Google アナリティクス 4 プロパティ  |  Google for Developers</p> </div> <div class="link-card-description"> </div> </div> <img src="https://www.gstatic.com/devrel-devsite/prod/v8384ce39f720e001fb8bd2a6f94b1084300273daaf700bffd864da68ae2d9c21/developers/images/opengraph/orange.png" class="link-card-image" /> </div> <a href="https://developers.google.com/analytics/devguides/collection/ga4/debug?hl=ja&technology=websites"></a> </div> なんと以下の記述が... > デバッグモードを無効にするには、'debug_mode' パラメータを削除します。パラメータを false に設定しても、デバッグモードが無効になることはありません。 [[nuxt.config]]は以下のようになっており... ```js config: { send_page_view: false, debug_mode: process.env.NODE_ENV !== "production", }, ``` [[@nuxtjs.google-gtag]]のコードを見ると、[以下のような記述](https://github.com/nuxt-community/google-gtag-module/blob/master/lib/plugin.js#L20)がある。 ```html gtag('config', '<%= options.id %>', <%= JSON.stringify(options.config, null, 2) %>) ``` つまり、見事に `{ debug_mode: false }`となってしまうわけで、デバッグモードが無効になっていない。 なので[[nuxt.config]]を変更する。 ```ts const isProduction = process.env.NODE_ENV === "production"; const gtagConfig = { id: "G-XXXXXXXXXX", config: { send_page_view: false, }, debug: !isProduction, disableAutoPageTrack: false, }; // debug_mode: false でもデバッグモードは有効になるため別の処理として追加している (undefinedでもいいかもだけど) // https://developers.google.com/analytics/devguides/collection/ga4/debug?hl=ja&technology=websites if (!isProduction) { gtagConfig.config.debug_mode = true; } export default { modules: [ ["@nuxtjs/google-gtag", gtagConfig], ], }; ``` [[📝@nuxtjs google-gtagでnuxt.configのmodulesにてconfig.debug_modeにfalseを指定してもデバッグモードが有効になってしまう]] にも記載済。