【Next.js 13】環境ファイル別で Google Analytics を設定する
この記事では、Production と Staging 環境で別々の Google Analytics データストリームを利用する手順を紹介します。NextJS 特有の環境ファイルの扱い方や、NextJS 13 から正式に使える App Directory でも利用可能な設定例になります。
はじめに
NextJS における環境ファイルについて
NextJS では .env.local
.env.development
.env.production
の 3 種類の環境ファイルが用意されていますが、next start
や next build
で利用される環境ファイルは .env.production
のみです。
例えば Staging と Production 環境を用意している場合、環境ごとに next build
で Staging 用環境ファイルか Production 用環境ファイルを選べるほうが好ましいでしょう。しかし、NextJS では環境別に読み込む環境ファイルを指定することができないので、パッケージを利用する必要があります。
env-cmd を導入する
env-cmd
が環境別に環境ファイルを読み込むことを可能にしてくれます。
npm add env-cmd
このパッケージを利用して、package.yaml
を以下のように編集することで、任意の環境ファイルを指定することが可能になります。
"build": "env-cmd -f .env.prod next build",
"build:stg": "env-cmd -f .env.stg next build",
Google Analytics の設定
環境ファイルを用意する
まずは、Google Analytics GA4 のデータストリームを Production と Staging 用に用意して、測定 ID を入手します。
その後、env-cmd
で指定した環境ファイルに測定 ID を入力します。
NEXT_PUBLIC_GA_ID='G-[測定ID]'
NEXT_PUBLIC_GA_ID='G-[測定ID]'
gtag.ts を用意する
後々、測定 ID を取得したり pageview を呼び出すためのコードを用意します。
export const GA_MEASUREMENT_ID = process.env.NEXT_PUBLIC_GA_ID || "";
export const existsGaId = GA_MEASUREMENT_ID !== "";
export const pageview = (path: string) => {
window.gtag("config", GA_MEASUREMENT_ID, {
page_path: path,
});
};
ローカルで next dev
などでテスト中は Google Analytics にデータを飛ばさないので、ローカルの環境ファイルの測定 ID を空欄にすることで existsGaId が false になり、後々 Google Analytics を呼び出さないような仕組みになります。
gtag の型を定義します。
npm add -D @types/gtag.js
declare module 'gtag.js';
Google Analytics Client Component を作成する
先ほど作成した gtag.ts を用いて、Google Analytics を呼び出すための Client Component を作成します。NextJS 13 以降は、明示的に 'use client' と指定してクライアントサイドで実行するよう指定する必要があります。
'use client'
import { usePathname, useSearchParams } from 'next/navigation'
import Script from 'next/script'
import { useEffect } from 'react'
import { existsGaId, GA_MEASUREMENT_ID, pageview } from '../lib/gtag'
const GoogleAnalytics = () => {
const pathname = usePathname()
const searchParams = useSearchParams()
useEffect(() => {
if (!existsGaId) {
return
}
const url = pathname + searchParams.toString()
pageview(url)
}, [pathname, searchParams])
return (
<>
<Script
strategy='lazyOnload'
src={`https://www.googletagmanager.com/gtag/js?id=${GA_MEASUREMENT_ID}`}
/>
<Script id='gtag-init' strategy='afterInteractive'>
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GA_MEASUREMENT_ID}', {
page_path: window.location.pathname,
});
`}
</Script>
</>
)
}
export default GoogleAnalytics
layout.tsx から Google Analytics を呼び出す
最後に、app 直下の layout.tsx から Google Analytics を呼び出して、設定完了です。
import GoogleAnalytics from '@/components/GoogleAnalytics'
// 途中省略...
export default function RootLayout({ children }: { children: React.ReactNode }): JSX.Element {
return (
<html lang='en'>
<head>
<GoogleAnalytics />
</head>
<body className={zen_kaku_gothic_new.className}>{children}</body>
</html>
)
}
宣伝
ダイエット中の人を応援するために、ファミリーレストランのメニューをガチャガチャ形式で選べるネタ(?)サイトを作成しました。
カロリーを指定してメニューを選べるので、ネタで遊んでみてください!
普段は、誰でも使いやすい「筋トレ記録アプリ」を開発しておりますので、こちらも是非ご利用ください!
参照
Discussion
はじめまして!Masahiroと申します。
Next.jsのGoogle Analyticsの導入について質問があります。
今個人でアプリを作っているのですが、kazukiさんの記事を参考に作っています。
下記のコードで
<head>
内でGoogleAnalytics コンポーネントを読み込んでいるのですがchromeの検証ツールで見てみると
scriptの読み込みが
<body>
内に読み込まれてしまいます。しかし、google Analyticsは正常に計測されています(計測は本番環境のみ)
Google Analyticsを読み込んでいる場所は
app/layout.tsx
になります。本来読み込まれる場所は
<head>
で合っていますでしょうか?色々と原因を調べて見たのですが、
他に
<head>
に取り入れているのはSEO対策のMetadataのtitle
とdescription
をそれぞれのディレクトリのlayout.tsx
で書いていますがそこまで影響はないと考えています。原因などは分かりますでしょうか?
ソースコードは下記になります。
github
Masahiroさん、コメントありがとうございます!
おっしゃる通り、
<head>
で<GoogleAnalytics />
を読み込んでも実際には<body>
内で読み込まれるようです。これは
GoogleAnalytics.tsx
のnext/script
のstrategy
をlazyOnload
やafterInteractive
で指定しているからだと思われます。GitHub でも類似 Issue が過去に上がっています。
特に動作上で問題を感じていないのでこのまま運用しようと思っていますが、もし何か計測で問題があるようでしたらご指摘いただけますと幸いです!
ご返信ありがとうございます!
参考資料の共有もありがとうございます!
そういう挙動なんですね!
現状、google analyticsで計測が出来ていて、特に問題は出ていないです!
また、何か問題がありましたら相談させてください!