ro ko
ro ko

Reputation: 2986

Allow google analytics to load only after consented in Next.js

I integrated google analytics to next.js - to say, I followed these guides:

  1. https://frontend-digest.com/using-nextjs-with-google-analytics-and-typescript-620ba2359dea
  2. https://github.com/vercel/next.js/tree/canary/examples/with-google-analytics

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

Answers (2)

Ryan Gaudion
Ryan Gaudion

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

XTOTHEL
XTOTHEL

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

Related Questions