How to Add Google Analytics to Next.js 14 (App Router)
Google Analytics in Next.js App Router requires a specific setup — the old _app.js pattern doesn't exist. Here's the correct implementation that handles page views on navigation without double-counting.
Setup
npm install @next/third-parties
@next/third-parties is the official Next.js package for third-party scripts. For GA4, it handles script loading, page view tracking, and performance optimization.
Add to Root Layout
app/layout.tsx:
import { GoogleAnalytics } from '@next/third-parties/google';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang='en'>
<body>{children}</body>
{process.env.NODE_ENV === 'production' && (
<GoogleAnalytics gaId={process.env.NEXT_PUBLIC_GA_ID!} />
)}
</html>
);
}
.env.local:
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
The NODE_ENV === 'production' check prevents GA events from firing in development. Without it, your dev traffic pollutes your analytics data.
Page View Tracking
GoogleAnalytics from @next/third-parties handles page views automatically on client-side navigation — no extra code needed.
Custom Events
import { sendGAEvent } from '@next/third-parties/google';
// Track a button click
function PricingButton() {
return (
<button
onClick={() => sendGAEvent('event', 'purchase_intent', {
plan: 'pro',
location: 'pricing_page'
})}
>
Get Pro
</button>
);
}
// Track a conversion
function handleCheckoutSuccess() {
sendGAEvent('event', 'purchase', {
currency: 'USD',
value: 99,
items: [{ item_id: 'ai-saas-starter', item_name: 'AI SaaS Starter Kit' }]
});
}
Alternative: Script Tag Approach
If you need more control over loading behavior:
import Script from 'next/script';
export default function RootLayout({ children }: { children: React.ReactNode }) {
const gaId = process.env.NEXT_PUBLIC_GA_ID;
return (
<html lang='en'>
<body>
{children}
{gaId && process.env.NODE_ENV === 'production' && (
<>
<Script
src={`https://www.googletagmanager.com/gtag/js?id=${gaId}`}
strategy='afterInteractive'
/>
<Script id='ga-init' strategy='afterInteractive'>
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${gaId}', { page_path: window.location.pathname });
`}
</Script>
</>
)}
</body>
</html>
);
}
Use strategy='afterInteractive' to load GA after the page is interactive — this prevents GA from blocking page render.
PostHog: The Better Alternative for AI SaaS
For AI SaaS specifically, PostHog is often a better fit than GA4:
- Session recordings show exactly how users interact with your AI features
- Feature flags let you A/B test AI prompts or UI variants
- Funnel analysis tracks conversion from free → paid
- Open source, self-hostable option available
npm install posthog-js
// app/providers.tsx
'use client';
import posthog from 'posthog-js';
import { PostHogProvider } from 'posthog-js/react';
import { useEffect } from 'react';
export function PHProvider({ children }: { children: React.ReactNode }) {
useEffect(() => {
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
api_host: '/ingest', // proxy through Next.js to avoid ad blockers
capture_pageview: false, // manual control
});
}, []);
return <PostHogProvider client={posthog}>{children}</PostHogProvider>;
}
Pre-Configured in the Starter Kit
The AI SaaS Starter Kit ships with GA4 + PostHog both pre-configured in the root layout — toggle each via env vars.
Atlas — building at whoffagents.com
Top comments (0)