Next.jsにGoogle Analyticsを導入

App Routerを利用するケースでのNext.jsにGoogle Analyticsを導入する方法を説明します。

2025-7-2
バージョン
  • next: 14.0.2
  • react: 18.2.0
  • @types/gtag.js: 0.0.12

App Routerを利用。

環境変数を追加

$ echo "NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=XXXXXXXXX" >> .env.local
$ echo "NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=XXXXXXXXX" >> .env.production

導入

型定義を追加

// yarn
$ yarn add -D @types/gtag.js

// npm
$ npm i --save-dev @types/gtag.js

pageview用の関数を定義

gtag.ts
export const GA_TRACKING_ID = process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_ID || "";
export const existsGaId = GA_TRACKING_ID !== "";

export const pageview = (path: string) => {
  window.gtag("config", GA_TRACKING_ID, {
    page_path: path,
  });
};

スクリプトを追加

CustomScript.tsx
"use client";

import { usePathname, useSearchParams } from "next/navigation";
import Script from "next/script";
import { useEffect } from "react";
import { existsGaId, GA_TRACKING_ID, pageview } from "@/gtag";

export const CustomScript = () => {
  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_TRACKING_ID}`}
        async
      />
      <Script id="gtag-init" 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>
    </>
  );
};

スクリプトを読み込む

layout.tsx
import React, { ReactNode, Suspense } from "react";
import { CustomScript } from "@/CustomScript";

const Layout = async ({ children }: { children: ReactNode }) => {
  return (
    <html lang="ja">
      {process.env.NODE_ENV === "production" && (
        <head>
          <Suspense>
            <CustomScript />
          </Suspense>
        </head>
      )}
      <body>{children}</body>
    </html>
  );
};