@c15t/scripts 1.0.2-rc.0 → 1.1.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/databuddy.cjs +103 -48
  2. package/dist/databuddy.js +99 -47
  3. package/dist/engine/compile.cjs +126 -0
  4. package/dist/engine/compile.js +89 -0
  5. package/dist/engine/runtime.cjs +379 -0
  6. package/dist/engine/runtime.js +345 -0
  7. package/dist/google-tag-manager.cjs +78 -86
  8. package/dist/google-tag-manager.js +74 -79
  9. package/dist/google-tag.cjs +86 -37
  10. package/dist/google-tag.js +82 -36
  11. package/dist/linkedin-insights.cjs +51 -33
  12. package/dist/linkedin-insights.js +46 -31
  13. package/dist/meta-pixel.cjs +90 -28
  14. package/dist/meta-pixel.js +86 -27
  15. package/dist/microsoft-uet.cjs +90 -50
  16. package/dist/microsoft-uet.js +86 -49
  17. package/dist/posthog.cjs +100 -51
  18. package/dist/posthog.js +96 -50
  19. package/dist/resolve.cjs +67 -0
  20. package/dist/resolve.js +33 -0
  21. package/dist/tiktok-pixel.cjs +91 -29
  22. package/dist/tiktok-pixel.js +86 -27
  23. package/dist/types.cjs +47 -0
  24. package/dist/types.js +7 -0
  25. package/dist/x-pixel.cjs +48 -14
  26. package/dist/x-pixel.js +43 -12
  27. package/dist-types/databuddy.d.ts +81 -40
  28. package/dist-types/engine/compile.d.ts +3 -0
  29. package/dist-types/engine/runtime.d.ts +3 -0
  30. package/dist-types/engine.test.d.ts +1 -0
  31. package/dist-types/google-tag-manager.d.ts +65 -30
  32. package/dist-types/google-tag.d.ts +68 -9
  33. package/dist-types/helpers.test.d.ts +1 -0
  34. package/dist-types/linkedin-insights.d.ts +43 -11
  35. package/dist-types/meta-pixel.d.ts +62 -14
  36. package/dist-types/microsoft-uet.d.ts +66 -11
  37. package/dist-types/posthog.d.ts +78 -19
  38. package/dist-types/resolve.d.ts +9 -0
  39. package/dist-types/tiktok-pixel.d.ts +59 -11
  40. package/dist-types/types.d.ts +259 -0
  41. package/dist-types/x-pixel.d.ts +39 -12
  42. package/package.json +3 -3
