I’m having trouble with Google Analytics in my Next.js 14.0.4 project. When my page loads, I get an error saying window.gtag is not a function.
The problem started after upgrading to Next.js 14. I’m using @types/gtag.js and client-only packages. The issue seems to be that gtag isn’t loading properly, which breaks my cookie consent system.
Here’s my main layout structure:
<html lang='en'>
<head>
<AnalyticsScript />
</head>
<body className='main-container'>
<NotificationToast />
<HeaderNav />
<main className='content-wrapper'>
{children}
</main>
<FooterSection />
<ConsentModal />
</body>
</html>
And my consent component:
'use client';
type CookieSettings = {
advertising: boolean
tracking: boolean
}
export default function ConsentModal() {
const [userConsent, setUserConsent] = useState<CookieSettings>();
useEffect(() => {
const savedConsent = getStoredValue("user_consent", null);
setUserConsent(savedConsent);
}, []);
useEffect(() => {
const adConsent = userConsent?.advertising ? 'granted' : 'denied'
const trackingConsent = userConsent?.tracking ? 'granted' : 'denied'
if (typeof window !== 'undefined' && typeof window.gtag !== 'undefined') {
window.gtag("consent", 'update', {
'analytics_storage': trackingConsent,
'ad_storage': adConsent,
});
} else {
console.warn("gtag function not available");
}
storeValue("user_consent", userConsent);
}, [userConsent]);
return (
<div className={`consent-banner ${userConsent != null ? "hidden" : "flex"}`}>
<div className='banner-content'>
<p>We use cookies for analytics</p>
<div className='button-group'>
<Button onClick={() => setUserConsent({ advertising: false, tracking: true })}>
Essential Only
</Button>
<Button onClick={() => setUserConsent({ advertising: true, tracking: true })}>
Accept All
</Button>
</div>
</div>
</div>
)
}
Even with the conditional check, gtag never becomes available. How can I make sure Google Analytics loads properly before trying to use it?