Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

Google Analytics in Next.js 14: GDPR-Compliant Consent Banner with Cookies

Ready to add Google Analytics to your Next.js 14 app without feeling like a creepy data stalker? Let’s whip up a GDPR-compliant consent banner faster than you can say “cookie monster”! 🍪

Why Bother with Consent?

Before we dive in, let’s address the elephant in the room: GDPR compliance. It’s not just about avoiding hefty fines; it’s about respecting your users’ privacy. Plus, it’s a great excuse to add a fancy banner to your site. Win-win!

What You’ll Need

  • Next.js 14 (because you’re living on the edge)
  • TailwindCSS (for that sweet, responsive design)
  • A Google Analytics 4 account (time to graduate from GA3, folks)

Got all that? Great! Let’s cook up some code.

Step 1: Setting Up Google Analytics

First, let’s get cozy with Google Analytics. Install these packages:

npm install client-only @types/gtag.js --save-dev

Now, grab your GA4 Measurement ID (it looks like G-XXXXXXXXXX) from your Google Analytics dashboard. You’ll need it soon.

Step 2: The Google Analytics Component

Create a new file components/GoogleAnalytics.tsx:

'use client';

import Script from 'next/script';
import { usePathname, useSearchParams } from 'next/navigation';
import { useEffect } from 'react';

const pageview = (GA_MEASUREMENT_ID: string, url: string) => {
  window.gtag('config', GA_MEASUREMENT_ID, { page_path: url });
};

export default function GoogleAnalytics({ GA_MEASUREMENT_ID }: { GA_MEASUREMENT_ID: string }) {
  const pathname = usePathname();
  const searchParams = useSearchParams();

  useEffect(() => {
    const url = pathname + searchParams.toString();
    pageview(GA_MEASUREMENT_ID, url);
  }, [pathname, searchParams, GA_MEASUREMENT_ID]);

  return (
    <>
      <Script
        strategy="afterInteractive"
        src={`https://www.googletagmanager.com/gtag/js?id=${GA_MEASUREMENT_ID}`}
      />
      <Script
        id="google-analytics"
        strategy="afterInteractive"
        dangerouslySetInnerHTML={{
          __html: `
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());

            gtag('consent', 'default', {
              'analytics_storage': 'denied'
            });
            
            gtag('config', '${GA_MEASUREMENT_ID}', {
              page_path: window.location.pathname,
            });
          `,
        }}
      />
    </>
  );
}

This component loads GA scripts and sets default consent to “denied” because we’re good privacy citizens.

Step 3: The Cookie Consent Banner

Now for the star of the show, our cookie consent banner. Create components/CookieBanner.tsx:

'use client';

import { useState, useEffect } from 'react';
import Link from 'next/link';
import { Cookie } from 'lucide-react';

const getLocalStorage = (key: string, defaultValue: any) => {
  const stickyValue = localStorage.getItem(key);
  return stickyValue !== null && stickyValue !== 'undefined'
    ? JSON.parse(stickyValue)
    : defaultValue;
};

const setLocalStorage = (key: string, value: any) => {
  localStorage.setItem(key, JSON.stringify(value));
};

export default function CookieBanner() {
  const [cookieConsent, setCookieConsent] = useState<boolean | undefined>();
  const [show, setShow] = useState<boolean>(false);

  useEffect(() => {
    const storedCookieConsent = getLocalStorage('cookie_consent', null);
    setCookieConsent(storedCookieConsent);

    const timer = setTimeout(() => setShow(true), 3000);
    return () => clearTimeout(timer);
  }, []);

  useEffect(() => {
    const newValue = cookieConsent ? 'granted' : 'denied';
    window.gtag('consent', 'update', {
      analytics_storage: newValue,
    });
    setLocalStorage('cookie_consent', cookieConsent);
  }, [cookieConsent]);

  if (!show || cookieConsent !== undefined) return null;

  return (
    <div className="fixed bottom-0 left-2 right-2 mx-auto mb-2 flex max-w-max flex-col items-center justify-between gap-4 rounded-xl border border-neutral-700 bg-neutral-800 px-3 py-3 shadow sm:max-w-sm sm:flex-row sm:right-auto lg:max-w-lg lg:gap-5 md:px-4 lg:py-4">
      <div className="flex flex-col items-center gap-2 lg:flex-row">
        <Cookie className="mt-5 text-[#f1ff81] lg:mt-0" />
        <div className="w-fit text-center font-mono text-sm text-white lg:text-left">
          <Link href="/info/cookies">
            <p>
              We use <span className="font-bold text-[#f1ff81]">cookies</span> to
              analyze site traffic and personalize content.
            </p>
          </Link>
        </div>
      </div>
      <div className="mt-3 flex gap-2 lg:mt-0 lg:flex-1 lg:text-sm">
        <button
          className="rounded-full border border-neutral-700 px-5 py-2 text-gray-300 tracking-tight"
          onClick={() => setCookieConsent(false)}
        >
          Decline
        </button>
        <button
          className="rounded-full bg-white px-5 py-2 font-medium text-neutral-700 tracking-tight"
          onClick={() => setCookieConsent(true)}
        >
          Allow
        </button>
      </div>
    </div>
  );
}

This banner is like a polite butler, asking for permission before serving up those delicious analytics cookies.

Step 4: Putting It All Together

Update your app/layout.tsx to include both components:

import { Suspense } from 'react';
import GoogleAnalytics from '@/components/GoogleAnalytics';
import CookieBanner from '@/components/CookieBanner';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <Suspense>
          <GoogleAnalytics GA_MEASUREMENT_ID="G-YOUR_MEASUREMENT_ID" />
        </Suspense>
      </head>
      <body>
        {children}
        <Suspense>
          <CookieBanner />
        </Suspense>
      </body>
    </html>
  );
}

The Grand Finale

And there you have it! You’ve just set up a GDPR-compliant Google Analytics setup with a snazzy consent banner in your Next.js 14 app. Here’s what we accomplished:

  1. Set up Google Analytics with consent mode
  2. Created a responsive, GDPR-compliant cookie banner
  3. Implemented user preference storage
  4. Integrated everything into your Next.js app

Now you can track your users guilt-free! Remember, with great power comes great responsibility. Use your newfound analytics wisely, and may your bounce rates be ever in your favor! 📊🚀

Leave a Reply

Your email address will not be published. Required fields are marked *