[[🦉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を指定してもデバッグモードが有効になってしまう]] にも記載済。