Skip to content

Commit 7691064

Browse files
authored
refactor(blog): streamline cookie consent flow (#431)
1 parent ef2cd14 commit 7691064

File tree

10 files changed

+323
-196
lines changed

10 files changed

+323
-196
lines changed

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

Lines changed: 206 additions & 143 deletions
Large diffs are not rendered by default.

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

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

33
import {
4-
consentUpdateScript,
54
gtmScript,
6-
initialConsentScript,
75
metaPixel,
86
metaScript,
97
provideTracking,
@@ -33,15 +31,7 @@ export const provideAppTracking = (): EnvironmentProviders => {
3331
],
3432
},
3533
cookieConsent: cookieConsentConfig,
36-
scripts: [
37-
initialConsentScript(),
38-
gtmScript('GTM-5XNT5NS'),
39-
consentUpdateScript('ads', 'ad_storage', 'granted'),
40-
consentUpdateScript('ads', 'ad_storage', 'denied'),
41-
consentUpdateScript('analytics', 'analytics_storage', 'granted'),
42-
consentUpdateScript('analytics', 'analytics_storage', 'denied'),
43-
metaScript('284876369340184'),
44-
],
34+
scripts: [gtmScript('GTM-5XNT5NS'), metaScript('284876369340184')],
4535
pixels: [metaPixel('284876369340184')],
4636
}),
4737
]);
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
export * from './lib/tracking';
22
export * from './lib/scripts';
3+
export * from './lib/const';
4+
export * from './lib/cookie-consent';
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export const CATEGORIES = {
2+
NECESSARY: 'necessary',
3+
ANALYTICS: 'analytics',
4+
ADVERTISEMENT: 'advertisement',
5+
FUNCTIONALITY: 'functionality',
6+
SECURITY: 'security',
7+
};
8+
9+
export const SERVICES = {
10+
AD_STORAGE: 'ad_storage',
11+
AD_USER_DATA: 'ad_user_data',
12+
AD_PERSONALIZATION: 'ad_personalization',
13+
ANALYTICS_STORAGE: 'analytics_storage',
14+
FUNCTIONALITY_STORAGE: 'functionality_storage',
15+
PERSONALIZATION_STORAGE: 'personalization_storage',
16+
SECURITY_STORAGE: 'security_storage',
17+
};

libs/blog/tracking/feature/src/lib/cookie-consent/cookie-consent.provider.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import {
66
PLATFORM_ID,
77
provideAppInitializer,
88
} from '@angular/core';
9-
import type { CookieConsentConfig } from 'vanilla-cookieconsent';
109

1110
import { CookieConsentService } from './cookie-consent.service';
11+
import { CreateCookieConsentConfigFn } from './models';
1212

