Skip to content

Commit de61818

Browse files
authored
fix: gtm preview mode (#268)
1 parent fa59318 commit de61818

File tree

5 files changed

+77
-31
lines changed

5 files changed

+77
-31
lines changed

apps/blog/src/app/providers/tracking/cookie-consent.config.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import type { CookieConsentConfig } from 'vanilla-cookieconsent';
22

3+
declare global {
4+
interface Window {
5+
dataLayer: {
6+
push: (...args: any[]) => void;
7+
};
8+
}
9+
}
10+
311
export const cookieConsentConfig = {
412
categories: {
513
necessary: {
@@ -14,11 +22,18 @@ export const cookieConsentConfig = {
1422
enabled: false,
1523
readOnly: false,
1624
},
25+
ads: {},
26+
},
27+
onConsent: () => {
28+
window.dataLayer.push({ event: 'consent_update' });
29+
window.dispatchEvent(new CustomEvent('ptupdate'));
1730
},
1831
onChange: () => {
32+
window.dataLayer.push({ event: 'consent_update_change' });
1933
window.dispatchEvent(new CustomEvent('ptupdate'));
2034
},
2135
onFirstConsent: () => {
36+
window.dataLayer.push({ event: 'consent_update_first' });
2237
window.dispatchEvent(new CustomEvent('ptupdate'));
2338
},
2439
language: {

apps/blog/src/app/providers/tracking/tracking.provider.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';
22

33
import {
4+
consent,
5+
gtag,
46
gtmScript,
5-
metaPixel,
6-
metaScript,
77
provideTracking,
88
} from '@angular-love/blog/tracking/feature';
99

@@ -14,6 +14,10 @@ export const provideAppTracking = (): EnvironmentProviders => {
1414
provideTracking({
1515
partyTown: {
1616
partyTown: {
17+
forward: [
18+
['dataLayer.push', { preserveBehavior: true }],
19+
['fbq', { preserveBehavior: true }],
20+
],
1721
enabled: true,
1822
reverseProxy: 'https://reverse.contact-ef8.workers.dev/',
1923
proxiedHosts: [
@@ -27,8 +31,14 @@ export const provideAppTracking = (): EnvironmentProviders => {
2731
'static.ads-twitter.com',
2832
],
2933
},
30-
scripts: [gtmScript('GTM-5XNT5NS'), metaScript('284876369340184')],
31-
pixels: [metaPixel('284876369340184')],
34+
scripts: [
35+
gtag(),
36+
gtmScript('GTM-5XNT5NS'),
37+
consent('ads', 'ad_storage', 'granted'),
38+
consent('ads', 'ad_storage', 'denied'),
39+
consent('analytics', 'analytics_storage', 'granted'),
40+
consent('analytics', 'analytics_storage', 'denied'),
41+
],
3242
},
3343
cookieConsent: cookieConsentConfig,
3444
}),

apps/blog/src/environments/environment.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { provideConfig } from '@angular-love/shared/config';
22

33
import { AppEnvironment } from './app-environment';
4+
import { provideAppTracking } from "../app/providers/tracking";
45

56
export const environment: AppEnvironment = {
67
baseUrl: process.env.AL_BASE_URL,
@@ -16,5 +17,6 @@ export const environment: AppEnvironment = {
1617
giscusCategory: process.env.AL_GISCUS_CATEGORY,
1718
giscusCategoryId: process.env.AL_GISCUS_CATEGORY_ID,
1819
}),
20+
provideAppTracking(),
1921
],
2022
};
Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
import { PartyTownScriptFactory } from './partytown.service';
22

3+
export const gtag = (): PartyTownScriptFactory => (gtmScript) => {
4+
gtmScript.textContent = `
5+
window.dataLayer = window.dataLayer || [];
6+
window.gtag = function gtag(){dataLayer.push(arguments);}
7+
8+
gtag('consent', 'default', {
9+
'ad_storage': 'denied',
10+
'analytics_storage': 'denied'
11+
});
12+
`;
13+
return gtmScript;
14+
};
15+
316
export const gtmScript =
417
(id: string): PartyTownScriptFactory =>
518
(gtmScript) => {
6-
gtmScript.setAttribute('type', 'text/plain');
7-
gtmScript.setAttribute('data-type', 'text/partytown');
8-
gtmScript.setAttribute('data-category', 'analytics');
919
gtmScript.textContent = `(function (w, d, s, l, i) {
1020
w[l] = w[l] || [];
1121
w[l].push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
@@ -16,3 +26,23 @@ export const gtmScript =
1626
})(window, document, 'script', 'dataLayer', '${id}');`;
1727
return gtmScript;
1828
};
29+
30+
export const consent =
31+
(
32+
category: 'analytics' | 'ads',
33+
consentType: 'ad_storage' | 'analytics_storage',
34+
status: 'granted' | 'denied',
35+
): PartyTownScriptFactory =>
36+
(gtmScript) => {
37+
gtmScript.setAttribute('type', 'text/plain');
38+
gtmScript.setAttribute(
39+
'data-category',
40+
status === 'granted' ? category : `!${category}`,
41+
);
42+
gtmScript.textContent = `
43+
gtag('consent', 'update', {
44+
'${consentType}': '${status}'
45+
});
46+
`;
47+
return gtmScript;
48+
};

libs/blog/tracking/feature/src/lib/partytown/partytown.service.ts

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import {
88
makeEnvironmentProviders,
99
PLATFORM_ID,
1010
} from '@angular/core';
11-
import { NavigationStart, Router } from '@angular/router';
12-
import { filter, first, tap } from 'rxjs';
1311

1412
/**
1513
* Credits https://github.com/find-ida/angular-ssr-partytown
@@ -19,7 +17,7 @@ export type PartyTownConfig = {
1917
enabled: boolean;
2018
debug?: boolean;
2119
basePath?: string;
22-
forward?: string[];
20+
forward?: (string | [string, { preserveBehavior: boolean }])[];
2321
reverseProxy?: string;
2422
proxiedHosts?: string[];
2523
};
@@ -44,7 +42,7 @@ export const providePartyTown = (
4442
enabled: config.partyTown?.enabled ?? false,
4543
debug: config.partyTown?.debug ?? false,
4644
basePath: config.partyTown?.basePath ?? '/~partytown',
47-
forward: config.partyTown?.forward ?? ['dataLayer.push', 'fbq'],
45+
forward: config.partyTown?.forward ?? [],
4846
reverseProxy: config.partyTown?.reverseProxy ?? '',
4947
proxiedHosts: config.partyTown?.proxiedHosts ?? [],
5048
},
@@ -79,28 +77,14 @@ export type PartyTownPixelFactory = (img: HTMLImageElement) => HTMLImageElement;
7977
export class PartyTownService {
8078
private readonly _config = inject(PARTY_TOWN_CONFIG, { optional: true });
8179
private readonly _document = inject(DOCUMENT);
82-
private readonly _router = inject(Router);
8380

8481
init(): void {
8582
if (this._config?.partyTown?.enabled) {
86-
this._router.events
87-
.pipe(
88-
filter((ev): ev is NavigationStart => ev instanceof NavigationStart),
89-
tap({
90-
next: (asd) => {
91-
this.initPartyTownScript();
92-
const disablePartyTown = asd.url.includes('gtm_debug=');
83+
this.initPartyTownScript();
84+
const disablePartyTown = window.location.search.includes('gtm_debug=');
9385

94-
this.initScripts(
95-
disablePartyTown,
96-
...(this._config?.scripts ?? []),
97-
);
98-
this.initPixels(...(this._config?.pixels ?? []));
99-
},
100-
}),
101-
first(),
102-
)
103-
.subscribe();
86+
this.initScripts(disablePartyTown, ...(this._config?.scripts ?? []));
87+
this.initPixels(...(this._config?.pixels ?? []));
10488
}
10589
}
10690

@@ -111,11 +95,16 @@ export class PartyTownService {
11195
scripts.forEach((script) => {
11296
const scriptElement = this._document.createElement('script');
11397
const _script = script(scriptElement);
114-
if (disablePartyTown) {
115-
_script.removeAttribute('data-type');
98+
if (!disablePartyTown) {
99+
if (_script.type) {
100+
_script.setAttribute('data-type', 'text/partytown');
101+
} else {
102+
_script.setAttribute('type', 'text/partytown');
103+
}
116104
}
117105

118106
this._document.head.appendChild(_script);
107+
window.dispatchEvent(new CustomEvent('ptupdate'));
119108
});
120109
}
121110

0 commit comments

Comments
 (0)