Skip to content

Commit fbb73ce

Browse files
authored
Add Google Tag Manager integration with consent awareness (#406)
1 parent ed16cfa commit fbb73ce

File tree

2 files changed

+116
-5
lines changed

2 files changed

+116
-5
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import React, { useEffect } from 'react';
2+
import { hasConsent, onConsentChange } from '../../lib/analytics/consent-manager';
3+
4+
// Google Tag Manager ID - hardcoded for production
5+
const GTM_ID = 'GTM-M2JZHV8N';
6+
7+
declare global {
8+
interface Window {
9+
dataLayer?: any[];
10+
google_tag_manager?: any;
11+
}
12+
}
13+
14+
export function GTMProvider({ children }: { children: React.ReactNode }) {
15+
useEffect(() => {
16+
// Check initial consent status
17+
const consentGiven = hasConsent();
18+
19+
if (consentGiven) {
20+
enableGTM();
21+
}
22+
23+
// Listen for consent changes
24+
const cleanup = onConsentChange((granted) => {
25+
if (granted) {
26+
enableGTM();
27+
} else {
28+
disableGTM();
29+
}
30+
});
31+
32+
return () => {
33+
cleanup();
34+
// Clean up GTM scripts on unmount
35+
removeGTMScripts();
36+
};
37+
}, []);
38+
39+
const enableGTM = () => {
40+
if (typeof window === 'undefined') return;
41+
42+
// Check if GTM is already loaded
43+
if (document.getElementById('gtm-script')) {
44+
return;
45+
}
46+
47+
// Initialize dataLayer
48+
window.dataLayer = window.dataLayer || [];
49+
window.dataLayer.push({
50+
'gtm.start': new Date().getTime(),
51+
event: 'gtm.js'
52+
});
53+
54+
// Inject GTM script in head
55+
const script = document.createElement('script');
56+
script.id = 'gtm-script';
57+
script.async = true;
58+
script.src = `https://www.googletagmanager.com/gtm.js?id=${GTM_ID}`;
59+
60+
const firstScript = document.getElementsByTagName('script')[0];
61+
if (firstScript && firstScript.parentNode) {
62+
firstScript.parentNode.insertBefore(script, firstScript);
63+
} else {
64+
document.head.appendChild(script);
65+
}
66+
67+
// Inject noscript iframe in body
68+
const noscript = document.createElement('noscript');
69+
noscript.id = 'gtm-noscript';
70+
const iframe = document.createElement('iframe');
71+
iframe.src = `https://www.googletagmanager.com/ns.html?id=${GTM_ID}`;
72+
iframe.height = '0';
73+
iframe.width = '0';
74+
iframe.style.display = 'none';
75+
iframe.style.visibility = 'hidden';
76+
noscript.appendChild(iframe);
77+
78+
document.body.insertBefore(noscript, document.body.firstChild);
79+
};
80+
81+
const disableGTM = () => {
82+
if (typeof window === 'undefined') return;
83+
84+
// Remove GTM scripts
85+
removeGTMScripts();
86+
87+
// Clear dataLayer
88+
if (window.dataLayer) {
89+
window.dataLayer = [];
90+
}
91+
};
92+
93+
const removeGTMScripts = () => {
94+
// Remove GTM script
95+
const script = document.getElementById('gtm-script');
96+
if (script) {
97+
script.remove();
98+
}
99+
100+
// Remove noscript
101+
const noscript = document.getElementById('gtm-noscript');
102+
if (noscript) {
103+
noscript.remove();
104+
}
105+
};
106+
107+
return <>{children}</>;
108+
}

src/theme/Layout/index.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,20 @@ import React from 'react';
22
import OriginalLayout from '@theme-original/Layout';
33
import { CookieConsent } from '../../components/CookieConsent';
44
import { PostHogProvider } from '../../components/PostHogProvider';
5+
import { GTMProvider } from '../../components/GTMProvider';
56
import { IntercomProvider } from '../../components/IntercomProvider';
67
import { AnnouncementBanner } from '../../components/AnnouncementBanner';
78

89
export default function Layout(props) {
910
return (
1011
<PostHogProvider>
11-
<IntercomProvider>
12-
<AnnouncementBanner />
13-
<OriginalLayout {...props} />
14-
<CookieConsent />
15-
</IntercomProvider>
12+
<GTMProvider>
13+
<IntercomProvider>
14+
<AnnouncementBanner />
15+
<OriginalLayout {...props} />
16+
<CookieConsent />
17+
</IntercomProvider>
18+
</GTMProvider>
1619
</PostHogProvider>
1720
);
1821
}

0 commit comments

Comments
 (0)