@escape-game-over/atlas 0.1.59 → 0.1.61

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@escape-game-over/atlas",
3
- "version": "0.1.59",
3
+ "version": "0.1.61",
4
4
  "type": "module",
5
5
  "description": "Typed, data-driven machinery for static multi-locale, multi-deployment Astro sites.",
6
6
  "private": false,
@@ -1,7 +1,12 @@
1
1
  import { warn } from "../warn.ts";
2
2
  import { UUID } from "./snap-pixel.ts";
3
3
 
4
- /** AppLovin's Axon pixel. Marketing: it loads only once a visitor grants that. */
4
+ /**
5
+ * AppLovin's Axon pixel. Marketing: it loads only once a visitor grants that.
6
+ *
7
+ * @see https://support.applovin.com/en/growth/promoting-your-websites/axon-pixel-integration/axon-pixel-native-js
8
+ * @see https://support.applovin.com/en/growth/promoting-your-websites/axon-pixel-integration/events-and-objects
9
+ */
5
10
  export interface AxonPixelSettings {
6
11
  /** From the Axon dashboard: a UUID. */
7
12
  readonly eventKey: string;
@@ -0,0 +1,29 @@
1
+ import { warn } from "../warn.ts";
2
+
3
+ /**
4
+ * Microsoft Clarity. It has a cookieless mode, so like Google it loads for
5
+ * every visitor: without consent it records each page view on its own and sets
6
+ * no cookie, and the visitor's answer switches its cookies on or off.
7
+ *
8
+ * @see https://learn.microsoft.com/en-us/clarity/setup-and-installation/clarity-setup
9
+ * @see https://learn.microsoft.com/en-us/clarity/setup-and-installation/consent-mode
10
+ * @see https://learn.microsoft.com/en-us/clarity/setup-and-installation/clarity-consent-api-v2
11
+ */
12
+ export interface ClaritySettings {
13
+ /** From the Clarity project's settings: 10 lowercase letters and digits. */
14
+ readonly projectId: string;
15
+ }
16
+
17
+ /** Warns about an id that is not a project id: it would report nowhere. */
18
+ export function checkClarity(
19
+ clarity: ClaritySettings | undefined,
20
+ at: string
21
+ ): void {
22
+ if (clarity === undefined || /^[a-z0-9]{10}$/.test(clarity.projectId)) {
23
+ return;
24
+ }
25
+ warn(
26
+ at,
27
+ `Clarity project id "${clarity.projectId}" is not 10 lowercase letters and digits, so it reports nowhere. Copy it from the Clarity project's settings.`
28
+ );
29
+ }
@@ -1,6 +1,10 @@
1
1
  import { warn } from "../warn.ts";
2
2
 
3
- /** Drip's site tracking. Marketing: it loads only once a visitor grants that. */
3
+ /**
4
+ * Drip's site tracking. Marketing: it loads only once a visitor grants that.
5
+ *
6
+ * @see https://help.drip.com/hc/en-us/articles/4424702539789-Install-Your-JavaScript-Snippet
7
+ */
4
8
  export interface DripSettings {
5
9
  /** From Drip's Site Setup: digits, the `_dcs.account` of its snippet. */
6
10
  readonly accountId: string;
@@ -1,6 +1,7 @@
1
1
  import type { MetaTag } from "../meta/tag.ts";
2
2
  import type { HttpsUrl } from "../url.ts";
3
3
  import { type AxonPixelSettings, checkAxonPixel } from "./axon-pixel.ts";
4
+ import { type ClaritySettings, checkClarity } from "./clarity.ts";
4
5
  import { checkDrip, type DripSettings } from "./drip.ts";
5
6
  import { type GoogleSettings, googleEmits, googleScripts } from "./google.ts";
6
7
  import { checkMetaPixel, type MetaPixelSettings } from "./meta-pixel.ts";
@@ -29,6 +30,7 @@ import {
29
30
  */
30
31
 
31
32
  export type { AxonPixelSettings } from "./axon-pixel.ts";
33
+ export type { ClaritySettings } from "./clarity.ts";
32
34
  export type { DripSettings } from "./drip.ts";
33
35
  export {
34
36
  CONSENT_UPDATE_GLOBAL,
@@ -60,6 +62,8 @@ export interface AnalyticsSettings {
60
62
  readonly axon?: AxonPixelSettings;
61
63
  /** Loaded by `ConsentBanner`, after marketing is granted. */
62
64
  readonly drip?: DripSettings;
65
+ /** Loaded by `ConsentBanner` for every visitor, cookieless until analytics is granted. */
66
+ readonly clarity?: ClaritySettings;
63
67
  }
64
68
 
65
69
  /**
@@ -85,6 +89,7 @@ export function analyticsScripts(
85
89
  checkSnapPixel(analytics.snapchat, origin);
86
90
  checkAxonPixel(analytics.axon, origin);
87
91
  checkDrip(analytics.drip, origin);
92
+ checkClarity(analytics.clarity, origin);
88
93
  const google = googleScripts(analytics.google, origin);
89
94
  return {
90
95
  head: [...google.head, ...umamiScripts(analytics.umami)],
@@ -133,6 +138,9 @@ export function consentVendors(
133
138
  axon: analytics.axon !== undefined,
134
139
  // No consent mode at all.
135
140
  drip: analytics.drip !== undefined,
141
+ // Cookieless without consent, but the answer is what switches its
142
+ // cookies on, so it needs the banner.
143
+ clarity: analytics.clarity !== undefined,
136
144
  };
137
145
 
138
146
  return (Object.keys(VENDORS) as (keyof AnalyticsSettings)[]).filter(
@@ -1,7 +1,13 @@
1
1
  import type { NonEmpty } from "../types.ts";
2
2
  import { warn } from "../warn.ts";
3
3
 
4
- /** Meta's pixel. Marketing: it loads only once a visitor grants that. */
4
+ /**
5
+ * Meta's pixel. Marketing: it loads only once a visitor grants that.
6
+ *
7
+ * @see https://developers.facebook.com/docs/meta-pixel/get-started
8
+ * @see https://developers.facebook.com/docs/meta-pixel/reference
9
+ * @see https://developers.facebook.com/docs/meta-pixel/implementation/gdpr
10
+ */
5
11
  export interface MetaPixelSettings {
6
12
  /** From Events Manager: 15 or 16 digits. Several share one script. */
7
13
  readonly pixelIds: NonEmpty<string>;
@@ -1,7 +1,12 @@
1
1
  import type { NonEmpty } from "../types.ts";
2
2
  import { warn } from "../warn.ts";
3
3
 
4
- /** Snapchat's pixel. Marketing: it loads only once a visitor grants that. */
4
+ /**
5
+ * Snapchat's pixel. Marketing: it loads only once a visitor grants that.
6
+ *
7
+ * @see https://businesshelp.snapchat.com/s/article/pixel-direct-implementation
8
+ * @see https://forbusiness.snapchat.com/en-US/blog/the-snap-pixel-how-it-works-and-how-to-install-it
9
+ */
5
10
  export interface SnapPixelSettings {
6
11
  /** From Snap's Events Manager: a UUID. */
7
12
  readonly pixelIds: NonEmpty<string>;
@@ -1,7 +1,13 @@
1
1
  import type { NonEmpty } from "../types.ts";
2
2
  import { warn } from "../warn.ts";
3
3
 
4
- /** TikTok's pixel. Marketing: it loads only once a visitor grants that. */
4
+ /**
5
+ * TikTok's pixel. Marketing: it loads only once a visitor grants that.
6
+ *
7
+ * @see https://ads.tiktok.com/help/article/get-started-pixel
8
+ * @see https://ads.tiktok.com/help/article/standard-events-parameters
9
+ * @see https://ads.tiktok.com/help/article/how-to-use-cookies-with-tiktok-pixel
10
+ */
5
11
  export interface TikTokPixelSettings {
6
12
  /** From TikTok Events Manager: 20 capital letters and digits. */
7
13
  readonly pixelIds: NonEmpty<string>;
@@ -5,34 +5,37 @@
5
5
  * buttons.
6
6
  *
7
7
  * Renders nothing — and ships no script — when this site's analytics need no
8
- * permission. Also loads the vendors that wait for consent, such as the Meta, TikTok, Snap and Axon pixels and Drip. Otherwise the banner starts hidden and shows only to a visitor
8
+ * permission. Otherwise the banner starts hidden and shows only to a visitor
9
9
  * with no answer on record, or when a `data-consent-reopen` control is pressed.
10
+ *
11
+ * It also starts the vendors that wait on the answer — the Meta, TikTok, Snap
12
+ * and Axon pixels, Drip and Clarity — fetching each one's code only once its
13
+ * category is granted.
10
14
  */
11
15
  import type { HTMLAttributes } from "astro/types";
12
16
  import { type AnalyticsSettings, consentRequired } from "../analytics/index.ts";
13
- import AxonPixel from "./AxonPixel.astro";
14
17
  import ConsentElement from "./ConsentElement.astro";
15
- import Drip from "./Drip.astro";
16
- import MetaPixel from "./MetaPixel.astro";
17
- import SnapPixel from "./SnapPixel.astro";
18
- import TikTokPixel from "./TikTokPixel.astro";
18
+ import type { ConsentVendors } from "./consent-vendors.ts";
19
19
 
20
20
  type Props = HTMLAttributes<"div"> & {
21
21
  readonly analytics: AnalyticsSettings | undefined;
22
22
  };
23
23
 
24
24
  const { analytics, ...attrs } = Astro.props;
25
+ const vendors: ConsentVendors = {
26
+ meta: analytics?.meta,
27
+ tiktok: analytics?.tiktok,
28
+ snapchat: analytics?.snapchat,
29
+ axon: analytics?.axon,
30
+ drip: analytics?.drip,
31
+ clarity: analytics?.clarity,
32
+ };
25
33
  ---
26
34
 
27
35
  {consentRequired(analytics) && (
28
- <>
29
- <ConsentElement {...attrs}>
30
- <slot />
31
- </ConsentElement>
32
- {analytics?.meta && <MetaPixel settings={analytics.meta} />}
33
- {analytics?.tiktok && <TikTokPixel settings={analytics.tiktok} />}
34
- {analytics?.snapchat && <SnapPixel settings={analytics.snapchat} />}
35
- {analytics?.axon && <AxonPixel settings={analytics.axon} />}
36
- {analytics?.drip && <Drip settings={analytics.drip} />}
37
- </>
36
+ <ConsentElement
37
+ {...attrs}
38
+ vendors={vendors}>
39
+ <slot />
40
+ </ConsentElement>
38
41
  )}
@@ -3,15 +3,21 @@
3
3
  import type { HTMLAttributes } from "astro/types";
4
4
  import AtlasElement from "./AtlasElement.astro";
5
5
  import { consentBanner } from "./consent-element.ts";
6
+ import type { ConsentVendors } from "./consent-vendors.ts";
6
7
 
7
- type Props = HTMLAttributes<"div">;
8
+ type Props = HTMLAttributes<"div"> & {
9
+ readonly vendors: ConsentVendors;
10
+ };
11
+
12
+ const { vendors, ...attrs } = Astro.props;
8
13
  ---
9
14
 
10
15
  <script src="./consent-element.ts" />
11
16
 
12
17
  <AtlasElement
13
18
  of={consentBanner}
14
- {...Astro.props}
19
+ {...attrs}
20
+ data-vendors={JSON.stringify(vendors)}
15
21
  hidden
16
22
  role="dialog"
17
23
  aria-modal="false"
@@ -11,6 +11,11 @@
11
11
  *
12
12
  * Give the element its size; the map fills it.
13
13
  *
14
+ * @see https://developers.google.com/maps/documentation/javascript/load-maps-js-api
15
+ * @see https://developers.google.com/maps/documentation/javascript/advanced-markers/overview
16
+ * @see https://developers.google.com/maps/documentation/get-map-id
17
+ * @see https://developers.google.com/maps/billing-and-pricing/pricing
18
+ *
14
19
  * ```astro
15
20
  * <GoogleMap apiKey={key} mapId={id} colorScheme="DARK" places={[{ at, label, href }]} class="block h-96">
16
21
  * <button type="button">Show map</button>
@@ -1,8 +1,5 @@
1
1
  import { appendScript } from "./append-script.ts";
2
2
  import type { ConsentGated } from "./consent-gate.ts";
3
- import { whenGranted } from "./consent-gate.ts";
4
- import { element } from "./element.ts";
5
- import { data } from "./ref.ts";
6
3
 
7
4
  /** Axon's `axon`: a queue until its scripts arrive and replay it. */
8
5
  interface Axon {
@@ -62,11 +59,3 @@ export function axonPixel(eventKey: string): ConsentGated {
62
59
  },
63
60
  };
64
61
  }
65
-
66
- /** Internal to `AxonPixel.astro`. */
67
- export const axonPixelElement = element(
68
- "atlas-axon-pixel",
69
- ({ root, signal }) => {
70
- whenGranted("marketing", axonPixel(data(root, "event-key")), signal);
71
- }
72
- );
@@ -0,0 +1,15 @@
1
+ /** What `clarity.ts` defines once the page has loaded. */
2
+ interface ClarityWindow {
3
+ clarity?: (...args: unknown[]) => void;
4
+ }
5
+
6
+ /**
7
+ * Marks the current Clarity recording with a named event — a form sent, a
8
+ * booking opened — so recordings can be filtered by it.
9
+ *
10
+ * Sent with or without consent: Clarity records either way, and without it
11
+ * sets no cookie. Dropped before Clarity loads, or where it is not configured.
12
+ */
13
+ export function clarityEvent(name: string): void {
14
+ (window as unknown as ClarityWindow).clarity?.("event", name);
15
+ }
@@ -0,0 +1,53 @@
1
+ import { appendScript } from "./append-script.ts";
2
+ import type { ConsentChoices } from "./consent.ts";
3
+
4
+ /** Clarity's `clarity`: a queue until its script arrives and replays it. */
5
+ interface Clarity {
6
+ (...args: unknown[]): void;
7
+ q?: unknown[];
8
+ }
9
+
10
+ interface ClarityWindow {
11
+ clarity?: Clarity;
12
+ }
13
+
14
+ /** Clarity's own base code, as it defines `clarity` before the script loads. */
15
+ function defineClarity(): Clarity {
16
+ const global = window as unknown as ClarityWindow;
17
+ if (global.clarity !== undefined) return global.clarity;
18
+ // `arguments` is the list of whatever a call passed, which every regular
19
+ // `function` gets without declaring it (an arrow function does not). The
20
+ // queue stores that object rather than an array because Clarity's official
21
+ // snippet does: it is the shape Clarity promises its script will replay.
22
+ const clarity = function () {
23
+ // biome-ignore lint/complexity/noArguments: see above.
24
+ const args = arguments;
25
+ clarity.q ??= [];
26
+ clarity.q.push(args);
27
+ } as Clarity;
28
+ global.clarity = clarity;
29
+ return clarity;
30
+ }
31
+
32
+ /** Clarity's consent call, in its own spelling. */
33
+ const consentv2 = (choices: ConsentChoices) => ({
34
+ ad_Storage: choices.marketing,
35
+ analytics_Storage: choices.analytics,
36
+ });
37
+
38
+ /**
39
+ * Clarity, loaded with the first answer passed to what this returns, which
40
+ * `startVendors` calls with the answer so far and then every new one. Stated
41
+ * even when denied: a Clarity project set to use cookies by default would
42
+ * otherwise set them before anyone was asked.
43
+ */
44
+ export function clarity(projectId: string): (choices: ConsentChoices) => void {
45
+ let loaded = false;
46
+ return (choices) => {
47
+ const queue = defineClarity();
48
+ queue("consentv2", consentv2(choices));
49
+ if (loaded) return;
50
+ loaded = true;
51
+ appendScript(`https://www.clarity.ms/tag/${projectId}`);
52
+ };
53
+ }
@@ -13,6 +13,7 @@ export * from "./attribution.ts";
13
13
  export * from "./axon-event.ts";
14
14
  export * from "./background-video.ts";
15
15
  export * from "./carousel.ts";
16
+ export * from "./clarity-event.ts";
16
17
  // Reading only: a form that reports what the visitor agreed to. Recording an
17
18
  // answer stays with the banner.
18
19
  export { type ConsentRecord, readConsent } from "./consent.ts";
@@ -7,6 +7,7 @@ import {
7
7
  readConsent,
8
8
  recordConsent,
9
9
  } from "./consent.ts";
10
+ import { startVendors } from "./consent-vendors.ts";
10
11
  import { element } from "./element.ts";
11
12
  import { data, ref, refs } from "./ref.ts";
12
13
 
@@ -38,6 +39,8 @@ import { data, ref, refs } from "./ref.ts";
38
39
  * withdraw.
39
40
  */
40
41
  export const consentBanner = element(CONSENT_TAG, ({ root, signal }) => {
42
+ startVendors(JSON.parse(data(root, "vendors")), signal);
43
+
41
44
  const boxes = refs<HTMLInputElement>(root, "[data-consent-category]").map(
42
45
  (box) => {
43
46
  const category = data(box, "consent-category");
@@ -46,3 +46,24 @@ export function whenGranted(
46
46
  { signal }
47
47
  );
48
48
  }
49
+
50
+ /**
51
+ * For a vendor with a cookieless mode, which loads whatever the answer: after
52
+ * `load`, `apply` gets the answer so far (everything denied until one is
53
+ * given), then every answer given on this page.
54
+ */
55
+ export function withConsent(
56
+ apply: (choices: ConsentChoices) => void,
57
+ signal?: AbortSignal
58
+ ): void {
59
+ const start = () => {
60
+ apply(readConsent() ?? { analytics: "denied", marketing: "denied" });
61
+ addEventListener(
62
+ CONSENT_EVENT,
63
+ (event) => apply((event as CustomEvent<ConsentChoices>).detail),
64
+ { signal }
65
+ );
66
+ };
67
+ if (document.readyState === "complete") start();
68
+ else addEventListener("load", start, { once: true, signal });
69
+ }
@@ -0,0 +1,100 @@
1
+ import type { AnalyticsSettings } from "../analytics/index.ts";
2
+ import type { ConsentChoices } from "./consent.ts";
3
+ import { type ConsentGated, whenGranted, withConsent } from "./consent-gate.ts";
4
+ import { reportDevError } from "./dev-log.ts";
5
+
6
+ /** The vendors the banner starts: the analytics settings loaded in the browser. */
7
+ export type ConsentVendors = Pick<
8
+ AnalyticsSettings,
9
+ "meta" | "tiktok" | "snapchat" | "axon" | "drip" | "clarity"
10
+ >;
11
+
12
+ /**
13
+ * A vendor whose code is fetched on its first grant, not with the page. Calls
14
+ * wait on the one import, so they reach the vendor in the order they were made.
15
+ */
16
+ function lazy(load: () => Promise<ConsentGated>): ConsentGated {
17
+ let vendor: Promise<ConsentGated | undefined> | undefined;
18
+ const loaded = () => {
19
+ vendor ??= load().catch((error) => {
20
+ reportDevError("consent vendors", error);
21
+ return undefined;
22
+ });
23
+ return vendor;
24
+ };
25
+ return {
26
+ grant: () => {
27
+ loaded().then((ready) => ready?.grant());
28
+ },
29
+ revoke: () => {
30
+ vendor?.then((ready) => ready?.revoke?.());
31
+ },
32
+ };
33
+ }
34
+
35
+ /**
36
+ * Starts every configured vendor. Nothing vendor-specific is downloaded until
37
+ * its consent category is granted — except Clarity, which runs cookieless
38
+ * without consent and so loads with the page.
39
+ */
40
+ export function startVendors(
41
+ vendors: ConsentVendors,
42
+ signal?: AbortSignal
43
+ ): void {
44
+ const { meta, tiktok, snapchat, axon, drip, clarity } = vendors;
45
+ if (meta !== undefined) {
46
+ whenGranted(
47
+ "marketing",
48
+ lazy(async () =>
49
+ (await import("./meta-pixel.ts")).metaPixel(meta.pixelIds)
50
+ ),
51
+ signal
52
+ );
53
+ }
54
+ if (tiktok !== undefined) {
55
+ whenGranted(
56
+ "marketing",
57
+ lazy(async () =>
58
+ (await import("./tiktok-pixel.ts")).tiktokPixel(tiktok.pixelIds)
59
+ ),
60
+ signal
61
+ );
62
+ }
63
+ if (snapchat !== undefined) {
64
+ whenGranted(
65
+ "marketing",
66
+ lazy(async () =>
67
+ (await import("./snap-pixel.ts")).snapPixel(snapchat.pixelIds)
68
+ ),
69
+ signal
70
+ );
71
+ }
72
+ if (axon !== undefined) {
73
+ whenGranted(
74
+ "marketing",
75
+ lazy(async () =>
76
+ (await import("./axon-pixel.ts")).axonPixel(axon.eventKey)
77
+ ),
78
+ signal
79
+ );
80
+ }
81
+ if (drip !== undefined) {
82
+ whenGranted(
83
+ "marketing",
84
+ lazy(async () => (await import("./drip.ts")).drip(drip.accountId)),
85
+ signal
86
+ );
87
+ }
88
+ if (clarity !== undefined) {
89
+ let apply: Promise<((choices: ConsentChoices) => void) | undefined>;
90
+ withConsent((choices) => {
91
+ apply ??= import("./clarity.ts")
92
+ .then((module) => module.clarity(clarity.projectId))
93
+ .catch((error) => {
94
+ reportDevError("consent vendors", error);
95
+ return undefined;
96
+ });
97
+ apply.then((ready) => ready?.(choices));
98
+ }, signal);
99
+ }
100
+ }
package/src/astro/drip.ts CHANGED
@@ -1,8 +1,5 @@
1
1
  import { appendScript } from "./append-script.ts";
2
2
  import type { ConsentGated } from "./consent-gate.ts";
3
- import { whenGranted } from "./consent-gate.ts";
4
- import { element } from "./element.ts";
5
- import { data } from "./ref.ts";
6
3
 
7
4
  /** Drip's globals: a queue of calls, and the account its script reports to. */
8
5
  interface DripWindow {
@@ -30,8 +27,3 @@ export function drip(accountId: string): ConsentGated {
30
27
  },
31
28
  };
32
29
  }
33
-
34
- /** Internal to `Drip.astro`. */
35
- export const dripElement = element("atlas-drip", ({ root, signal }) => {
36
- whenGranted("marketing", drip(data(root, "account-id")), signal);
37
- });
@@ -1,8 +1,5 @@
1
1
  import { appendScript } from "./append-script.ts";
2
2
  import type { ConsentGated } from "./consent-gate.ts";
3
- import { whenGranted } from "./consent-gate.ts";
4
- import { element } from "./element.ts";
5
- import { data } from "./ref.ts";
6
3
 
7
4
  /** Meta's `fbq`: a queue until `fbevents.js` arrives and replays it. */
8
5
  interface Fbq {
@@ -64,15 +61,3 @@ export function metaPixel(pixelIds: readonly string[]): ConsentGated {
64
61
  },
65
62
  };
66
63
  }
67
-
68
- /** Internal to `MetaPixel.astro`. */
69
- export const metaPixelElement = element(
70
- "atlas-meta-pixel",
71
- ({ root, signal }) => {
72
- whenGranted(
73
- "marketing",
74
- metaPixel(JSON.parse(data(root, "pixel-ids"))),
75
- signal
76
- );
77
- }
78
- );
@@ -1,8 +1,5 @@
1
1
  import { appendScript } from "./append-script.ts";
2
2
  import type { ConsentGated } from "./consent-gate.ts";
3
- import { whenGranted } from "./consent-gate.ts";
4
- import { element } from "./element.ts";
5
- import { data } from "./ref.ts";
6
3
 
7
4
  /** Snap's `snaptr`: a queue until `scevent.min.js` arrives and replays it. */
8
5
  interface Snaptr {
@@ -55,15 +52,3 @@ export function snapPixel(pixelIds: readonly string[]): ConsentGated {
55
52
  },
56
53
  };
57
54
  }
58
-
59
- /** Internal to `SnapPixel.astro`. */
60
- export const snapPixelElement = element(
61
- "atlas-snap-pixel",
62
- ({ root, signal }) => {
63
- whenGranted(
64
- "marketing",
65
- snapPixel(JSON.parse(data(root, "pixel-ids"))),
66
- signal
67
- );
68
- }
69
- );
@@ -1,8 +1,5 @@
1
1
  import { appendScript } from "./append-script.ts";
2
2
  import type { ConsentGated } from "./consent-gate.ts";
3
- import { whenGranted } from "./consent-gate.ts";
4
- import { element } from "./element.ts";
5
- import { data } from "./ref.ts";
6
3
 
7
4
  /** TikTok's `ttq`: a queue of calls until `events.js` arrives and replays it. */
8
5
  interface Ttq extends Array<unknown> {
@@ -98,15 +95,3 @@ export function tiktokPixel(pixelIds: readonly string[]): ConsentGated {
98
95
  },
99
96
  };
100
97
  }
101
-
102
- /** Internal to `TikTokPixel.astro`. */
103
- export const tiktokPixelElement = element(
104
- "atlas-tiktok-pixel",
105
- ({ root, signal }) => {
106
- whenGranted(
107
- "marketing",
108
- tiktokPixel(JSON.parse(data(root, "pixel-ids"))),
109
- signal
110
- );
111
- }
112
- );
package/src/index.ts CHANGED
@@ -23,6 +23,7 @@ export {
23
23
  type AnalyticsSettings,
24
24
  type AnalyticsTags,
25
25
  type AxonPixelSettings,
26
+ type ClaritySettings,
26
27
  CONSENT_UPDATE_GLOBAL,
27
28
  type ConsentDefaults,
28
29
  type ConsentState,
@@ -1,18 +0,0 @@
1
- ---
2
- /** Internal to `ConsentBanner.astro`, so the pixel's script ships only where it is configured. */
3
- import type { AxonPixelSettings } from "../analytics/axon-pixel.ts";
4
- import AtlasElement from "./AtlasElement.astro";
5
- import { axonPixelElement } from "./axon-pixel.ts";
6
-
7
- interface Props {
8
- readonly settings: AxonPixelSettings;
9
- }
10
- ---
11
-
12
- <script src="./axon-pixel.ts" />
13
-
14
- <AtlasElement
15
- of={axonPixelElement}
16
- data-event-key={Astro.props.settings.eventKey}
17
- hidden
18
- />
@@ -1,18 +0,0 @@
1
- ---
2
- /** Internal to `ConsentBanner.astro`, so Drip's script ships only where it is configured. */
3
- import type { DripSettings } from "../analytics/drip.ts";
4
- import AtlasElement from "./AtlasElement.astro";
5
- import { dripElement } from "./drip.ts";
6
-
7
- interface Props {
8
- readonly settings: DripSettings;
9
- }
10
- ---
11
-
12
- <script src="./drip.ts" />
13
-
14
- <AtlasElement
15
- of={dripElement}
16
- data-account-id={Astro.props.settings.accountId}
17
- hidden
18
- />
@@ -1,18 +0,0 @@
1
- ---
2
- /** Internal to `ConsentBanner.astro`, so the pixel's script ships only where it is configured. */
3
- import type { MetaPixelSettings } from "../analytics/meta-pixel.ts";
4
- import AtlasElement from "./AtlasElement.astro";
5
- import { metaPixelElement } from "./meta-pixel.ts";
6
-
7
- interface Props {
8
- readonly settings: MetaPixelSettings;
9
- }
10
- ---
11
-
12
- <script src="./meta-pixel.ts" />
13
-
14
- <AtlasElement
15
- of={metaPixelElement}
16
- data-pixel-ids={JSON.stringify(Astro.props.settings.pixelIds)}
17
- hidden
18
- />
@@ -1,18 +0,0 @@
1
- ---
2
- /** Internal to `ConsentBanner.astro`, so the pixel's script ships only where it is configured. */
3
- import type { SnapPixelSettings } from "../analytics/snap-pixel.ts";
4
- import AtlasElement from "./AtlasElement.astro";
5
- import { snapPixelElement } from "./snap-pixel.ts";
6
-
7
- interface Props {
8
- readonly settings: SnapPixelSettings;
9
- }
10
- ---
11
-
12
- <script src="./snap-pixel.ts" />
13
-
14
- <AtlasElement
15
- of={snapPixelElement}
16
- data-pixel-ids={JSON.stringify(Astro.props.settings.pixelIds)}
17
- hidden
18
- />
@@ -1,18 +0,0 @@
1
- ---
2
- /** Internal to `ConsentBanner.astro`, so the pixel's script ships only where it is configured. */
3
- import type { TikTokPixelSettings } from "../analytics/tiktok-pixel.ts";
4
- import AtlasElement from "./AtlasElement.astro";
5
- import { tiktokPixelElement } from "./tiktok-pixel.ts";
6
-
7
- interface Props {
8
- readonly settings: TikTokPixelSettings;
9
- }
10
- ---
11
-
12
- <script src="./tiktok-pixel.ts" />
13
-
14
- <AtlasElement
15
- of={tiktokPixelElement}
16
- data-pixel-ids={JSON.stringify(Astro.props.settings.pixelIds)}
17
- hidden
18
- />