Reputation: 2986
I integrated google analytics to next.js - to say, I followed these guides:
Which works just fine, now the issue is I need to allow loading google analytics only after cookie consent, I store my cookie consent in localStorage at the moment simply in the format:
checkboxValues = {
necessary: true,
statistics: false,
marketing: false,
};
Now I need to check localStorage.getItem('acceptCookies');
and make sure google analytics is loaded only when statistics: true
.
import Document, { Html, Head, Main, NextScript } from "next/document";
import { GA_TRACKING_ID } from "../utils/gtag";
export default class MyDocument extends Document {
render() {
return (
<Html>
<Head>
{/* Global Site Tag (gtag.js) - Google Analytics */}
<script
async
src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`}
/>
<script
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GA_TRACKING_ID}', {
page_path: window.location.pathname,
});
`
}}
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
for me to check for the localStorage before render()
is not possible as localStorage is only available after componentDidMount
. Stuck with this, any direction?
Upvotes: 4
Views: 5398
Reputation: 975
As per this blog post you can create a cookie banner component which updates the Google Analytics consent:
'use client';
import { getLocalStorage, setLocalStorage } from '@/lib/storageHelper';
import { useState, useEffect } from 'react';
export default function CookieBanner(){
const [cookieConsent, setCookieConsent] = useState(false);
useEffect (() => {
const storedCookieConsent = getLocalStorage("cookie_consent", null)
setCookieConsent(storedCookieConsent)
}, [setCookieConsent])
useEffect(() => {
const newValue = cookieConsent ? 'granted' : 'denied'
window.gtag("consent", 'update', {
'analytics_storage': newValue
});
setLocalStorage("cookie_consent", cookieConsent)
}, [cookieConsent]);
return (
...
Just call onClick={() => setCookieConsent(true)}
when the user accepts cookie consent.
Update: storageHelper looks like this:
import "client-only";
export function getLocalStorage(key: string, defaultValue:any){
const stickyValue = localStorage.getItem(key);
return (stickyValue !== null && stickyValue !== 'undefined')
? JSON.parse(stickyValue)
: defaultValue;
}
export function setLocalStorage(key: string, value:any){
localStorage.setItem(key, JSON.stringify(value));
}
Upvotes: 1
Reputation: 5208
there are built-in consent functions: https://developers.google.com/gtagjs/devguide/consent
so you in your case add
gtag('consent', 'default', {
'analytics_storage': 'denied'
});
So it'll look something like:
<script
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
//this defaults to denying
gtag('consent', 'default', {
'analytics_storage': 'denied'
});
gtag('js', new Date());
//check for consent, you'll need to write your own function here, but you get the idea
if(consentGranted){
gtag('consent', 'update', {
'analytics_storage': 'granted'
});
}
gtag('config', '${GA_TRACKING_ID}', {
page_path: window.location.pathname,
});
`
}}
/>
Alternatively, you could just wrap the "config" to line in the similar consent line, though this might not be as a "complete" solution as it only stops the pageview:
if(consent){
gtag('config', '${GA_TRACKING_ID}', {
page_path: window.location.pathname,
});
}
Upvotes: 1