consentlayer 0.0.0-stage → 1.0.0-rc.0

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 (151) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +88 -2
  3. package/dist/adapters/google-consent-mode.d.ts +20 -0
  4. package/dist/adapters/google-consent-mode.js +18 -0
  5. package/dist/adapters/google-consent-mode.js.map +1 -0
  6. package/dist/adapters/shopify.d.ts +49 -0
  7. package/dist/adapters/shopify.js +85 -0
  8. package/dist/adapters/shopify.js.map +1 -0
  9. package/dist/adapters/tcf.d.ts +20 -0
  10. package/dist/adapters/tcf.js +64 -0
  11. package/dist/adapters/tcf.js.map +1 -0
  12. package/dist/analytics-provider-07mxUgIK.d.ts +36 -0
  13. package/dist/angular.d.ts +56 -0
  14. package/dist/angular.js +120 -0
  15. package/dist/angular.js.map +1 -0
  16. package/dist/auto-tracking.d.ts +11 -0
  17. package/dist/auto-tracking.js +72 -0
  18. package/dist/auto-tracking.js.map +1 -0
  19. package/dist/chunk-7XLGT6U3.js +34 -0
  20. package/dist/chunk-7XLGT6U3.js.map +1 -0
  21. package/dist/chunk-BWPWDN4G.js +61 -0
  22. package/dist/chunk-BWPWDN4G.js.map +1 -0
  23. package/dist/chunk-DK45XPEY.js +77 -0
  24. package/dist/chunk-DK45XPEY.js.map +1 -0
  25. package/dist/chunk-ETU64ZV3.js +98 -0
  26. package/dist/chunk-ETU64ZV3.js.map +1 -0
  27. package/dist/chunk-FDJMIJFV.js +367 -0
  28. package/dist/chunk-FDJMIJFV.js.map +1 -0
  29. package/dist/chunk-HJGBVDPM.js +47 -0
  30. package/dist/chunk-HJGBVDPM.js.map +1 -0
  31. package/dist/chunk-J3KUPF4R.js +69 -0
  32. package/dist/chunk-J3KUPF4R.js.map +1 -0
  33. package/dist/chunk-LBEIEAJX.js +55 -0
  34. package/dist/chunk-LBEIEAJX.js.map +1 -0
  35. package/dist/chunk-LEAQJXJU.js +582 -0
  36. package/dist/chunk-LEAQJXJU.js.map +1 -0
  37. package/dist/chunk-R6I7OYQB.js +69 -0
  38. package/dist/chunk-R6I7OYQB.js.map +1 -0
  39. package/dist/chunk-RK2M57GW.js +54 -0
  40. package/dist/chunk-RK2M57GW.js.map +1 -0
  41. package/dist/chunk-RZ4TYRNY.js +128 -0
  42. package/dist/chunk-RZ4TYRNY.js.map +1 -0
  43. package/dist/chunk-TVSZJLRC.js +112 -0
  44. package/dist/chunk-TVSZJLRC.js.map +1 -0
  45. package/dist/chunk-TYOQYV45.js +79 -0
  46. package/dist/chunk-TYOQYV45.js.map +1 -0
  47. package/dist/chunk-UAIZU5WD.js +52 -0
  48. package/dist/chunk-UAIZU5WD.js.map +1 -0
  49. package/dist/chunk-VIIGBALD.js +14 -0
  50. package/dist/chunk-VIIGBALD.js.map +1 -0
  51. package/dist/consent-controller-DyHPNfyT.d.ts +47 -0
  52. package/dist/consentlayer-banner.global.js +20 -0
  53. package/dist/consentlayer.global.js +9 -0
  54. package/dist/create-analytics-Bzvm1UpE.d.ts +44 -0
  55. package/dist/ecommerce.d.ts +41 -0
  56. package/dist/ecommerce.js +43 -0
  57. package/dist/ecommerce.js.map +1 -0
  58. package/dist/index.d.ts +58 -0
  59. package/dist/index.js +42 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/next.d.ts +16 -0
  62. package/dist/next.js +27 -0
  63. package/dist/next.js.map +1 -0
  64. package/dist/nuxt/config.d.ts +7 -0
  65. package/dist/nuxt/config.js +6 -0
  66. package/dist/nuxt/config.js.map +1 -0
  67. package/dist/nuxt/index.d.ts +11 -0
  68. package/dist/nuxt/index.js +35 -0
  69. package/dist/nuxt/index.js.map +1 -0
  70. package/dist/nuxt/plugin.d.ts +5 -0
  71. package/dist/nuxt/plugin.js +24 -0
  72. package/dist/nuxt/plugin.js.map +1 -0
  73. package/dist/providers/contentsquare.d.ts +27 -0
  74. package/dist/providers/contentsquare.js +58 -0
  75. package/dist/providers/contentsquare.js.map +1 -0
  76. package/dist/providers/ga4.d.ts +46 -0
  77. package/dist/providers/ga4.js +3 -0
  78. package/dist/providers/ga4.js.map +1 -0
  79. package/dist/providers/gtm.d.ts +28 -0
  80. package/dist/providers/gtm.js +83 -0
  81. package/dist/providers/gtm.js.map +1 -0
  82. package/dist/providers/hotjar.d.ts +38 -0
  83. package/dist/providers/hotjar.js +68 -0
  84. package/dist/providers/hotjar.js.map +1 -0
  85. package/dist/providers/meta.d.ts +42 -0
  86. package/dist/providers/meta.js +65 -0
  87. package/dist/providers/meta.js.map +1 -0
  88. package/dist/providers/posthog.d.ts +42 -0
  89. package/dist/providers/posthog.js +91 -0
  90. package/dist/providers/posthog.js.map +1 -0
  91. package/dist/providers/sentry.d.ts +38 -0
  92. package/dist/providers/sentry.js +82 -0
  93. package/dist/providers/sentry.js.map +1 -0
  94. package/dist/providers/tiktok.d.ts +46 -0
  95. package/dist/providers/tiktok.js +72 -0
  96. package/dist/providers/tiktok.js.map +1 -0
  97. package/dist/providers/vercel.d.ts +14 -0
  98. package/dist/providers/vercel.js +17 -0
  99. package/dist/providers/vercel.js.map +1 -0
  100. package/dist/react/index.d.ts +78 -0
  101. package/dist/react/index.js +79 -0
  102. package/dist/react/index.js.map +1 -0
  103. package/dist/sentry/next.d.ts +1 -0
  104. package/dist/sentry/next.js +3 -0
  105. package/dist/sentry/next.js.map +1 -0
  106. package/dist/sentry/server.d.ts +24 -0
  107. package/dist/sentry/server.js +28 -0
  108. package/dist/sentry/server.js.map +1 -0
  109. package/dist/sentry-replay-HSFVEFCM.js +3 -0
  110. package/dist/sentry-replay-HSFVEFCM.js.map +1 -0
  111. package/dist/sentry-sdk-YQOGKGWD.js +3 -0
  112. package/dist/sentry-sdk-YQOGKGWD.js.map +1 -0
  113. package/dist/sentry-tracing-KWT7ITHF.js +3 -0
  114. package/dist/sentry-tracing-KWT7ITHF.js.map +1 -0
  115. package/dist/server/ga4.d.ts +15 -0
  116. package/dist/server/ga4.js +29 -0
  117. package/dist/server/ga4.js.map +1 -0
  118. package/dist/server/index.d.ts +116 -0
  119. package/dist/server/index.js +206 -0
  120. package/dist/server/index.js.map +1 -0
  121. package/dist/server/meta.d.ts +14 -0
  122. package/dist/server/meta.js +63 -0
  123. package/dist/server/meta.js.map +1 -0
  124. package/dist/server/sgtm.d.ts +18 -0
  125. package/dist/server/sgtm.js +34 -0
  126. package/dist/server/sgtm.js.map +1 -0
  127. package/dist/server/tiktok.d.ts +15 -0
  128. package/dist/server/tiktok.js +64 -0
  129. package/dist/server/tiktok.js.map +1 -0
  130. package/dist/solid.d.ts +59 -0
  131. package/dist/solid.js +3 -0
  132. package/dist/solid.js.map +1 -0
  133. package/dist/solidstart.d.ts +16 -0
  134. package/dist/solidstart.js +22 -0
  135. package/dist/solidstart.js.map +1 -0
  136. package/dist/svelte/GtmNoscript.svelte +18 -0
  137. package/dist/svelte/MetaPixelNoscript.svelte +18 -0
  138. package/dist/svelte.d.ts +55 -0
  139. package/dist/svelte.js +3 -0
  140. package/dist/svelte.js.map +1 -0
  141. package/dist/sveltekit.d.ts +18 -0
  142. package/dist/sveltekit.js +16 -0
  143. package/dist/sveltekit.js.map +1 -0
  144. package/dist/testing.d.ts +11 -0
  145. package/dist/testing.js +50 -0
  146. package/dist/testing.js.map +1 -0
  147. package/dist/types-BV_AFZKQ.d.ts +407 -0
  148. package/dist/vue.d.ts +92 -0
  149. package/dist/vue.js +97 -0
  150. package/dist/vue.js.map +1 -0
  151. package/package.json +281 -4