@@ -1,30 +1,89 @@
1
- function tiktokPixel({ pixelId, script }) {
2
- return {
3
- id: script?.id ?? 'tiktok-pixel',
4
- category: script?.category ?? 'marketing',
5
- textContent: `
6
- !function (w, d, t) {
7
- w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie","holdConsent","revokeConsent","grantConsent"],ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.instance=function(t){for(
8
- var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e},ttq.load=function(e,n){var r="${script?.src ?? 'https://analytics.tiktok.com/i18n/pixel/events.js'}",o=n&&n.partner;ttq._i=ttq._i||{},ttq._i[e]=[],ttq._i[e]._u=r,ttq._t=ttq._t||{},ttq._t[e]=+new Date,ttq._o=ttq._o||{},ttq._o[e]=n||{};n=document.createElement("script")
9
- ;n.type="text/javascript",n.async=!0,n.src=r+"?sdkid="+e+"&lib="+t;e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(n,e)};
10
- ttq.load('${pixelId}');
11
- ttq.grantConsent();
12
- ttq.page();
13
- }(window, document, 'ttq');
14
- `.trim(),
15
- persistAfterConsentRevoked: true,
16
- onLoad: (rest)=>{
17
- window.ttq.grantConsent();
18
- if (script?.onLoad) script.onLoad(rest);
1
+ import { resolveManifest } from "./resolve.js";
2
+ import { vendorManifestContract } from "./types.js";
3
+ const tiktokPixelManifest = {
4
+ ...vendorManifestContract,
5
+ vendor: 'tiktok-pixel',
6
+ category: 'marketing',
7
+ persistAfterConsentRevoked: true,
8
+ bootstrap: [
9
+ {
10
+ type: 'setGlobal',
11
+ name: 'TiktokAnalyticsObject',
12
+ value: 'ttq'
19
13
  },
20
- onConsentChange: ({ consents, ...rest })=>{
21
- if (consents.marketing) window.ttq.grantConsent();
22
- else window.ttq.revokeConsent();
23
- if (script?.onConsentChange) script.onConsentChange({
24
- consents,
25
- ...rest
26
- });
14
+ {
15
+ type: 'setGlobal',
16
+ name: 'ttq',
17
+ value: [],
18
+ ifUndefined: true
19
+ },
20
+ {
21
+ type: 'defineQueueMethods',
22
+ target: 'ttq',
23
+ methods: [
24
+ 'page',
25
+ 'track',
26
+ 'identify',
27
+ 'instances',
28
+ 'debug',
29
+ 'on',
30
+ 'off',
31
+ 'once',
32
+ 'ready',
33
+ 'alias',
34
+ 'group',
35
+ 'enableCookie',
36
+ 'disableCookie',
37
+ 'holdConsent',
38
+ 'revokeConsent',
39
+ 'grantConsent'
40
+ ]
41
+ }
42
+ ],
43
+ install: [
44
+ {
45
+ type: 'callGlobal',
46
+ global: 'ttq',
47
+ method: 'grantConsent'
48
+ },
49
+ {
50
+ type: 'callGlobal',
51
+ global: 'ttq',
52
+ method: 'page'
53
+ },
54
+ {
55
+ type: 'loadScript',
56
+ src: "{{scriptSrc}}?sdkid={{pixelId}}&lib=ttq",
57
+ async: true
58
+ }
59
+ ],
60
+ afterLoad: [
61
+ {
62
+ type: 'callGlobal',
63
+ global: 'ttq',
64
+ method: 'grantConsent'
65
+ }
66
+ ],
67
+ onConsentGranted: [
68
+ {
69
+ type: 'callGlobal',
70
+ global: 'ttq',
71
+ method: 'grantConsent'
72
+ }
73
+ ],
74
+ onConsentDenied: [
75
+ {
76
+ type: 'callGlobal',
77
+ global: 'ttq',
78
+ method: 'revokeConsent'
27
79
  }
28
- };
80
+ ]
81
+ };
82
+ function tiktokPixel({ pixelId, scriptSrc }) {
83
+ const resolved = resolveManifest(tiktokPixelManifest, {
84
+ pixelId,
85
+ scriptSrc: scriptSrc ?? 'https://analytics.tiktok.com/i18n/pixel/events.js'
86
+ });
87
+ return resolved;
29
88
  }
30
- export { tiktokPixel };
89
+ export { tiktokPixel, tiktokPixelManifest };
package/dist/types.cjs ADDED
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ VENDOR_MANIFEST_KIND: ()=>VENDOR_MANIFEST_KIND,
28
+ VENDOR_MANIFEST_SCHEMA_VERSION: ()=>VENDOR_MANIFEST_SCHEMA_VERSION,
29
+ vendorManifestContract: ()=>vendorManifestContract
30
+ });
31
+ const VENDOR_MANIFEST_KIND = 'c15t.vendor-manifest';
32
+ const VENDOR_MANIFEST_SCHEMA_VERSION = 1;
33
+ const vendorManifestContract = {
34
+ kind: VENDOR_MANIFEST_KIND,
35
+ schemaVersion: VENDOR_MANIFEST_SCHEMA_VERSION
36
+ };
37
+ exports.VENDOR_MANIFEST_KIND = __webpack_exports__.VENDOR_MANIFEST_KIND;
38
+ exports.VENDOR_MANIFEST_SCHEMA_VERSION = __webpack_exports__.VENDOR_MANIFEST_SCHEMA_VERSION;
39
+ exports.vendorManifestContract = __webpack_exports__.vendorManifestContract;
40
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
41
+ "VENDOR_MANIFEST_KIND",
42
+ "VENDOR_MANIFEST_SCHEMA_VERSION",
43
+ "vendorManifestContract"
44
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
45
+ Object.defineProperty(exports, '__esModule', {
46
+ value: true
47
+ });
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ const VENDOR_MANIFEST_KIND = 'c15t.vendor-manifest';
2
+ const VENDOR_MANIFEST_SCHEMA_VERSION = 1;
3
+ const vendorManifestContract = {
4
+ kind: VENDOR_MANIFEST_KIND,
5
+ schemaVersion: VENDOR_MANIFEST_SCHEMA_VERSION
6
+ };
7
+ export { VENDOR_MANIFEST_KIND, VENDOR_MANIFEST_SCHEMA_VERSION, vendorManifestContract };
package/dist/x-pixel.cjs CHANGED
@@ -13,7 +13,7 @@ var __webpack_require__ = {};
13
13
  })();
