In this comprehensive guide, you’ll learn how to integrate Google Analytics 4 (GA4) into your Next.js 14 application using the App Router and TypeScript. We’ll cover everything from basic setup to advanced tracking configurations, ensuring you get accurate analytics while maintaining optimal performance.
Why GA4 in Next.js?
- Real-time user behavior tracking
- Enhanced performance with proper script loading
- TypeScript support for better development
- Built-in SEO optimization
- Privacy compliance (GDPR, CCPA)
Prerequisites
Before starting, ensure you have:
- Next.js 14 or later installed
- Node.js version 18.17 or higher
- TypeScript configured
- Google Analytics 4 account
- Basic familiarity with App Router
Step-by-Step Installation
1. Set Up the Google Analytics Account
- Visit Google Analytics
- Create a new property or select existing one
- Set up a web data stream
- Copy your Measurement ID (G-XXXXXXXXXX)
2. Project Configuration
First, create a new Next.js project if you haven’t already:
npx create-next-app@latest my-analytics-app
cd my-analytics-app
3. Environment Setup
Create .env.local
in your project root:
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX
4. TypeScript Configuration
Create types/google-analytics.d.ts
:
interface Window {
gtag: (
command: string,
targetId: string,
config?: {
page_path?: string;
page_location?: string;
page_title?: string;
[key: string]: any;
}
) => void;
}
5. Analytics Utilities
Create utils/analytics.ts
:
export const GA_MEASUREMENT_ID = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID;
// Enhanced pageview tracking
export const pageview = (url: string, title: string) => {
if (typeof window.gtag !== 'undefined') {
window.gtag('config', GA_MEASUREMENT_ID!, {
page_path: url,
page_title: title,
page_location: window.location.href,
send_page_view: true
});
}
};
// Advanced event tracking
export const event = ({
action,
category,
label,
value,
}: {
action: string;
category: string;
label: string;
value?: number;
}) => {
if (typeof window.gtag !== 'undefined') {
window.gtag('event', action, {
event_category: category,
event_label: label,
value: value,
non_interaction: false,
timestamp: new Date().toISOString()
});
}
};
6. Analytics Component
Create components/GoogleAnalytics.tsx
:
'use client';
import Script from 'next/script';
import { usePathname, useSearchParams } from 'next/navigation';
import { useEffect } from 'react';
import { pageview } from '@/utils/analytics';
const GoogleAnalytics = () => {
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
const url = pathname + searchParams.toString();
// Delayed tracking for accurate title
setTimeout(() => {
pageview(url, document.title);
}, 100);
}, [pathname, searchParams]);
return (
<>
<Script
strategy="afterInteractive"
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID}`}
onLoad={() => {
console.log('Google Analytics loaded successfully');
}}
onError={(e) => {
console.error('Google Analytics failed to load:', e);
}}
/>
<Script
id="google-analytics"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID}', {
page_path: window.location.pathname,
cookie_flags: 'SameSite=None;Secure',
cookie_domain: window.location.hostname,
send_page_view: true
});
`,
}}
/>
</>
);
};
export default GoogleAnalytics;
7. Root Layout Integration
Update app/layout.tsx
:
import { Metadata } from 'next';
import GoogleAnalytics from '@/components/GoogleAnalytics';
export const metadata: Metadata = {
title: 'Your App Name',
description: 'Your app description for better SEO',
keywords: ['Next.js', 'Google Analytics', 'TypeScript', 'App Router'],
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
{process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID && (
<GoogleAnalytics />
)}
{children}
</body>
</html>
);
}
8. Custom Event Tracking
Example usage in any component:
import { event } from '@/utils/analytics';
export default function FeatureComponent() {
const handleClick = () => {
event({
action: 'feature_click',
category: 'engagement',
label: 'premium_feature',
value: 1
});
};
return (
<button onClick={handleClick}>
Premium Feature
</button>
);
}
Testing & Verification
- Build your application:
npm run build
npm start
- Open Google Analytics Real-Time view
- Navigate through your website
- Verify pageviews and events are tracking
Advanced Configuration
Content Security Policy
Update next.config.js
:
const nextConfig = {
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'Content-Security-Policy',
value: `
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.google-analytics.com;
img-src 'self' https://www.google-analytics.com;
connect-src 'self' https://www.google-analytics.com;
`.replace(/\s+/g, ' ').trim()
}
]
}
];
}
};
export default nextConfig;
Privacy Compliance
- Add Cookie Consent:
const hasConsent = () => {
// Implement your consent check logic
return localStorage.getItem('analytics-consent') === 'true';
};
// Only load GA if consent is given
{hasConsent() && <GoogleAnalytics />}
- Update Privacy Policy
- Implement Data Anonymization
- Add Cookie Banner
Troubleshooting
Common issues and solutions:
- Analytics Not Loading
- Check browser console for errors
- Verify Measurement ID
- Check CSP headers
- Missing Page Views
- Confirm script loading order
- Check route change handlers
- Verify consent management
- TypeScript Errors
- Update type definitions
- Check import paths
- Verify tsconfig settings
Best Practices
- Performance
- Use
strategy="afterInteractive"
- Implement lazy loading
- Optimize tracking code
- Error Handling
- Add Script onError handlers
- Implement fallbacks
- Log tracking failures
- Maintenance
- Regular version updates
- Monitor analytics health
- Audit tracking events
Additional Resources
Conclusion
You now have a production-ready Google Analytics 4 implementation in your Next.js application. This setup provides accurate tracking while maintaining performance and privacy compliance.