@@ -0,0 +1,7 @@
1
+ import { A as AnalyticsOptions } from '../create-analytics-Bzvm1UpE.js';
2
+ import '../types-BV_AFZKQ.js';
3
+
4
+ /** The default export of `app/consentlayer.config.ts`: returns the `createAnalytics()` options. Runs inside the Nuxt app, so `useRuntimeConfig()` works. */
5
+ declare const defineConsentLayerConfig: (factory: () => AnalyticsOptions) => () => AnalyticsOptions;
6
+
7
+ export { defineConsentLayerConfig };
@@ -0,0 +1,6 @@
1
+ // src/nuxt/config.ts
2
+ var defineConsentLayerConfig = (factory) => factory;
3
+
4
+ export { defineConsentLayerConfig };
5
+ //# sourceMappingURL=config.js.map
6
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/nuxt/config.ts"],"names":[],"mappings":";AAGO,IAAM,wBAAA,GAA2B,CAAC,OAAA,KAAoC","file":"config.js","sourcesContent":["import type { AnalyticsOptions } from '../core/create-analytics'\n\n/** The default export of `app/consentlayer.config.ts`: returns the `createAnalytics()` options. Runs inside the Nuxt app, so `useRuntimeConfig()` works. */\nexport const defineConsentLayerConfig = (factory: () => AnalyticsOptions) => factory\n"]}
@@ -0,0 +1,11 @@
1
+ import { NuxtModule } from 'nuxt/schema';
2
+ import { ConsentLayerOptions } from '../vue.js';
3
+ import 'vue';
4
+ import '../consent-controller-DyHPNfyT.js';
5
+ import '../types-BV_AFZKQ.js';
6
+
7
+ /** The `consentlayer` key of `nuxt.config`: the `consentLayer` plugin options that are not functions. */
8
+ type ModuleOptions = Omit<ConsentLayerOptions, 'analytics' | 'router'>;
9
+ declare const module$1: NuxtModule<ModuleOptions>;
10
+
11
+ export { type ModuleOptions, module$1 as default };
@@ -0,0 +1,35 @@
1
+ import { defineNuxtModule, createResolver, findPath, addTemplate, addPlugin, addImports, addComponent } from 'nuxt/kit';
2
+
3
+ // src/nuxt/index.ts
4
+ var module$1 = defineNuxtModule({
5
+ meta: { name: "consentlayer", configKey: "consentlayer", compatibility: { nuxt: ">=4.0.0" } },
6
+ async setup(options, nuxt) {
7
+ const resolver = createResolver(import.meta.url);
8
+ const config = await findPath("~/consentlayer.config");
9
+ if (!config)
10
+ throw new Error(
11
+ "consentlayer/nuxt needs app/consentlayer.config.ts, exporting defineConsentLayerConfig(() => options)"
12
+ );
13
+ addTemplate({
14
+ filename: "consentlayer.config.mjs",
15
+ getContents: () => `export { default } from ${JSON.stringify(config)}`
16
+ });
17
+ addTemplate({
18
+ filename: "consentlayer.options.mjs",
19
+ getContents: () => `export default ${JSON.stringify(options)}`
20
+ });
21
+ nuxt.options.build.transpile.push(resolver.resolve("."));
22
+ addPlugin(resolver.resolve("./plugin"));
23
+ addImports([
24
+ { name: "defineConsentLayerConfig", from: resolver.resolve("./config") },
25
+ ...["useAnalytics", "useConsent", "useConsentController"].map((name) => ({ name, from: "consentlayer/vue" }))
26
+ ]);
27
+ addComponent({ name: "MetaPixelNoscript", export: "MetaPixelNoscript", filePath: "consentlayer/vue" });
28
+ addComponent({ name: "GtmNoscript", export: "GtmNoscript", filePath: "consentlayer/vue" });
29
+ }
30
+ });
31
+ var nuxt_default = module$1;
32
+
33
+ export { nuxt_default as default };
34
+ //# sourceMappingURL=index.js.map
35
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/nuxt/index.ts"],"names":["module"],"mappings":";;;AAOA,IAAMA,WAAoC,gBAAA,CAAgC;AAAA,EACxE,IAAA,EAAM,EAAE,IAAA,EAAM,cAAA,EAAgB,SAAA,EAAW,gBAAgB,aAAA,EAAe,EAAE,IAAA,EAAM,SAAA,EAAU,EAAE;AAAA,EAC5F,MAAM,KAAA,CAAM,OAAA,EAAS,IAAA,EAAM;AACzB,IAAA,MAAM,QAAA,GAAW,cAAA,CAAe,MAAA,CAAA,IAAA,CAAY,GAAG,CAAA;AAC/C,IAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,uBAAuB,CAAA;AACrD,IAAA,IAAI,CAAC,MAAA;AACH,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAEF,IAAA,WAAA,CAAY;AAAA,MACV,QAAA,EAAU,yBAAA;AAAA,MACV,aAAa,MAAM,CAAA,wBAAA,EAA2B,IAAA,CAAK,SAAA,CAAU,MAAM,CAAC,CAAA;AAAA,KACrE,CAAA;AACD,IAAA,WAAA,CAAY;AAAA,MACV,QAAA,EAAU,0BAAA;AAAA,MACV,aAAa,MAAM,CAAA,eAAA,EAAkB,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,KAC7D,CAAA;AACD,IAAA,IAAA,CAAK,QAAQ,KAAA,CAAM,SAAA,CAAU,KAAK,QAAA,CAAS,OAAA,CAAQ,GAAG,CAAC,CAAA;AACvD,IAAA,SAAA,CAAU,QAAA,CAAS,OAAA,CAAQ,UAAU,CAAC,CAAA;AACtC,IAAA,UAAA,CAAW;AAAA,MACT,EAAE,IAAA,EAAM,0BAAA,EAA4B,MAAM,QAAA,CAAS,OAAA,CAAQ,UAAU,CAAA,EAAE;AAAA,MACvE,GAAG,CAAC,cAAA,EAAgB,YAAA,EAAc,sBAAsB,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,MAAU,EAAE,IAAA,EAAM,IAAA,EAAM,oBAAmB,CAAE;AAAA,KAC7G,CAAA;AACD,IAAA,YAAA,CAAa,EAAE,IAAA,EAAM,mBAAA,EAAqB,QAAQ,mBAAA,EAAqB,QAAA,EAAU,oBAAoB,CAAA;AACrG,IAAA,YAAA,CAAa,EAAE,IAAA,EAAM,aAAA,EAAe,QAAQ,aAAA,EAAe,QAAA,EAAU,oBAAoB,CAAA;AAAA,EAC3F;AACF,CAAC,CAAA;AAED,IAAO,YAAA,GAAQA","file":"index.js","sourcesContent":["import { addComponent, addImports, addPlugin, addTemplate, createResolver, defineNuxtModule, findPath } from 'nuxt/kit'\nimport type { NuxtModule } from 'nuxt/schema'\nimport type { ConsentLayerOptions } from '../vue'\n\n/** The `consentlayer` key of `nuxt.config`: the `consentLayer` plugin options that are not functions. */\nexport type ModuleOptions = Omit<ConsentLayerOptions, 'analytics' | 'router'>\n\nconst module: NuxtModule<ModuleOptions> = defineNuxtModule<ModuleOptions>({\n meta: { name: 'consentlayer', configKey: 'consentlayer', compatibility: { nuxt: '>=4.0.0' } },\n async setup(options, nuxt) {\n const resolver = createResolver(import.meta.url)\n const config = await findPath('~/consentlayer.config')\n if (!config)\n throw new Error(\n 'consentlayer/nuxt needs app/consentlayer.config.ts, exporting defineConsentLayerConfig(() => options)',\n )\n\n addTemplate({\n filename: 'consentlayer.config.mjs',\n getContents: () => `export { default } from ${JSON.stringify(config)}`,\n })\n addTemplate({\n filename: 'consentlayer.options.mjs',\n getContents: () => `export default ${JSON.stringify(options)}`,\n })\n nuxt.options.build.transpile.push(resolver.resolve('.'))\n addPlugin(resolver.resolve('./plugin'))\n addImports([\n { name: 'defineConsentLayerConfig', from: resolver.resolve('./config') },\n ...['useAnalytics', 'useConsent', 'useConsentController'].map((name) => ({ name, from: 'consentlayer/vue' })),\n ])\n addComponent({ name: 'MetaPixelNoscript', export: 'MetaPixelNoscript', filePath: 'consentlayer/vue' })\n addComponent({ name: 'GtmNoscript', export: 'GtmNoscript', filePath: 'consentlayer/vue' })\n },\n})\n\nexport default module\n"]}
@@ -0,0 +1,5 @@
1
+ import * as nuxt_app from 'nuxt/app';
2
+
3
+ declare const _default: nuxt_app.Plugin<Record<string, unknown>> & nuxt_app.ObjectPlugin<Record<string, unknown>>;
4
+
5
+ export { _default as default };
@@ -0,0 +1,24 @@
1
+ import config from '#build/consentlayer.config.mjs';
2
+ import options from '#build/consentlayer.options.mjs';
3
+ import { createAnalytics } from 'consentlayer';
4
+ import { consentLayer } from 'consentlayer/vue';
5
+ import { defineNuxtPlugin, useRouter } from 'nuxt/app';
6
+
7
+ // src/nuxt/plugin.ts
8
+ var plugin_default = defineNuxtPlugin({
9
+ name: "consentlayer",
10
+ setup(nuxtApp) {
11
+ const { captureErrors = true, ...rest } = options;
12
+ const analytics = createAnalytics(config());
13
+ nuxtApp.vueApp.use(consentLayer, { ...rest, captureErrors: false, analytics, router: useRouter() });
14
+ if (captureErrors && import.meta.client) {
15
+ nuxtApp.hook("vue:error", (error, _instance, info) => {
16
+ void analytics.captureError(error, { source: "boundary", tags: { vue_info: info } });
17
+ });
18
+ }
19
+ }
20
+ });
21
+
22
+ export { plugin_default as default };
23
+ //# sourceMappingURL=plugin.js.map
24
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/nuxt/plugin.ts"],"names":[],"mappings":";;;;;;;AAMA,IAAO,iBAAQ,gBAAA,CAAiB;AAAA,EAC9B,IAAA,EAAM,cAAA;AAAA,EACN,MAAM,OAAA,EAAS;AACb,IAAA,MAAM,EAAE,aAAA,GAAgB,IAAA,EAAM,GAAG,MAAK,GAAI,OAAA;AAC1C,IAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,MAAA,EAAQ,CAAA;AAC1C,IAAA,OAAA,CAAQ,MAAA,CAAO,GAAA,CAAI,YAAA,EAAc,EAAE,GAAG,IAAA,EAAM,aAAA,EAAe,KAAA,EAAO,SAAA,EAAW,MAAA,EAAQ,SAAA,EAAU,EAAG,CAAA;AAClG,IAAA,IAAI,aAAA,IAAiB,YAAY,MAAA,EAAQ;AACvC,MAAA,OAAA,CAAQ,IAAA,CAAK,WAAA,EAAa,CAAC,KAAA,EAAO,WAAW,IAAA,KAAS;AACpD,QAAA,KAAK,SAAA,CAAU,YAAA,CAAa,KAAA,EAAO,EAAE,MAAA,EAAQ,UAAA,EAAY,IAAA,EAAM,EAAE,QAAA,EAAU,IAAA,EAAK,EAAG,CAAA;AAAA,MACrF,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AACF,CAAC","file":"plugin.js","sourcesContent":["import config from '#build/consentlayer.config.mjs'\nimport options from '#build/consentlayer.options.mjs'\nimport { createAnalytics } from 'consentlayer'\nimport { consentLayer } from 'consentlayer/vue'\nimport { defineNuxtPlugin, useRouter } from 'nuxt/app'\n\nexport default defineNuxtPlugin({\n name: 'consentlayer',\n setup(nuxtApp) {\n const { captureErrors = true, ...rest } = options\n const analytics = createAnalytics(config())\n nuxtApp.vueApp.use(consentLayer, { ...rest, captureErrors: false, analytics, router: useRouter() })\n if (captureErrors && import.meta.client) {\n nuxtApp.hook('vue:error', (error, _instance, info) => {\n void analytics.captureError(error, { source: 'boundary', tags: { vue_info: info } })\n })\n }\n },\n})\n"]}
@@ -0,0 +1,27 @@
1
+ import { f as AnalyticsPlugin, P as PluginContext, g as PageEvent, h as AnalyticsEventPayload, U as UserIdentity } from '../types-BV_AFZKQ.js';
2
+
3
+ declare global {
4
+ interface Window {
5
+ _uxa?: unknown[][];
6
+ }
7
+ }
8
+ /** Options for `contentsquare`. */
9
+ type ContentsquareOptions = {
10
+ /** The ID in your tag's URL: `t.contentsquare.net/uxa/<tagId>.js`. */
11
+ /** `undefined` or `''` turns the provider off. */
12
+ tagId: string | undefined;
13
+ };
14
+ /** Contentsquare (Hotjar's successor), after analytics consent. */
15
+ declare function contentsquare(options: ContentsquareOptions): AnalyticsPlugin | {
16
+ id: string;
17
+ requiredConsent: "analytics";
18
+ consent(context: PluginContext): void;
19
+ load(): void;
20
+ page(page: PageEvent): void;
21
+ track(event: AnalyticsEventPayload): void;
22
+ identify(identity: UserIdentity): void;
23
+ reset(): void;
24
+ teardown(context: PluginContext): void;
25
+ };
26
+
27
+ export { type ContentsquareOptions, contentsquare };
@@ -0,0 +1,58 @@
1
+ import { expireCookies } from '../chunk-TVSZJLRC.js';
2
+ import { skippedPlugin, definePlugin, loadScript } from '../chunk-7XLGT6U3.js';
3
+ import { getFlag, setFlag } from '../chunk-R6I7OYQB.js';
4
+
5
+ // src/providers/contentsquare.ts
6
+ var push = (...command) => (window._uxa = window._uxa ?? []).push(command);
7
+ var pathOf = (path = location.pathname) => path.split(/[?#]/)[0];
8
+ function contentsquare(options) {
9
+ const tagId = options.tagId?.trim();
10
+ if (!tagId) return skippedPlugin("contentsquare", "tagId");
11
+ let loadedPath;
12
+ return definePlugin({
13
+ id: "contentsquare",
14
+ requiredConsent: "analytics",
15
+ consent(context) {
16
+ if (typeof window !== "undefined" && context.consent?.analytics) expireCookies((name) => name === "_cs_optout");
17
+ },
18
+ load() {
19
+ if (typeof window === "undefined" || getFlag("ContentsquareInitialized")) return;
20
+ window._uxa = window._uxa ?? [];
21
+ loadedPath = pathOf();
22
+ void loadScript(`https://t.contentsquare.net/uxa/${tagId}.js`).catch(() => void 0);
23
+ setFlag("ContentsquareInitialized", true);
24
+ },
25
+ page(page) {
26
+ const path = pathOf(page.path);
27
+ if (path === loadedPath) {
28
+ loadedPath = void 0;
29
+ return;
30
+ }
31
+ loadedPath = void 0;
32
+ push("trackPageview", path);
33
+ },
34
+ track(event) {
35
+ if (event.name !== "purchase") {
36
+ push("trackPageEvent", event.name);
37
+ return;
38
+ }
39
+ const { transaction_id, value, currency } = event.params;
40
+ push("ec:transaction:create", { id: transaction_id, revenue: value, currency });
41
+ push("ec:transaction:send");
42
+ },
43
+ identify(identity) {
44
+ if (identity.userId) push("identify", identity.userId);
45
+ },
46
+ reset() {
47
+ push("resetIdentity");
48
+ },
49
+ teardown(context) {
50
+ if (typeof window === "undefined" || context.consent?.analytics || !getFlag("ContentsquareInitialized")) return;
51
+ push("optout");
52
+ }
53
+ });
54
+ }
55
+
56
+ export { contentsquare };
57
+ //# sourceMappingURL=contentsquare.js.map
58
+ //# sourceMappingURL=contentsquare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/providers/contentsquare.ts"],"names":[],"mappings":";;;;;AAgBA,IAAM,IAAA,GAAO,CAAA,GAAI,OAAA,KAAA,CAAwB,MAAA,CAAO,IAAA,GAAO,OAAO,IAAA,IAAQ,EAAC,EAAG,IAAA,CAAK,OAAO,CAAA;AACtF,IAAM,MAAA,GAAS,CAAC,IAAA,GAAO,QAAA,CAAS,aAAa,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA,CAAE,CAAC,CAAA;AAG1D,SAAS,cAAc,OAAA,EAA+B;AAC3D,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,EAAO,IAAA,EAAK;AAClC,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,aAAA,CAAc,iBAAiB,OAAO,CAAA;AACzD,EAAA,IAAI,UAAA;AACJ,EAAA,OAAO,YAAA,CAAa;AAAA,IAClB,EAAA,EAAI,eAAA;AAAA,IACJ,eAAA,EAAiB,WAAA;AAAA,IACjB,QAAQ,OAAA,EAAS;AAEf,MAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,OAAA,CAAQ,OAAA,EAAS,WAAW,aAAA,CAAc,CAAC,IAAA,KAAS,IAAA,KAAS,YAAY,CAAA;AAAA,IAChH,CAAA;AAAA,IACA,IAAA,GAAO;AACL,MAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,OAAA,CAAQ,0BAA0B,CAAA,EAAG;AAC1E,MAAA,MAAA,CAAO,IAAA,GAAO,MAAA,CAAO,IAAA,IAAQ,EAAC;AAC9B,MAAA,UAAA,GAAa,MAAA,EAAO;AACpB,MAAA,KAAK,WAAW,CAAA,gCAAA,EAAmC,KAAK,KAAK,CAAA,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AACpF,MAAA,OAAA,CAAQ,4BAA4B,IAAI,CAAA;AAAA,IAC1C,CAAA;AAAA,IACA,KAAK,IAAA,EAAM;AACT,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA;AAC7B,MAAA,IAAI,SAAS,UAAA,EAAY;AACvB,QAAA,UAAA,GAAa,MAAA;AACb,QAAA;AAAA,MACF;AACA,MAAA,UAAA,GAAa,MAAA;AACb,MAAA,IAAA,CAAK,iBAAiB,IAAI,CAAA;AAAA,IAC5B,CAAA;AAAA,IACA,MAAM,KAAA,EAAO;AACX,MAAA,IAAI,KAAA,CAAM,SAAS,UAAA,EAAY;AAC7B,QAAA,IAAA,CAAK,gBAAA,EAAkB,MAAM,IAAI,CAAA;AACjC,QAAA;AAAA,MACF;AACA,MAAA,MAAM,EAAE,cAAA,EAAgB,KAAA,EAAO,QAAA,KAAa,KAAA,CAAM,MAAA;AAClD,MAAA,IAAA,CAAK,yBAAyB,EAAE,EAAA,EAAI,gBAAgB,OAAA,EAAS,KAAA,EAAO,UAAU,CAAA;AAC9E,MAAA,IAAA,CAAK,qBAAqB,CAAA;AAAA,IAC5B,CAAA;AAAA,IACA,SAAS,QAAA,EAAU;AACjB,MAAA,IAAI,QAAA,CAAS,MAAA,EAAQ,IAAA,CAAK,UAAA,EAAY,SAAS,MAAM,CAAA;AAAA,IACvD,CAAA;AAAA,IACA,KAAA,GAAQ;AACN,MAAA,IAAA,CAAK,eAAe,CAAA;AAAA,IACtB,CAAA;AAAA,IACA,SAAS,OAAA,EAAS;AAChB,MAAA,IAAI,OAAO,WAAW,WAAA,IAAe,OAAA,CAAQ,SAAS,SAAA,IAAa,CAAC,OAAA,CAAQ,0BAA0B,CAAA,EAAG;AACzG,MAAA,IAAA,CAAK,QAAQ,CAAA;AAAA,IACf;AAAA,GACD,CAAA;AACH","file":"contentsquare.js","sourcesContent":["import { definePlugin, getFlag, loadScript, setFlag, skippedPlugin } from '../core/plugin'\nimport { expireCookies } from '../core/utils'\n\ndeclare global {\n interface Window {\n _uxa?: unknown[][]\n }\n}\n\n/** Options for `contentsquare`. */\nexport type ContentsquareOptions = {\n /** The ID in your tag's URL: `t.contentsquare.net/uxa/<tagId>.js`. */\n /** `undefined` or `''` turns the provider off. */\n tagId: string | undefined\n}\n\nconst push = (...command: unknown[]) => (window._uxa = window._uxa ?? []).push(command)\nconst pathOf = (path = location.pathname) => path.split(/[?#]/)[0]\n\n/** Contentsquare (Hotjar's successor), after analytics consent. */\nexport function contentsquare(options: ContentsquareOptions) {\n const tagId = options.tagId?.trim()\n if (!tagId) return skippedPlugin('contentsquare', 'tagId')\n let loadedPath: string | undefined\n return definePlugin({\n id: 'contentsquare',\n requiredConsent: 'analytics',\n consent(context) {\n // ponytail: Contentsquare has no web opt-in; dropping the opt-out cookie takes effect on the next page load\n if (typeof window !== 'undefined' && context.consent?.analytics) expireCookies((name) => name === '_cs_optout')\n },\n load() {\n if (typeof window === 'undefined' || getFlag('ContentsquareInitialized')) return\n window._uxa = window._uxa ?? []\n loadedPath = pathOf()\n void loadScript(`https://t.contentsquare.net/uxa/${tagId}.js`).catch(() => undefined)\n setFlag('ContentsquareInitialized', true)\n },\n page(page) {\n const path = pathOf(page.path)\n if (path === loadedPath) {\n loadedPath = undefined\n return\n }\n loadedPath = undefined\n push('trackPageview', path)\n },\n track(event) {\n if (event.name !== 'purchase') {\n push('trackPageEvent', event.name)\n return\n }\n const { transaction_id, value, currency } = event.params\n push('ec:transaction:create', { id: transaction_id, revenue: value, currency })\n push('ec:transaction:send')\n },\n identify(identity) {\n if (identity.userId) push('identify', identity.userId)\n },\n reset() {\n push('resetIdentity')\n },\n teardown(context) {\n if (typeof window === 'undefined' || context.consent?.analytics || !getFlag('ContentsquareInitialized')) return\n push('optout')\n },\n })\n}\n"]}
@@ -0,0 +1,46 @@
1
+ import { f as AnalyticsPlugin, P as PluginContext, g as PageEvent, h as AnalyticsEventPayload, U as UserIdentity, i as UserTraits } from '../types-BV_AFZKQ.js';
2
+
3
+ declare global {
4
+ interface Window {
5
+ dataLayer?: unknown[];
6
+ gtag?: (...args: unknown[]) => void;
7
+ }
8
+ }
9
+ /** Options for `ga4`. */
10
+ type Ga4Options = {
11
+ /** `undefined` or `''` turns the provider off. */
12
+ measurementId: string | undefined;
13
+ /**
14
+ * `true`: gtag.js loads at boot with Consent Mode set to denied.
15
+ * `false` (default): nothing loads until analytics consent is granted.
16
+ */
17
+ loadBeforeConsent?: boolean;
18
+ consentMode?: Ga4ConsentMode;
19
+ /** Your tagging server, e.g. `https://sgtm.example.com`: hits go to it instead of Google. */
20
+ serverContainerUrl?: string;
21
+ };
22
+ /**
23
+ * `'basic'` (default): the tag is configured once analytics is granted.
24
+ * `'advanced'`: the tag loads and is configured at boot, so Google receives
25
+ * cookieless pings while consent is denied.
26
+ */
27
+ type Ga4ConsentMode = 'basic' | 'advanced';
28
+ /** GA4 event names allow only letters, digits and underscores. */
29
+ declare function ga4EventName(name: string): string;
30
+ /** User-provided data; empty when there is no email or phone to share. */
31
+ declare function ga4UserData(identity: UserIdentity): Record<string, string>;
32
+ /** Google Analytics 4 via gtag.js, with Consent Mode v2. Needs analytics consent; ad signals follow marketing consent. */
33
+ declare function ga4(options: Ga4Options): AnalyticsPlugin | {
34
+ id: string;
35
+ requiredConsent: "analytics" | "none";
36
+ loadBeforeConsent: boolean;
37
+ setup(): void;
38
+ consent({ consent, identity }: PluginContext): void;
39
+ load({ emitError }: PluginContext): void;
40
+ page(page: PageEvent): void;
41
+ track(event: AnalyticsEventPayload): void;
42
+ identify(identity: UserIdentity, _traits: UserTraits, { consent }: PluginContext): void;
43
+ reset(): void;
44
+ };
45
+
46
+ export { type Ga4ConsentMode, type Ga4Options, ga4, ga4EventName, ga4UserData };
@@ -0,0 +1,3 @@
1
+ export { ga4, ga4EventName, ga4UserData } from '../chunk-ETU64ZV3.js';
2
+ //# sourceMappingURL=ga4.js.map
3
+ //# sourceMappingURL=ga4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"ga4.js"}
@@ -0,0 +1,28 @@
1
+ import { j as ProviderConsentRequirement, f as AnalyticsPlugin, P as PluginContext, g as PageEvent, h as AnalyticsEventPayload, U as UserIdentity, i as UserTraits } from '../types-BV_AFZKQ.js';
2
+
3
+ /** Options for `gtm`. */
4
+ type GtmOptions = {
5
+ /** `undefined` or `''` turns the provider off. */
6
+ containerId: string | undefined;
7
+ /**
8
+ * `'none'` (default): the container loads at boot and its tags follow
9
+ * Consent Mode. A category: nothing loads until it is granted.
10
+ */
11
+ requiredConsent?: ProviderConsentRequirement;
12
+ /** Your tagging server, e.g. `https://sgtm.example.com`: `gtm.js` loads from it instead of Google. */
13
+ serverContainerUrl?: string;
14
+ };
15
+ /** Google Tag Manager. Feeds page views, events, the user ID and consent into `dataLayer`. */
16
+ declare function gtm(options: GtmOptions): AnalyticsPlugin | {
17
+ id: string;
18
+ requiredConsent: ProviderConsentRequirement;
19
+ setup(): void;
20
+ consent({ consent, identity }: PluginContext): void;
21
+ load({ emitError }: PluginContext): void;
22
+ page(page: PageEvent): void;
23
+ track(event: AnalyticsEventPayload): void;
24
+ identify(identity: UserIdentity, _traits: UserTraits, { consent }: PluginContext): void;
25
+ reset(): void;
26
+ };
27
+
28
+ export { type GtmOptions, gtm };
@@ -0,0 +1,83 @@
1
+ import { builtInConsentMode, ensureGtag } from '../chunk-BWPWDN4G.js';
2
+ import { assertHttpsOrRelativeUrl } from '../chunk-J3KUPF4R.js';
3
+ import { skippedPlugin, definePlugin, loadScript } from '../chunk-7XLGT6U3.js';
4
+ import { setFlag, getFlag } from '../chunk-R6I7OYQB.js';
5
+
6
+ // src/providers/gtm.ts
7
+ var GTM_CONTAINER_ID = /^GTM-[A-Z0-9]{4,12}$/;
8
+ function gtm(options) {
9
+ if (!options.containerId?.trim()) return skippedPlugin("gtm", "containerId");
10
+ const containerId = options.containerId.trim();
11
+ if (!GTM_CONTAINER_ID.test(containerId)) {
12
+ throw new Error(
13
+ `[consentlayer] Invalid GTM container ID: expected format "GTM-XXXXXXX", received "${containerId}".`
14
+ );
15
+ }
16
+ const origin = options.serverContainerUrl ? assertHttpsOrRelativeUrl(options.serverContainerUrl, "gtm serverContainerUrl").replace(/\/$/, "") : "https://www.googletagmanager.com";
17
+ let ownConsentMode = false;
18
+ let userId = null;
19
+ let consented = null;
20
+ const push = (message) => window.dataLayer?.push(message);
21
+ const pushUserId = (next) => {
22
+ if ((next ?? null) === userId) return;
23
+ userId = next ?? null;
24
+ push({ event: "consentlayer_identify", user_id: userId });
25
+ };
26
+ return definePlugin({
27
+ id: "gtm",
28
+ requiredConsent: options.requiredConsent ?? "none",
29
+ setup() {
30
+ if (typeof window === "undefined") return;
31
+ ownConsentMode = !getFlag("GoogleConsentMode");
32
+ if (ownConsentMode) builtInConsentMode(null);
33
+ else ensureGtag();
34
+ },
35
+ consent({ consent, identity }) {
36
+ if (typeof window === "undefined") return;
37
+ if (ownConsentMode) builtInConsentMode(consent);
38
+ if (consent && JSON.stringify(consent) !== JSON.stringify(consented)) {
39
+ consented = consent;
40
+ push({ event: "consentlayer_consent", consent: { ...consent } });
41
+ }
42
+ pushUserId(consent?.analytics ? identity.userId : void 0);
43
+ },
44
+ load({ emitError }) {
45
+ if (typeof window === "undefined") return;
46
+ const loaded = setFlag("GtmLoaded", getFlag("GtmLoaded") ?? {});
47
+ if (loaded[containerId]) return;
48
+ loaded[containerId] = true;
49
+ push({ "gtm.start": Date.now(), event: "gtm.js" });
50
+ loadScript(`${origin}/gtm.js?id=${encodeURIComponent(containerId)}`).catch(
51
+ () => emitError({
52
+ scope: "provider-script-load",
53
+ message: `Failed to load Google Tag Manager container ${containerId}`
54
+ })
55
+ );
56
+ },
57
+ page(page) {
58
+ if (typeof window === "undefined") return;
59
+ push({
60
+ event: "page_view",
61
+ page_location: page.url ?? window.location.href,
62
+ page_path: page.path ?? window.location.pathname,
63
+ page_title: page.title ?? document.title
64
+ });
65
+ },
66
+ track(event) {
67
+ if (typeof window === "undefined") return;
68
+ push({ ...event.params, ...event.options.providers?.gtm, event: event.name });
69
+ },
70
+ identify(identity, _traits, { consent }) {
71
+ if (typeof window === "undefined" || !consent?.analytics) return;
72
+ pushUserId(identity.userId);
73
+ },
74
+ reset() {
75
+ if (typeof window === "undefined") return;
76
+ pushUserId(void 0);
77
+ }
78
+ });
79
+ }
80
+
81
+ export { gtm };
82
+ //# sourceMappingURL=gtm.js.map
83
+ //# sourceMappingURL=gtm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/providers/gtm.ts"],"names":[],"mappings":";;;;;;AAkBA,IAAM,gBAAA,GAAmB,sBAAA;AAGlB,SAAS,IAAI,OAAA,EAAqB;AACvC,EAAA,IAAI,CAAC,QAAQ,WAAA,EAAa,IAAA,IAAQ,OAAO,aAAA,CAAc,OAAO,aAAa,CAAA;AAC3E,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,WAAA,CAAY,IAAA,EAAK;AAC7C,EAAA,IAAI,CAAC,gBAAA,CAAiB,IAAA,CAAK,WAAW,CAAA,EAAG;AACvC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,qFAAqF,WAAW,CAAA,EAAA;AAAA,KAClG;AAAA,EACF;AACA,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,kBAAA,GACnB,wBAAA,CAAyB,OAAA,CAAQ,kBAAA,EAAoB,wBAAwB,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,GAChG,kCAAA;AACJ,EAAA,IAAI,cAAA,GAAiB,KAAA;AACrB,EAAA,IAAI,MAAA,GAAwB,IAAA;AAC5B,EAAA,IAAI,SAAA,GAAiC,IAAA;AACrC,EAAA,MAAM,OAAO,CAAC,OAAA,KAAqC,MAAA,CAAO,SAAA,EAAW,KAAK,OAAO,CAAA;AACjF,EAAA,MAAM,UAAA,GAAa,CAAC,IAAA,KAA6B;AAC/C,IAAA,IAAA,CAAK,IAAA,IAAQ,UAAU,MAAA,EAAQ;AAC/B,IAAA,MAAA,GAAS,IAAA,IAAQ,IAAA;AACjB,IAAA,IAAA,CAAK,EAAE,KAAA,EAAO,uBAAA,EAAyB,OAAA,EAAS,QAAQ,CAAA;AAAA,EAC1D,CAAA;AACA,EAAA,OAAO,YAAA,CAAa;AAAA,IAClB,EAAA,EAAI,KAAA;AAAA,IACJ,eAAA,EAAiB,QAAQ,eAAA,IAAmB,MAAA;AAAA,IAC5C,KAAA,GAAQ;AACN,MAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,MAAA,cAAA,GAAiB,CAAC,QAAQ,mBAAmB,CAAA;AAC7C,MAAA,IAAI,cAAA,qBAAmC,IAAI,CAAA;AAAA,WACtC,UAAA,EAAW;AAAA,IAClB,CAAA;AAAA,IACA,OAAA,CAAQ,EAAE,OAAA,EAAS,QAAA,EAAS,EAAG;AAC7B,MAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,MAAA,IAAI,cAAA,qBAAmC,OAAO,CAAA;AAC9C,MAAA,IAAI,OAAA,IAAW,KAAK,SAAA,CAAU,OAAO,MAAM,IAAA,CAAK,SAAA,CAAU,SAAS,CAAA,EAAG;AACpE,QAAA,SAAA,GAAY,OAAA;AACZ,QAAA,IAAA,CAAK,EAAE,OAAO,sBAAA,EAAwB,OAAA,EAAS,EAAE,GAAG,OAAA,IAAW,CAAA;AAAA,MACjE;AACA,MAAA,UAAA,CAAW,OAAA,EAAS,SAAA,GAAY,QAAA,CAAS,MAAA,GAAS,MAAS,CAAA;AAAA,IAC7D,CAAA;AAAA,IACA,IAAA,CAAK,EAAE,SAAA,EAAU,EAAG;AAClB,MAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,MAAA,MAAM,SAAS,OAAA,CAAQ,WAAA,EAAa,QAAiC,WAAW,CAAA,IAAK,EAAE,CAAA;AACvF,MAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACzB,MAAA,MAAA,CAAO,WAAW,CAAA,GAAI,IAAA;AACtB,MAAA,IAAA,CAAK,EAAE,WAAA,EAAa,IAAA,CAAK,KAAI,EAAG,KAAA,EAAO,UAAU,CAAA;AACjD,MAAA,UAAA,CAAW,GAAG,MAAM,CAAA,WAAA,EAAc,mBAAmB,WAAW,CAAC,EAAE,CAAA,CAAE,KAAA;AAAA,QAAM,MACzE,SAAA,CAAU;AAAA,UACR,KAAA,EAAO,sBAAA;AAAA,UACP,OAAA,EAAS,+CAA+C,WAAW,CAAA;AAAA,SACpE;AAAA,OACH;AAAA,IACF,CAAA;AAAA,IACA,KAAK,IAAA,EAAM;AACT,MAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,MAAA,IAAA,CAAK;AAAA,QACH,KAAA,EAAO,WAAA;AAAA,QACP,aAAA,EAAe,IAAA,CAAK,GAAA,IAAO,MAAA,CAAO,QAAA,CAAS,IAAA;AAAA,QAC3C,SAAA,EAAW,IAAA,CAAK,IAAA,IAAQ,MAAA,CAAO,QAAA,CAAS,QAAA;AAAA,QACxC,UAAA,EAAY,IAAA,CAAK,KAAA,IAAS,QAAA,CAAS;AAAA,OACpC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,MAAM,KAAA,EAAO;AACX,MAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,MAAA,IAAA,CAAK,EAAE,GAAG,KAAA,CAAM,MAAA,EAAQ,GAAG,KAAA,CAAM,OAAA,CAAQ,SAAA,EAAW,GAAA,EAAK,KAAA,EAAO,KAAA,CAAM,IAAA,EAAM,CAAA;AAAA,IAC9E,CAAA;AAAA,IACA,QAAA,CAAS,QAAA,EAAU,OAAA,EAAS,EAAE,SAAQ,EAAG;AACvC,MAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,SAAS,SAAA,EAAW;AAC1D,MAAA,UAAA,CAAW,SAAS,MAAM,CAAA;AAAA,IAC5B,CAAA;AAAA,IACA,KAAA,GAAQ;AACN,MAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,MAAA,UAAA,CAAW,MAAS,CAAA;AAAA,IACtB;AAAA,GACD,CAAA;AACH","file":"gtm.js","sourcesContent":["import { builtInConsentMode, ensureGtag } from '../core/consent-mode'\nimport { definePlugin, getFlag, loadScript, setFlag, skippedPlugin } from '../core/plugin'\nimport type { ConsentState, ProviderConsentRequirement } from '../core/types'\nimport { assertHttpsOrRelativeUrl } from '../core/validation'\n\n/** Options for `gtm`. */\nexport type GtmOptions = {\n /** `undefined` or `''` turns the provider off. */\n containerId: string | undefined\n /**\n * `'none'` (default): the container loads at boot and its tags follow\n * Consent Mode. A category: nothing loads until it is granted.\n */\n requiredConsent?: ProviderConsentRequirement\n /** Your tagging server, e.g. `https://sgtm.example.com`: `gtm.js` loads from it instead of Google. */\n serverContainerUrl?: string\n}\n\nconst GTM_CONTAINER_ID = /^GTM-[A-Z0-9]{4,12}$/\n\n/** Google Tag Manager. Feeds page views, events, the user ID and consent into `dataLayer`. */\nexport function gtm(options: GtmOptions) {\n if (!options.containerId?.trim()) return skippedPlugin('gtm', 'containerId')\n const containerId = options.containerId.trim()\n if (!GTM_CONTAINER_ID.test(containerId)) {\n throw new Error(\n `[consentlayer] Invalid GTM container ID: expected format \"GTM-XXXXXXX\", received \"${containerId}\".`,\n )\n }\n const origin = options.serverContainerUrl\n ? assertHttpsOrRelativeUrl(options.serverContainerUrl, 'gtm serverContainerUrl').replace(/\\/$/, '')\n : 'https://www.googletagmanager.com'\n let ownConsentMode = false\n let userId: string | null = null\n let consented: ConsentState | null = null\n const push = (message: Record<string, unknown>) => window.dataLayer?.push(message)\n const pushUserId = (next: string | undefined) => {\n if ((next ?? null) === userId) return\n userId = next ?? null\n push({ event: 'consentlayer_identify', user_id: userId })\n }\n return definePlugin({\n id: 'gtm',\n requiredConsent: options.requiredConsent ?? 'none',\n setup() {\n if (typeof window === 'undefined') return\n ownConsentMode = !getFlag('GoogleConsentMode')\n if (ownConsentMode) builtInConsentMode(null)\n else ensureGtag()\n },\n consent({ consent, identity }) {\n if (typeof window === 'undefined') return\n if (ownConsentMode) builtInConsentMode(consent)\n if (consent && JSON.stringify(consent) !== JSON.stringify(consented)) {\n consented = consent\n push({ event: 'consentlayer_consent', consent: { ...consent } })\n }\n pushUserId(consent?.analytics ? identity.userId : undefined)\n },\n load({ emitError }) {\n if (typeof window === 'undefined') return\n const loaded = setFlag('GtmLoaded', getFlag<Record<string, boolean>>('GtmLoaded') ?? {})\n if (loaded[containerId]) return\n loaded[containerId] = true\n push({ 'gtm.start': Date.now(), event: 'gtm.js' })\n loadScript(`${origin}/gtm.js?id=${encodeURIComponent(containerId)}`).catch(() =>\n emitError({\n scope: 'provider-script-load',\n message: `Failed to load Google Tag Manager container ${containerId}`,\n }),\n )\n },\n page(page) {\n if (typeof window === 'undefined') return\n push({\n event: 'page_view',\n page_location: page.url ?? window.location.href,\n page_path: page.path ?? window.location.pathname,\n page_title: page.title ?? document.title,\n })\n },\n track(event) {\n if (typeof window === 'undefined') return\n push({ ...event.params, ...event.options.providers?.gtm, event: event.name })\n },\n identify(identity, _traits, { consent }) {\n if (typeof window === 'undefined' || !consent?.analytics) return\n pushUserId(identity.userId)\n },\n reset() {\n if (typeof window === 'undefined') return\n pushUserId(undefined)\n },\n })\n}\n"]}
@@ -0,0 +1,38 @@
1
+ import { f as AnalyticsPlugin, h as AnalyticsEventPayload, U as UserIdentity, i as UserTraits, P as PluginContext } from '../types-BV_AFZKQ.js';
2
+
3
+ declare global {
4
+ interface Window {
5
+ hj?: (...args: unknown[]) => void;
6
+ _hjSettings?: {
7
+ hjid: number;
8
+ hjsv: number;
9
+ };
10
+ }
11
+ }
12
+ /** Options for `hotjar`. */
13
+ type HotjarOptions = {
14
+ /** A positive integer, as a number or a string of digits; `undefined` or `''` turns the provider off. */
15
+ siteId: number | string | undefined;
16
+ /** A positive integer, as a number or a string of digits; `undefined` or `''` turns the provider off. */
17
+ version: number | string | undefined;
18
+ /**
19
+ * Hotjar can't be stopped once loaded. On analytics withdrawal its cookies
20
+ * and storage are always deleted; `true` also reloads the page so recording stops.
21
+ */
22
+ reloadOnRevoke?: boolean;
23
+ };
24
+ /**
25
+ * Hotjar, after analytics consent.
26
+ * @deprecated Hotjar accounts are moving to Contentsquare; use `contentsquare()` once yours has.
27
+ */
28
+ declare function hotjar(options: HotjarOptions): AnalyticsPlugin | {
29
+ id: string;
30
+ requiredConsent: "analytics";
31
+ load(): void;
32
+ track(event: AnalyticsEventPayload): void;
33
+ identify(identity: UserIdentity, traits: UserTraits): void;
34
+ teardown(context: PluginContext): void;
35
+ reset(): void;
36
+ };
37
+
38
+ export { type HotjarOptions, hotjar };
@@ -0,0 +1,68 @@
1
+ import { expireCookies } from '../chunk-TVSZJLRC.js';
2
+ import { skippedPlugin, definePlugin, loadScript } from '../chunk-7XLGT6U3.js';
3
+ import { getFlag, setFlag } from '../chunk-R6I7OYQB.js';
4
+
5
+ // src/providers/hotjar.ts
6
+ function clearHotjarStorage() {
7
+ expireCookies((name) => name.startsWith("_hj"));
8
+ for (const storage of [localStorage, sessionStorage]) {
9
+ for (const key of Object.keys(storage)) {
10
+ if (/^_?hj/.test(key)) storage.removeItem(key);
11
+ }
12
+ }
13
+ }
14
+ function ensureHotjar(options) {
15
+ if (typeof window === "undefined" || getFlag("HotjarInitialized")) return;
16
+ window.hj = window.hj ?? ((...args) => {
17
+ window.hj.q = window.hj.q ?? [];
18
+ window.hj.q.push(args);
19
+ });
20
+ window._hjSettings = { hjid: options.siteId, hjsv: options.version };
21
+ void loadScript(`https://static.hotjar.com/c/hotjar-${options.siteId}.js?sv=${options.version}`).catch(
22
+ () => void 0
23
+ );
24
+ setFlag("HotjarInitialized", true);
25
+ }
26
+ var toPositiveInteger = (value) => typeof value === "number" ? value : /^\d+$/.test(value) ? Number(value) : Number.NaN;
27
+ function hotjar(options) {
28
+ const rawSiteId = typeof options.siteId === "string" ? options.siteId.trim() : options.siteId;
29
+ const rawVersion = typeof options.version === "string" ? options.version.trim() : options.version;
30
+ if (rawSiteId === void 0 || rawSiteId === "") return skippedPlugin("hotjar", "siteId");
31
+ if (rawVersion === void 0 || rawVersion === "") return skippedPlugin("hotjar", "version");
32
+ const siteId = toPositiveInteger(rawSiteId);
33
+ const version = toPositiveInteger(rawVersion);
34
+ if (!Number.isSafeInteger(siteId) || siteId <= 0 || !Number.isSafeInteger(version) || version <= 0) {
35
+ throw new Error(
36
+ `[consentlayer] Invalid Hotjar siteId or version: expected positive integers, received ${JSON.stringify(options.siteId)} and ${JSON.stringify(options.version)}.`
37
+ );
38
+ }
39
+ return definePlugin({
40
+ id: "hotjar",
41
+ requiredConsent: "analytics",
42
+ load() {
43
+ ensureHotjar({ siteId, version });
44
+ },
45
+ track(event) {
46
+ window.hj?.("event", event.name);
47
+ },
48
+ identify(identity, traits) {
49
+ const attributes = identity.userId && identity.email ? { ...traits, email: identity.email } : traits;
50
+ window.hj?.("identify", identity.userId ?? null, attributes);
51
+ },
52
+ teardown(context) {
53
+ if (typeof window === "undefined" || context.consent?.analytics) return;
54
+ try {
55
+ clearHotjarStorage();
56
+ } finally {
57
+ if (options.reloadOnRevoke) location.reload();
58
+ }
59
+ },
60
+ reset() {
61
+ window.hj?.("identify", null, {});
62
+ }
63
+ });
64
+ }
65
+
66
+ export { hotjar };
67
+ //# sourceMappingURL=hotjar.js.map
68
+ //# sourceMappingURL=hotjar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/providers/hotjar.ts"],"names":[],"mappings":"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","file":"hotjar.js","sourcesContent":["import { definePlugin, getFlag, loadScript, setFlag, skippedPlugin } from '../core/plugin'\nimport { expireCookies } from '../core/utils'\n\ndeclare global {\n interface Window {\n hj?: (...args: unknown[]) => void\n _hjSettings?: { hjid: number; hjsv: number }\n }\n}\n\n/** Options for `hotjar`. */\nexport type HotjarOptions = {\n /** A positive integer, as a number or a string of digits; `undefined` or `''` turns the provider off. */\n siteId: number | string | undefined\n /** A positive integer, as a number or a string of digits; `undefined` or `''` turns the provider off. */\n version: number | string | undefined\n /**\n * Hotjar can't be stopped once loaded. On analytics withdrawal its cookies\n * and storage are always deleted; `true` also reloads the page so recording stops.\n */\n reloadOnRevoke?: boolean\n}\n\nfunction clearHotjarStorage(): void {\n expireCookies((name) => name.startsWith('_hj'))\n for (const storage of [localStorage, sessionStorage]) {\n for (const key of Object.keys(storage)) {\n if (/^_?hj/.test(key)) storage.removeItem(key)\n }\n }\n}\n\nfunction ensureHotjar(options: { siteId: number; version: number }): void {\n if (typeof window === 'undefined' || getFlag('HotjarInitialized')) return\n window.hj =\n window.hj ??\n ((...args: unknown[]) => {\n ;(window.hj as unknown as { q?: unknown[] }).q = (window.hj as unknown as { q?: unknown[] }).q ?? []\n ;(window.hj as unknown as { q: unknown[] }).q.push(args)\n })\n window._hjSettings = { hjid: options.siteId, hjsv: options.version }\n\n void loadScript(`https://static.hotjar.com/c/hotjar-${options.siteId}.js?sv=${options.version}`).catch(\n () => undefined,\n )\n setFlag('HotjarInitialized', true)\n}\n\nconst toPositiveInteger = (value: number | string) =>\n typeof value === 'number' ? value : /^\\d+$/.test(value) ? Number(value) : Number.NaN\n\n/**\n * Hotjar, after analytics consent.\n * @deprecated Hotjar accounts are moving to Contentsquare; use `contentsquare()` once yours has.\n */\nexport function hotjar(options: HotjarOptions) {\n const rawSiteId = typeof options.siteId === 'string' ? options.siteId.trim() : options.siteId\n const rawVersion = typeof options.version === 'string' ? options.version.trim() : options.version\n if (rawSiteId === undefined || rawSiteId === '') return skippedPlugin('hotjar', 'siteId')\n if (rawVersion === undefined || rawVersion === '') return skippedPlugin('hotjar', 'version')\n const siteId = toPositiveInteger(rawSiteId)\n const version = toPositiveInteger(rawVersion)\n if (!Number.isSafeInteger(siteId) || siteId <= 0 || !Number.isSafeInteger(version) || version <= 0) {\n throw new Error(\n `[consentlayer] Invalid Hotjar siteId or version: expected positive integers, received ${JSON.stringify(options.siteId)} and ${JSON.stringify(options.version)}.`,\n )\n }\n return definePlugin({\n id: 'hotjar',\n requiredConsent: 'analytics',\n load() {\n ensureHotjar({ siteId, version })\n },\n track(event) {\n window.hj?.('event', event.name)\n },\n identify(identity, traits) {\n const attributes = identity.userId && identity.email ? { ...traits, email: identity.email } : traits\n window.hj?.('identify', identity.userId ?? null, attributes)\n },\n teardown(context) {\n if (typeof window === 'undefined' || context.consent?.analytics) return\n try {\n clearHotjarStorage()\n } finally {\n if (options.reloadOnRevoke) location.reload()\n }\n },\n reset() {\n window.hj?.('identify', null, {})\n },\n })\n}\n"]}
@@ -0,0 +1,42 @@
1
+ import { U as UserIdentity, h as AnalyticsEventPayload, f as AnalyticsPlugin, P as PluginContext, g as PageEvent } from '../types-BV_AFZKQ.js';
2
+
3
+ /** Translates a standard event into a Meta standard event, or a custom one. */
4
+ declare function toMetaEvent(event: AnalyticsEventPayload): {
5
+ method: 'track' | 'trackCustom';
6
+ name: string;
7
+ params: Record<string, unknown>;
8
+ };
9
+ /** Advanced matching; Meta accepts it only in `fbq('init')`. */
10
+ declare function metaUserData(identity: UserIdentity): Record<string, string>;
11
+
12
+ declare global {
13
+ interface Window {
14
+ fbq?: (method: string, eventNameOrPixelId?: string, params?: Record<string, unknown>, options?: {
15
+ eventID?: string;
16
+ }) => void;
17
+ _fbq?: typeof window.fbq;
18
+ }
19
+ }
20
+ /** Options for `meta`. */
21
+ type MetaOptions = {
22
+ /** `undefined` or `''` turns the provider off. */
23
+ pixelId: string | undefined;
24
+ locale?: string;
25
+ /**
26
+ * `true`: the pixel script loads at boot and is told consent is revoked.
27
+ * `false` (default): nothing loads until marketing consent is granted.
28
+ */
29
+ loadBeforeConsent?: boolean;
30
+ };
31
+ declare function meta(options: MetaOptions): AnalyticsPlugin | {
32
+ id: string;
33
+ requiredConsent: "marketing";
34
+ loadBeforeConsent: boolean;
35
+ load(loadContext: PluginContext): void;
36
+ consent(context: PluginContext): void;
37
+ teardown(context: PluginContext): void;
38
+ page(page: PageEvent, context: PluginContext): void;
39
+ track(event: AnalyticsEventPayload, context: PluginContext): void;
40
+ };
41
+
42
+ export { type MetaOptions, meta, metaUserData, toMetaEvent };
@@ -0,0 +1,65 @@
1
+ import { toMetaEvent, metaUserData } from '../chunk-LBEIEAJX.js';
2
+ export { metaUserData, toMetaEvent } from '../chunk-LBEIEAJX.js';
3
+ import { expireCookies } from '../chunk-TVSZJLRC.js';
4
+ import { assertValidMetaPixelId } from '../chunk-J3KUPF4R.js';
5
+ import { skippedPlugin, definePlugin, loadScript } from '../chunk-7XLGT6U3.js';
6
+ import { getFlag, setFlag } from '../chunk-R6I7OYQB.js';
7
+
8
+ // src/providers/meta.ts
9
+ var isOwnCookie = (name) => name === "_fbp" || name === "_fbc";
10
+ function meta(options) {
11
+ if (!options.pixelId?.trim()) return skippedPlugin("meta", "pixelId");
12
+ const pixelId = assertValidMetaPixelId(options.pixelId.trim());
13
+ const locale = options.locale ?? "en_US";
14
+ const isReady = () => typeof window !== "undefined" && typeof window.fbq === "function" && getFlag("MetaPixelInitialized") === true;
15
+ let matched = false;
16
+ let stale = false;
17
+ return definePlugin({
18
+ id: "meta",
19
+ requiredConsent: "marketing",
20
+ loadBeforeConsent: options.loadBeforeConsent ?? false,
21
+ load(loadContext) {
22
+ if (typeof window === "undefined" || getFlag("MetaPixelInitialized")) return;
23
+ const bootstrap = document.createElement("script");
24
+ bootstrap.setAttribute("data-consentlayer", "meta-pixel-bootstrap");
25
+ bootstrap.text = `!function(f,b,e,v,n){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
26
+ n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
27
+ n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];}(window);
28
+ fbq('consent', ${loadContext.consent?.marketing ? "'grant'" : "'revoke'"});
29
+ fbq('init', ${JSON.stringify(pixelId)}, ${JSON.stringify(metaUserData(loadContext.identity)).replace(/</g, "\\u003c")});`;
30
+ document.head.appendChild(bootstrap);
31
+ bootstrap.remove();
32
+ matched = Boolean(loadContext.identity.email || loadContext.identity.phone);
33
+ loadScript(`https://connect.facebook.net/${encodeURIComponent(locale)}/fbevents.js`).catch(
34
+ () => loadContext.emitError({
35
+ scope: "provider-script-load",
36
+ message: "Failed to load Meta Pixel (fbevents.js)"
37
+ })
38
+ );
39
+ setFlag("MetaPixelInitialized", true);
40
+ },
41
+ consent(context) {
42
+ if (typeof window !== "undefined" && context.consent && !context.consent.marketing) expireCookies(isOwnCookie);
43
+ if (!isReady()) return;
44
+ if (matched && !context.consent?.marketing) stale = true;
45
+ window.fbq?.("consent", context.consent?.marketing && !stale ? "grant" : "revoke");
46
+ },
47
+ teardown(context) {
48
+ if (typeof window === "undefined" || context.consent?.marketing) return;
49
+ expireCookies(isOwnCookie);
50
+ },
51
+ page(page, context) {
52
+ if (!isReady() || stale || !context.consent?.marketing) return;
53
+ window.fbq?.("track", "PageView", {}, { eventID: page.id });
54
+ },
55
+ track(event, context) {
56
+ if (!isReady() || stale || !context.consent?.marketing) return;
57
+ const { method, name, params } = toMetaEvent(event);
58
+ window.fbq?.(method, name, params, { eventID: event.id });
59
+ }
60
+ });
61
+ }
62
+
63
+ export { meta };
64
+ //# sourceMappingURL=meta.js.map
65
+ //# sourceMappingURL=meta.js.map