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?