11

On my Next JS website I needed to implement Google Analytics (GA) and Facebook Pixel (FP), which I did according to the documentation and is working as far as I can tell. Now, I need to make everything GDPR compliant, so that only after explicitly accepting cookies, these services can send information. I am not sure whether I did this the right/optimal way, so would appreciate if someone more knowledgeable than I could have a look. I use react-cookie-consent for the popup, which adds a cookie with a boolean indicating whether cookies were accepted or declined. With the following code I want to make sure that: 1. on first visit GA and FB are not activated until accepted is clicked (see handleAccept function). 2. on subsequent visits, GA and FB are active when previously the user accepted cookies. Here is my app.js:

import "../styles/globals.css";
import CookieConsent from "react-cookie-consent";
import * as gtag from "../lib/gtag";
import * as fbq from "../lib/fpixel";
import { useEffect } from "react";
import Script from "next/script";
import { useRouter } from "next/router";

function MyApp({ Component, pageProps }) {
  // for Google analytics and Facebook tracking
  const router = useRouter();
  useEffect(() => {
    fbq.pageview();
    const handleRouteChange = (url) => {
      gtag.pageview(url);
      fbq.pageview();
    };
    router.events.on("routeChangeComplete", handleRouteChange);
    return () => {
      router.events.off("routeChangeComplete", handleRouteChange);
    };
  }, [router.events]);
  
  // for subsequent page visits
  useEffect(() => {
    if (checkConsented()) {
      window.gtag("consent", "update", {
        ad_storage: "granted",
        analytics_storage: "granted",
      });
      window.fbq("consent", "grant");
    }
  }, []);

  function handleAccept() {
    window.gtag("consent", "update", {
      ad_storage: "granted",
      analytics_storage: "granted",
    });
    window.fbq("consent", "grant");
  }

  return (
    <>
      <Script
        strategy="afterInteractive"
        src={`https://www.googletagmanager.com/gtag/js?id=${gtag.GA_TRACKING_ID}`}
      />
      <Script
        id="gtag-init"
        strategy="afterInteractive"
        dangerouslySetInnerHTML={{
          __html: `
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('consent', 'default', {
              'ad_storage': 'denied',
              'analytics_storage': 'denied'
            });
            gtag('js', new Date());
            gtag('config', '${gtag.GA_TRACKING_ID}', {
              page_path: window.location.pathname,
            });
          `,
        }}
      />
      <Script
        strategy="afterInteractive"
        dangerouslySetInnerHTML={{
          __html: `
            !function(f,b,e,v,n,t,s)
            {if(f.fbq)return;n=f.fbq=function(){n.callMethod?
            n.callMethod.apply(n,arguments):n.queue.push(arguments)};
            if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
            n.queue=[];t=b.createElement(e);t.async=!0;
            t.src=v;s=b.getElementsByTagName(e)[0];
            s.parentNode.insertBefore(t,s)}(window, document,'script',
            'https://connect.facebook.net/en_US/fbevents.js');
            fbq('consent', 'revoke');
            fbq('init', ${fbq.FB_PIXEL_ID});
          `,
        }}
      />
      <CookieConsent
        buttonText="Accept"
        enableDeclineButton
        onAccept={() => {
          handleAccept();
        }}
        declineButtonText="Decline"
      >
        We use cookies to improve your experience on our site.
      </CookieConsent>
      <Component {...pageProps} />
    </>
  );
}

// function for checking whether visitor has consented before
function checkConsented() {
  let decodedCookie = decodeURIComponent(document.cookie);
  decodedCookie = decodedCookie.split(";");
  decodedCookie = decodedCookie.find((cookie) => {
    return cookie.substring(0, 13) === "CookieConsent";
  });
  if (!decodedCookie) {
    return false;
  }
  if (decodedCookie.substring(14, 18) === "true") {
    return true;
  }
  return false;
}

export default MyApp;

Will this work for my 2 goals? And is there a better way of doing this?

4
  • Have you tested it? Is anything not working as intended? Commented Feb 19, 2022 at 16:30
  • GA seems to be working, FP we’re not sure yet, as the problem might be how we configured it. Commented Feb 20, 2022 at 17:03
  • How did you end up implementing this?
    – GMaiolo
    Commented Jul 19, 2022 at 18:27
  • Just as shown above, seems to work but I'm no expert at FP or GA. Commented Jul 24, 2022 at 19:47

1 Answer 1

-1

According to the package's docs, you can retrieve the cookie's value like this:

import CookieConsent, { Cookies, getCookieConsentValue } from "react-cookie-consent";

console.log(getCookieConsentValue());

So you could skip your checkConsented() function and just use getCookieConsentValue() instead.

Not the answer you're looking for? Browse other questions tagged or ask your own question.