Next.jsアプリにGoogle Analytics 4のトラッキングを設定する(TypeScript版)
GA4への切り替えのアナウンスやブログ記事が増えてきました。 npmを探せばよしなにしてくれるライブラリもありそうで、実運用ではこちらを使う方が効率が良いかもしれません。 今回はGA4でのトラッキング方法の勉強もかねて、 […]
目次
GA4への切り替えのアナウンスやブログ記事が増えてきました。
npmを探せばよしなにしてくれるライブラリもありそうで、実運用ではこちらを使う方が効率が良いかもしれません。
今回はGA4でのトラッキング方法の勉強もかねて、あえて手組してみたので、その覚書です。
型情報のインストール
TypeScriptで実装する場合、gtag()
の型情報を手に入れておくと便利です。
npm i -D @types/gtag.js
ファイルを作成してグローバル変数で使えるようにします。(これはもしかするといらないかも)
types/gtag.d.ts
/// <reference types="gtag.js" />
declare module 'gtag.js';
IDEがgtag
で補完するようになれば、OKです。
gtag.jsの読み込み
続いてGA4のトラッキングに使うJSファイルを読み込みましょう。
pages/_app.tsx
に定義します。
import type { AppProps } from 'next/app'
import Script from 'next/script'
const GA_TRACKING_ID = process.env.NEXT_PUBLIC_GA_TRACKING_ID as sting // 'G-XXXXX'
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<Script
async
strategy='lazyOnload'
src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`}
/>
<Script strategy='afterInteractive'>
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GA_TRACKING_ID}', {
page_path: window.location.pathname,
});
`}
</Script>
<Component {...pageProps} />
</>
)
}
export default MyApp
next/script
を利用する形に変わっていますが、よくよく読むとAnalyticsの設定画面で表示されるコードとほぼ同じです。
<script async src="https://www.googletagmanager.com/gtag/js?id=xxxx"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-xxxx');
</script>
ページの遷移時にイベントを送信する
Analyticsの設定画面で表示されるコードのうち、ページビューに相当するイベントを送信している処理はgtag('config', 'G-xxxx');
です。
この関数を、Next.jsのルーティング機能で遷移した場合にも発火するようにpages/_apps.tsx
に実装しましょう。
const router = useRouter()
useEffect(() => {
const handleRouteChange = (url: string) => {
if (!window) return
window.gtag('config', GA_TRACKING_ID, {
page_location: url,
})
}
router.events.on('routeChangeComplete', handleRouteChange)
router.events.on('hashChangeComplete', handleRouteChange)
return () => {
router.events.off('routeChangeComplete', handleRouteChange)
router.events.off('hashChangeComplete', handleRouteChange)
}
}, [router.events])
window
のnullチェックは省略してもよいかもしれません。SSRまわりで事故る印象があるため、個人的に手癖として追加しています。
別ファイルにまとめてみた
管理しやすさを考えると、以下のような1コンポーネントにまとめた方が良いかもしれません。
export const GATracking: FC<{
trackingId?: string
}> = ({trackingId}) => {
const router = useRouter()
const { events } = router || {}
useEffect(() => {
const handleRouteChange = (url: string) => {
if (!window) return
window.gtag('config', '${trackingId}', {
page_path: url,
});
}
events.on('routeChangeComplete', handleRouteChange)
events.on('hashChangeComplete', handleRouteChange)
return () => {
events.off('routeChangeComplete', handleRouteChange)
events.off('hashChangeComplete', handleRouteChange)
}
}, [events])
return (
<>
<Script
async
strategy='lazyOnload'
src={`https://www.googletagmanager.com/gtag/js?id=${trackingId}`}
/>
<Script strategy='afterInteractive'>
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${trackingId}', {
page_path: window.location.pathname,
});
`}
</Script>
</>
)
}
SSRがあるアプリなどで、window
を使いたくない場合は、useCallback
などで関数に押し込めたものをHookにするのも手だと思います。
const putEvent = useCallback((eventName: Gtag.EventNames, params: Gtag.EventParams) => {
if (!window) return
window.gtag('event', eventName, params)
}, [])
参考記事
- https://dev.to/asross311/strongly-typed-ga4-with-nextjs-part-ii-danger-zone-26f
- https://dev.to/asross311/strongly-typed-google-analytics-v4-with-nextjs-4g13
- https://github.com/vercel/next.js/blob/canary/examples/with-google-analytics/pages/_app.js
- https://developers.google.com/tag-platform/devguides/add-tag?solution=gtag