Next.jsAnalyticsSEO
GA4 vs GTM vs G Tag: Understanding Google Analytics Tools for Next.js
A comprehensive guide to GA4, GTM, and gtag.js — what they are, how they work together, and how to implement them in Next.js.
May 4, 202510 min—views
When diving into analytics for your Next.js application, you’ll encounter three main Google tools: GA4, GTM, and G tag. Let’s break down what they are, how they work together, and exactly how to implement them.
Understanding the Google Analytics ecosystem
- GA4 — the analytics platform that stores, processes, and visualizes your data
- gtag.js — the JavaScript library that sends data from your site to Google
- GTM — a tag manager so you can control multiple tracking tags without redeploying
Think of them as: GA4 = dashboard, gtag.js = data pipeline, GTM = control center.
Option 1: Direct GA4 with gtag.js
Best for simple websites with basic tracking needs.
jsxapp/layout.jsx
import Script from "next/script";
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<Script
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GA_ID}`}
strategy="afterInteractive"
/>
<Script id="google-analytics" strategy="afterInteractive">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${process.env.NEXT_PUBLIC_GA_ID}');
`}
</Script>
</head>
<body>{children}</body>
</html>
);
}Option 2: Advanced setup with GTM
Best for complex tracking, multiple marketing tags, or frequent changes.
jsxapp/layout.jsx
import Script from "next/script";
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<Script id="gtm-script" strategy="afterInteractive">
{`
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','${process.env.NEXT_PUBLIC_GTM_ID}');
`}
</Script>
</head>
<body>
<noscript>
<iframe
src={`https://www.googletagmanager.com/ns.html?id=${process.env.NEXT_PUBLIC_GTM_ID}`}
height="0"
width="0"
style={{ display: "none", visibility: "hidden" }}
/>
</noscript>
{children}
</body>
</html>
);
}Tracking page views in Next.js
Since Next.js uses client-side routing, manually track page views after the initial load:
jsxcomponents/analytics-tracker.jsx
"use client";
import { usePathname, useSearchParams } from "next/navigation";
import { useEffect } from "react";
export function AnalyticsTracker() {
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
if (typeof window.gtag === "function") {
window.gtag("event", "page_view", {
page_path: pathname + searchParams.toString(),
});
}
}, [pathname, searchParams]);
return null;
}Data layer events with GTM
jsxcomponents/buy-button.jsx
"use client";
export function BuyButton({ productId, price, name }) {
const handlePurchase = () => {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: "purchase",
ecommerce: {
transaction_id: generateOrderId(),
value: price,
currency: "USD",
items: [{ item_id: productId, item_name: name, price }],
},
});
};
return <button onClick={handlePurchase}>Buy Now</button>;
}Consent-aware loading
Only load analytics after the user consents:
jsxcomponents/analytics.jsx
"use client";
import { useState, useEffect } from "react";
import Script from "next/script";
export function Analytics() {
const [consent, setConsent] = useState(false);
useEffect(() => {
setConsent(localStorage.getItem("analyticsConsent") === "true");
}, []);
if (!consent) return null;
return (
<>
<Script
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GA_ID}`}
strategy="afterInteractive"
/>
<Script id="google-analytics" strategy="afterInteractive">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${process.env.NEXT_PUBLIC_GA_ID}');
`}
</Script>
</>
);
}When to use which
- Direct GA4 — simple pageviews/events, you own the code, rare changes
- GTM — multiple marketing tags, non-devs update tracking, complex campaigns
Start simple with gtag.js. Move to GTM when your tracking needs grow — and always respect consent.