14
14
  (()=>{
15
15
  __webpack_require__.r = (exports1)=>{
16
- if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
16
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
17
  value: 'Module'
18
18
  });
19
19
  Object.defineProperty(exports1, '__esModule', {
@@ -25,26 +25,60 @@ var __webpack_exports__ = {};
25
25
  __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
27
  xPixel: ()=>xPixel,
28
- xPixelEvent: ()=>xPixelEvent
28
+ xPixelEvent: ()=>xPixelEvent,
29
+ xPixelManifest: ()=>xPixelManifest
29
30
  });
30
- function xPixel({ pixelId, script }) {
31
- return {
32
- id: script?.id ?? 'x-pixel',
33
- category: script?.category ?? 'marketing',
34
- textContent: `
35
- !function(e,t,n,s,u,a){e.twq||(s=e.twq=function(){s.exe?s.exe.apply(s,arguments):s.queue.push(arguments);
36
- },s.version='1.1',s.queue=[],u=t.createElement(n),u.async=!0,u.src='${script?.src ?? 'https://static.ads-twitter.com/uwt.js'}',
37
- a=t.getElementsByTagName(n)[0],a.parentNode.insertBefore(u,a))}(window,document,'script');
38
- twq('config','${pixelId}');
39
- `.trim()
40
- };
31
+ const external_resolve_cjs_namespaceObject = require("./resolve.cjs");
32
+ const external_types_cjs_namespaceObject = require("./types.cjs");
33
+ const xPixelManifest = {
34
+ ...external_types_cjs_namespaceObject.vendorManifestContract,
35
+ vendor: 'x-pixel',
36
+ category: 'marketing',
37
+ bootstrap: [
38
+ {
39
+ type: 'defineStubFunction',
40
+ name: 'twq',
41
+ queue: {
42
+ property: 'queue'
43
+ },
44
+ dispatchProperty: 'exe',
45
+ properties: {
46
+ version: '1.1'
47
+ },
48
+ ifUndefined: true
49
+ }
50
+ ],
51
+ install: [
52
+ {
53
+ type: 'callGlobal',
54
+ global: 'twq',
55
+ args: [
56
+ 'config',
57
+ '{{pixelId}}'
58
+ ]
59
+ },
60
+ {
61
+ type: 'loadScript',
62
+ src: "{{scriptSrc}}",
63
+ async: true
64
+ }
65
+ ]
66
+ };
67
+ function xPixel({ pixelId, scriptSrc }) {
68
+ const resolved = (0, external_resolve_cjs_namespaceObject.resolveManifest)(xPixelManifest, {
69
+ pixelId,
70
+ scriptSrc: scriptSrc ?? 'https://static.ads-twitter.com/uwt.js'
71
+ });
72
+ return resolved;
41
73
  }
42
74
  const xPixelEvent = (eventId, metadata)=>window.twq?.('event', eventId, metadata);
43
75
  exports.xPixel = __webpack_exports__.xPixel;
44
76
  exports.xPixelEvent = __webpack_exports__.xPixelEvent;
77
+ exports.xPixelManifest = __webpack_exports__.xPixelManifest;
45
78
  for(var __rspack_i in __webpack_exports__)if (-1 === [
46
79
  "xPixel",
47
- "xPixelEvent"
80
+ "xPixelEvent",
81
+ "xPixelManifest"
48
82
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
49
83
  Object.defineProperty(exports, '__esModule', {
50
84
  value: true
package/dist/x-pixel.js CHANGED
@@ -1,14 +1,45 @@
1
- function xPixel({ pixelId, script }) {
2
- return {
3
- id: script?.id ?? 'x-pixel',
4
- category: script?.category ?? 'marketing',
5
- textContent: `
6
- !function(e,t,n,s,u,a){e.twq||(s=e.twq=function(){s.exe?s.exe.apply(s,arguments):s.queue.push(arguments);
7
- },s.version='1.1',s.queue=[],u=t.createElement(n),u.async=!0,u.src='${script?.src ?? 'https://static.ads-twitter.com/uwt.js'}',
8
- a=t.getElementsByTagName(n)[0],a.parentNode.insertBefore(u,a))}(window,document,'script');
9
- twq('config','${pixelId}');
10
- `.trim()
11
- };
1
+ import { resolveManifest } from "./resolve.js";
2
+ import { vendorManifestContract } from "./types.js";
3
+ const xPixelManifest = {
4
+ ...vendorManifestContract,
5
+ vendor: 'x-pixel',
6
+ category: 'marketing',
7
+ bootstrap: [
8
+ {
9
+ type: 'defineStubFunction',
10
+ name: 'twq',
11
+ queue: {
12
+ property: 'queue'
13
+ },
14
+ dispatchProperty: 'exe',
15
+ properties: {
16
+ version: '1.1'
17
+ },
18
+ ifUndefined: true
19
+ }
20
+ ],
21
+ install: [
22
+ {
23
+ type: 'callGlobal',
24
+ global: 'twq',
25
+ args: [
26
+ 'config',
27
+ '{{pixelId}}'
28
+ ]
29
+ },
30
+ {
31
+ type: 'loadScript',
32
+ src: "{{scriptSrc}}",
33
+ async: true
34
+ }
35
+ ]
36
+ };
37
+ function xPixel({ pixelId, scriptSrc }) {
38
+ const resolved = resolveManifest(xPixelManifest, {
39
+ pixelId,
40
+ scriptSrc: scriptSrc ?? 'https://static.ads-twitter.com/uwt.js'
41
+ });
42
+ return resolved;
12
43
  }
13
44
  const xPixelEvent = (eventId, metadata)=>window.twq?.('event', eventId, metadata);
14
- export { xPixel, xPixelEvent };
45
+ export { xPixel, xPixelEvent, xPixelManifest };
@@ -1,4 +1,4 @@
1
- import type { Script } from '../../core/dist-types/index.d.ts';
1
+ import type { Script } from 'c15t';
2
2
  declare global {
3
3
  interface Window {
4
4
  databuddy?: {
@@ -20,6 +20,71 @@ declare global {
20
20
  };
21
21
  }
22
22
  }
23
+ /**
24
+ * DataBuddy vendor manifest.
25
+ *
26
+ * DataBuddy always loads but controls tracking via its `options.disabled` flag.
27
+ * Config is seeded via `window.databuddyConfig` before the script loads.
28
+ */
29
+ export declare const databuddyManifest: {
30
+ readonly vendor: "databuddy";
31
+ readonly category: "measurement";
32
+ readonly alwaysLoad: true;
33
+ readonly install: [{
34
+ readonly type: "loadScript";
35
+ readonly src: "{{scriptUrl}}";
36
+ readonly async: true;
37
+ readonly attributes: {
38
+ readonly crossorigin: "anonymous";
39
+ readonly 'data-client-id': "{{clientId}}";
40
+ readonly 'data-api-url': "{{apiUrl}}";
41
+ };
42
+ }];
43
+ readonly onBeforeLoadGranted: [{
44
+ readonly type: "setGlobal";
45
+ readonly name: "databuddyConfig";
46
+ readonly value: "{{configWhenGranted}}";
47
+ readonly ifUndefined: true;
48
+ }];
49
+ readonly onBeforeLoadDenied: [{
50
+ readonly type: "setGlobal";
51
+ readonly name: "databuddyConfig";
52
+ readonly value: "{{configWhenDenied}}";
53
+ readonly ifUndefined: true;
54
+ }];
55
+ readonly onLoadGranted: [{
56
+ readonly type: "setGlobalPath";
57
+ readonly path: ["databuddy", "options", "disabled"];
58
+ readonly value: false;
59
+ }];
60
+ readonly onLoadDenied: [{
61
+ readonly type: "setGlobalPath";
62
+ readonly path: ["databuddy", "options", "disabled"];
63
+ readonly value: true;
64
+ }];
65
+ readonly onConsentGranted: [{
66
+ readonly type: "setGlobal";
67
+ readonly name: "databuddyConfig";
68
+ readonly value: "{{configWhenGranted}}";
69
+ readonly ifUndefined: false;
70
+ }, {
71
+ readonly type: "setGlobalPath";
72
+ readonly path: ["databuddy", "options", "disabled"];
73
+ readonly value: false;
74
+ }];
75
+ readonly onConsentDenied: [{
76
+ readonly type: "setGlobal";
77
+ readonly name: "databuddyConfig";
78
+ readonly value: "{{configWhenDenied}}";
79
+ readonly ifUndefined: false;
80
+ }, {
81
+ readonly type: "setGlobalPath";
82
+ readonly path: ["databuddy", "options", "disabled"];
83
+ readonly value: true;
84
+ }];
85
+ readonly kind: "c15t.vendor-manifest";
86
+ readonly schemaVersion: 1;
87
+ };
23
88
  export interface DatabuddyConsentOptions {
24
89
  /**
25
90
  * Your Databuddy client ID.
@@ -35,49 +100,21 @@ export interface DatabuddyConsentOptions {
35
100
  * @default 'https://cdn.databuddy.cc/databuddy.js'
36
101
  */
37
102
  scriptUrl?: string;
38
- /**
39
- * Additional configuration options for Databuddy.
40
- * @example { trackScreenViews: true, trackOutgoingLinks: true }
41
- */
42
- options?: Record<string, unknown>;
43
- /**
44
- * Override or extend the default script values.
45
- *
46
- * Default values:
47
- * - `id`: 'databuddy'
48
- * - `category`: 'measurement'
49
- */
50
- script?: Partial<Script>;
103
+ /** Databuddy config object to seed when consent is granted at load time. */
104
+ configWhenGranted: Record<string, unknown>;
105
+ /** Databuddy config object to seed when consent is denied at load time. */
106
+ configWhenDenied: Record<string, unknown>;
51
107
  }
52
108
  /**
53
- * Loads the Databuddy script and manages consent state through a comprehensive lifecycle.
54
- *
55
- * This function orchestrates consent-aware analytics by coordinating between c15t's consent
56
- * state and Databuddy's tracking behavior. The consent management lifecycle works as follows:
57
- *
58
- * 1. **Before Script Load** (`onBeforeLoad`): Seeds `window.databuddyConfig` with the client
59
- * configuration, including setting `disabled: !hasConsent` to ensure Databuddy initializes
60
- * in the correct state. The Databuddy script reads this configuration object on initialization.
61
- *
62
- * 2. **On Script Load** (`onLoad`): After Databuddy has initialized, verifies that
63
- * `window.databuddy.options.disabled` matches the current consent state by calling
64
- * `handleConsentOpt()`.
109
+ * Loads the Databuddy script and manages consent state declaratively via the manifest runtime.
65
110
  *
66
- * 3. **On Consent Change** (`onConsentChange`): Dynamically toggles `window.databuddy.options.disabled`
67
- * to enable tracking when consent is granted or disable tracking when consent is revoked.
68
- * This ensures real-time compliance with user preferences.
69
- *
70
- * The script always loads (`alwaysLoad: true`) but tracking is controlled via the `disabled` flag,
71
- * allowing Databuddy to remain present in the DOM while respecting consent boundaries.
111
+ * The script always loads (`alwaysLoad: true`) but tracking is controlled via the `disabled`
112
+ * flag on Databuddy's global config/runtime objects, allowing the vendor to stay present in
113
+ * the DOM while respecting consent boundaries.
72
114
  *
73
115
  * @param options - Configuration for the Databuddy consent script
74
116
  * @returns The Databuddy script configuration object for c15t's script loader
75
117
  *
76
- * @throws This function does not throw errors directly. However, network failures or script
77
- * loading errors may cause the Databuddy script to fail silently without initializing
78
- * `window.databuddy`. The lifecycle callbacks handle these cases gracefully by checking for
79
- * the presence of `window.databuddy` before attempting to modify its state.
80
- *
81
118
  * @example
82
119
  * ```ts
83
120
  * import { configureConsentManager } from 'c15t';
@@ -87,13 +124,17 @@ export interface DatabuddyConsentOptions {
87
124
  * scripts: [
88
125
  * databuddy({
89
126
  * clientId: 'db_1234567890abcdef',
90
- * // scriptUrl: 'https://cdn.databuddy.cc/databuddy.js', // Optional, defaults to cdn.databuddy.cc
91
- * // apiUrl: 'https://basket.databuddy.cc', // Optional, defaults to basket.databuddy.cc
92
- * options: {
127
+ * configWhenGranted: {
128
+ * clientId: 'db_1234567890abcdef',
93
129
  * trackScreenViews: true,
94
130
  * trackOutgoingLinks: true,
95
131
  * trackPerformance: true,
96
132
  * samplingRate: 1.0,
133
+ * disabled: false,
134
+ * },
135
+ * configWhenDenied: {
136
+ * clientId: 'db_1234567890abcdef',
137
+ * disabled: true,
97
138
  * },
98
139
  * }),
99
140
  * ],
@@ -0,0 +1,3 @@
1
+ import type { ResolvedManifest, VendorManifest } from '../types';
2
+ export declare function interpolateValue(value: unknown, config: Record<string, unknown>): unknown;
3
+ export declare function compileManifest(manifest: VendorManifest, config?: Record<string, unknown>): ResolvedManifest;
@@ -0,0 +1,3 @@
1
+ import { type Script } from 'c15t';
2
+ import type { ResolvedManifest } from '../types';
3
+ export declare function resolvedManifestToScript(resolvedManifest: ResolvedManifest): Script;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,29 +1,61 @@
1
- import type { ConsentState, Script } from '../../core/dist-types/index.d.ts';
1
+ import type { Script } from 'c15t';
2
2
  declare global {
3
3
  interface Window {
4
4
  dataLayer: unknown[];
5
5
  gtag: (...args: unknown[]) => void;
6
6
  }
7
7
  }
8
- interface GTMConsentConfiguration {
9
- ad_storage: 'granted' | 'denied';
10
- ad_personalization: 'granted' | 'denied';
11
- ad_user_data: 'granted' | 'denied';
12
- analytics_storage: 'granted' | 'denied';
13
- personalization_storage: 'granted' | 'denied';
14
- functionality_storage: 'granted' | 'denied';
15
- security_storage: 'granted' | 'denied';
16
- }
17
- export declare const DEFAULT_GTM_CONSENT_CONFIG: GTMConsentConfiguration;
18
8
  /**
19
- * Converts ConsentState to GTM consent configuration
20
- *
21
- * @param consentState - The application's consent state
22
- * @returns GTM-compatible consent configuration
9
+ * Google Tag Manager vendor manifest.
23
10
  *
24
- * @see {@link CONSENT_STATE_TO_GTM_MAPPING} for the mapping logic
11
+ * Defines GTM as a declarative integration:
12
+ * - Initializes dataLayer and gtag function before the container loads
13
+ * - Maps c15t consent categories to Google Consent Mode v2 types
14
+ * - Signals consent state via `gtag('consent', 'default'|'update', ...)`
25
15
  */
26
- export declare function mapConsentStateToGTM(consentState: ConsentState): GTMConsentConfiguration;
16
+ export declare const googleTagManagerManifest: {
17
+ readonly vendor: "google-tag-manager";
18
+ readonly category: "necessary";
19
+ readonly alwaysLoad: true;
20
+ readonly bootstrap: [{
21
+ readonly type: "setGlobal";
22
+ readonly name: "dataLayer";
23
+ readonly value: readonly [];
24
+ readonly ifUndefined: true;
25
+ }, {
26
+ readonly type: "defineQueueFunction";
27
+ readonly name: "gtag";
28
+ readonly queue: "dataLayer";
29
+ readonly ifUndefined: true;
30
+ }];
31
+ readonly install: [{
32
+ readonly type: "pushToQueue";
33
+ readonly queue: "dataLayer";
34
+ readonly value: {
35
+ readonly 'gtm.start': "{{loadTime}}";
36
+ readonly event: "gtm.js";
37
+ };
38
+ }, {
39
+ readonly type: "loadScript";
40
+ readonly src: "https://www.googletagmanager.com/gtm.js?id={{id}}";
41
+ readonly async: true;
42
+ }];
43
+ readonly onConsentChange: [{
44
+ readonly type: "callGlobal";
45
+ readonly global: "gtag";
46
+ readonly args: ["event", "{{updateEventName}}"];
47
+ }];
48
+ readonly consentMapping: {
49
+ readonly necessary: ["security_storage"];
50
+ readonly functionality: ["functionality_storage"];
51
+ readonly measurement: ["analytics_storage"];
52
+ readonly marketing: ["ad_storage", "ad_user_data", "ad_personalization"];
53
+ readonly experience: ["personalization_storage"];
54
+ };
55
+ readonly consentSignal: "gtag";
56
+ readonly kind: "c15t.vendor-manifest";
57
+ readonly schemaVersion: 1;
58
+ };
27
59
  export interface GoogleTagManagerOptions {
28
60
  /**
29
61
  * Your Google Tag Manager container ID. Begins with 'GTM-'.
@@ -31,24 +63,28 @@ export interface GoogleTagManagerOptions {
31
63
  */
32
64
  id: string;
33
65
  /**
34
- * Update Event Name
35
- * A custom event name used as a trigger to load your script once the consent has been updated.
66
+ * Custom event name fired after consent updates.
67
+ * Can be used as a trigger in GTM to load scripts once consent is updated.
36
68
  *
37
69
  * @default 'consent-update'
38
- * @example 'consent-update'
39
70
  */
40
71
  updateEventName?: string;
41
72
  /**
42
- * Override or extend the default script values.
73
+ * Custom mapping from c15t consent categories to Google Consent Mode v2 types.
74
+ * Overrides the default mapping when provided.
43
75
  *
44
- * Default values:
45
- * - `id`: 'google-tag-manager'
46
- * - `src`: `https://www.googletagmanager.com/gtm.js?id=${id}`
47
- * - `category`: 'necessary' (You control what scripts get loaded via Google Tag Manager)
48
- * - `alwaysLoad`: true
49
- * - `async`: true
76
+ * @default
77
+ * ```ts
78
+ * {
79
+ * necessary: ['security_storage'],
80
+ * functionality: ['functionality_storage'],
81
+ * measurement: ['analytics_storage'],
82
+ * marketing: ['ad_storage', 'ad_user_data', 'ad_personalization'],
83
+ * experience: ['personalization_storage'],
84
+ * }
85
+ * ```
50
86
  */
51
- script?: Partial<Script>;
87
+ consentMapping?: Record<string, string[]>;
52
88
  }
53
89
  /**
54
90
  * Creates a Google Tag Manager script.
@@ -58,5 +94,4 @@ export interface GoogleTagManagerOptions {
58
94
  * @param options - The options for the Google Tag Manager script.
59
95
  * @returns The Google Tag Manager script.
60
96
  */
61
- export declare function googleTagManager({ id, script, updateEventName, }: GoogleTagManagerOptions): Script;
62
- export {};
97
+ export declare function googleTagManager({ id, updateEventName, consentMapping, }: GoogleTagManagerOptions): Script;