Next.jsReact

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)
  }, [])

参考記事

ブックマークや限定記事(予定)など

WP Kyotoサポーター募集中

WordPressやフロントエンドアプリのホスティング、Algolia・AWSなどのサービス利用料を支援する「WP Kyotoサポーター」を募集しています。
月額または年額の有料プランを契約すると、ブックマーク機能などのサポーター限定機能がご利用いただけます。

14日間のトライアルも用意しておりますので、「このサイトよく見るな」という方はぜひご検討ください。

広告ここから
広告ここまで

Related Category posts