1313
export const provideCookieConsent = (
14-
config: CookieConsentConfig,
14+
config: CreateCookieConsentConfigFn,
1515
): EnvironmentProviders => {
1616
return makeEnvironmentProviders([
1717
CookieConsentService,
@@ -23,7 +23,7 @@ export const provideCookieConsent = (
2323
return () => {
2424
if (isPlatformBrowser(platformId)) {
2525
cookieConsentService.cookieConsent.subscribe((cc) => {
26-
cc.run(config);
26+
cc.run(config(cc));
2727
});
2828
}
2929
};

libs/blog/tracking/feature/src/lib/cookie-consent/cookie-consent.service.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import {
2-
EnvironmentProviders,
3-
Injectable,
4-
makeEnvironmentProviders,
5-
} from '@angular/core';
1+
import { Injectable } from '@angular/core';
62
import { defer, Observable, shareReplay } from 'rxjs';
73
import type * as CookieConsent from 'vanilla-cookieconsent';
84

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './models';
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import type * as CookieConsent from 'vanilla-cookieconsent';
2+
3+
export type CreateCookieConsentConfigFn = (
4+
cc: typeof CookieConsent,
5+
) => CookieConsent.CookieConsentConfig;
Lines changed: 78 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,13 @@
1-
import { ScriptFactory } from '../scripts-loader';
1+
import type * as CookieConsent from 'vanilla-cookieconsent';
22

3-
export const initialConsentScript = (): ScriptFactory => (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-
};
3+
import { CATEGORIES, SERVICES } from '../const';
4+
import { ScriptFactory } from '../scripts-loader';
155

166
export const gtmScript =
177
(id: string): ScriptFactory =>
188
(gtmScript) => {
9+
gtmScript.setAttribute('type', 'text/plain');
10+
gtmScript.setAttribute('data-category', 'necessary');
1911
gtmScript.textContent = `(function (w, d, s, l, i) {
2012
w[l] = w[l] || [];
2113
w[l].push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
@@ -27,22 +19,76 @@ export const gtmScript =
2719
return gtmScript;
2820
};
2921

30-
export const consentUpdateScript =
31-
(
32-
category: 'analytics' | 'ads',
33-
consentType: 'ad_storage' | 'analytics_storage',
34-
status: 'granted' | 'denied',
35-
): ScriptFactory =>
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-
};
22+
type PushFn = (...args: any[]) => void;
23+
type DataLayer = {
24+
push: PushFn;
25+
};
26+
27+
declare global {
28+
let dataLayer: DataLayer;
29+
let gtag: PushFn;
30+
31+
interface Window {
32+
dataLayer: DataLayer;
33+
gtag: PushFn;
34+
}
35+
}
36+
37+
export function defaultGtagConsent(): void {
38+
gtag('consent', 'default', {
39+
[SERVICES.AD_STORAGE]: 'denied',
40+
[SERVICES.AD_USER_DATA]: 'denied',
41+
[SERVICES.AD_PERSONALIZATION]: 'denied',
42+
[SERVICES.ANALYTICS_STORAGE]: 'denied',
43+
[SERVICES.FUNCTIONALITY_STORAGE]: 'denied',
44+
[SERVICES.PERSONALIZATION_STORAGE]: 'denied',
45+
[SERVICES.SECURITY_STORAGE]: 'denied',
46+
});
47+
}
48+
49+
export function updateGtagConsent(cc: typeof CookieConsent): void {
50+
gtag('consent', 'update', {
51+
[SERVICES.ANALYTICS_STORAGE]: cc.acceptedService(
52+
SERVICES.ANALYTICS_STORAGE,
53+
CATEGORIES.ANALYTICS,
54+
)
55+
? 'granted'
56+
: 'denied',
57+
[SERVICES.AD_STORAGE]: cc.acceptedService(
58+
SERVICES.AD_STORAGE,
59+
CATEGORIES.ADVERTISEMENT,
60+
)
61+
? 'granted'
62+
: 'denied',
63+
[SERVICES.AD_USER_DATA]: cc.acceptedService(
64+
SERVICES.AD_USER_DATA,
65+
CATEGORIES.ADVERTISEMENT,
66+
)
67+
? 'granted'
68+
: 'denied',
69+
[SERVICES.AD_PERSONALIZATION]: cc.acceptedService(
70+
SERVICES.AD_PERSONALIZATION,
71+
CATEGORIES.ADVERTISEMENT,
72+
)
73+
? 'granted'
74+
: 'denied',
75+
[SERVICES.FUNCTIONALITY_STORAGE]: cc.acceptedService(
76+
SERVICES.FUNCTIONALITY_STORAGE,
77+
CATEGORIES.FUNCTIONALITY,
78+
)
79+
? 'granted'
80+
: 'denied',
81+
[SERVICES.PERSONALIZATION_STORAGE]: cc.acceptedService(
82+
SERVICES.PERSONALIZATION_STORAGE,
83+
CATEGORIES.FUNCTIONALITY,
84+
)
85+
? 'granted'
86+
: 'denied',
87+
[SERVICES.SECURITY_STORAGE]: cc.acceptedService(
88+
SERVICES.SECURITY_STORAGE,
89+
CATEGORIES.SECURITY,
90+
)
91+
? 'granted'
92+
: 'denied',
93+
});
94+
}

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,21 @@ import {
66
PLATFORM_ID,
77
provideAppInitializer,
88
} from '@angular/core';
9-
import type { CookieConsentConfig } from 'vanilla-cookieconsent';
109

10+
import { CreateCookieConsentConfigFn } from './cookie-consent';
1111
import { provideCookieConsent } from './cookie-consent/cookie-consent.provider';
1212
import {
1313
PartyTownConfig,
1414
PartyTownService,
1515
providePartyTown,
1616
} from './partytown';
17+
import { defaultGtagConsent } from './scripts';
1718
import { PixelFactory, ScriptFactory, ScriptsLoader } from './scripts-loader';
1819
import { ScriptsLoaderService } from './scripts-loader.service';
1920

2021
export type TrackingConfig = {
2122
partyTown: PartyTownConfig;
22-
cookieConsent: CookieConsentConfig;
23+
cookieConsent: CreateCookieConsentConfigFn;
2324
scripts?: ScriptFactory[];
2425
pixels?: PixelFactory[];
2526
};
@@ -51,6 +52,12 @@ export const provideTracking = (
5152

5253
return () => {
5354
if (isPlatformBrowser(platformId)) {
55+
window.dataLayer = window.dataLayer || [];
56+
window.gtag = function gtag() {
57+
// eslint-disable-next-line prefer-rest-params
58+
dataLayer.push(arguments);
59+
};
60+
defaultGtagConsent();
5461
scriptsLoader.init(config.scripts ?? [], config.pixels ?? []);
5562
}
5663
};

0 commit comments

Comments
 (0)