@d8a-tech/wt 0.1.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 (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +113 -0
  3. package/dist/browser_entry.d.ts +1 -0
  4. package/dist/cookies/consent.d.ts +4 -0
  5. package/dist/cookies/cookie_jar.d.ts +48 -0
  6. package/dist/cookies/cookie_settings.d.ts +23 -0
  7. package/dist/cookies/d8a_cookies.d.ts +71 -0
  8. package/dist/cookies/identity.d.ts +89 -0
  9. package/dist/cookies/session_manager.d.ts +36 -0
  10. package/dist/ga4/consent_wire.d.ts +38 -0
  11. package/dist/ga4/gtag_mapper.d.ts +46 -0
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.min.mjs +3 -0
  14. package/dist/index.min.mjs.map +7 -0
  15. package/dist/install.d.ts +23 -0
  16. package/dist/runtime/anon_cid.d.ts +13 -0
  17. package/dist/runtime/browser_context.d.ts +2 -0
  18. package/dist/runtime/config_resolver.d.ts +4 -0
  19. package/dist/runtime/consent_resolver.d.ts +7 -0
  20. package/dist/runtime/consent_update_ping.d.ts +10 -0
  21. package/dist/runtime/d8a_global.d.ts +11 -0
  22. package/dist/runtime/debug_logger.d.ts +6 -0
  23. package/dist/runtime/dispatcher.d.ts +18 -0
  24. package/dist/runtime/engagement_timer.d.ts +21 -0
  25. package/dist/runtime/enhanced_measurement.d.ts +14 -0
  26. package/dist/runtime/gtag_consent_bridge.d.ts +9 -0
  27. package/dist/runtime/linker.d.ts +53 -0
  28. package/dist/runtime/param_precedence.d.ts +27 -0
  29. package/dist/runtime/queue_consumer.d.ts +12 -0
  30. package/dist/runtime/runtime_names.d.ts +12 -0
  31. package/dist/runtime/state.d.ts +2 -0
  32. package/dist/runtime/uach.d.ts +31 -0
  33. package/dist/transport/send.d.ts +20 -0
  34. package/dist/types.d.ts +144 -0
  35. package/dist/utils/endpoint.d.ts +14 -0
  36. package/dist/utils/gtag_primitives.d.ts +8 -0
  37. package/dist/utils/is_record.d.ts +1 -0
  38. package/dist/utils/window_slots.d.ts +4 -0
  39. package/dist/web-tracker.min.js +3 -0
  40. package/dist/web-tracker.min.js.map +7 -0
  41. package/dist/wt.min.js +3 -0
  42. package/dist/wt.min.js.map +7 -0
  43. package/index.d.ts +167 -0
  44. package/package.json +62 -0
@@ -0,0 +1,23 @@
1
+ import { createQueueConsumer } from "./runtime/queue_consumer.ts";
2
+ import { createDispatcher } from "./runtime/dispatcher.ts";
3
+ import type { WindowLike } from "./types.ts";
4
+ type InstallResult = {
5
+ consumer: ReturnType<typeof createQueueConsumer>;
6
+ dispatcher: ReturnType<typeof createDispatcher>;
7
+ dataLayerName: string;
8
+ globalName: string;
9
+ };
10
+ /**
11
+ * Installs the tracker runtime and begins consuming queued `dataLayer` entries.
12
+ *
13
+ * This is the programmatic installer used by both consumption modes:
14
+ * - script-tag bundle (`src/browser_entry.ts`) installs on load
15
+ * - ESM usage (`src/index.ts`) can call this explicitly
16
+ */
17
+ export declare function installD8a({ windowRef, dataLayerName, globalName, gtagDataLayerName, }?: {
18
+ windowRef?: WindowLike;
19
+ dataLayerName?: unknown;
20
+ globalName?: unknown;
21
+ gtagDataLayerName?: unknown;
22
+ }): InstallResult;
23
+ export {};
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Generates a cookieless cid using the same logic as our normal `_d8a` cookie
3
+ * value generator, but without persisting it anywhere.
4
+ *
5
+ * This keeps the cid format consistent across consented and non-consented flows.
6
+ */
7
+ export declare function generateAnonCid(): string;
8
+ export declare function getOrCreateAnonCid({ windowRef, state, }: {
9
+ windowRef?: unknown;
10
+ state?: {
11
+ anonCid?: string | null;
12
+ } | null;
13
+ }): string;
@@ -0,0 +1,2 @@
1
+ import type { BrowserContext, WindowLike } from "../types.ts";
2
+ export declare function getBrowserContext(w: WindowLike): BrowserContext;
@@ -0,0 +1,4 @@
1
+ import type { PropertyConfig, RuntimeState } from "../types.ts";
2
+ export declare function getPropertyIds(getState: () => RuntimeState): string[];
3
+ export declare function getPropertyConfig(getState: () => RuntimeState, propertyId: string): PropertyConfig;
4
+ export declare function getSetParams(getState: () => RuntimeState): Record<string, unknown>;
@@ -0,0 +1,7 @@
1
+ import type { ConsentState, RuntimeState } from "../types.ts";
2
+ export declare function getEffectiveConsent(getState: () => RuntimeState): ConsentState;
3
+ export declare function getConsentParts(getState: () => RuntimeState): {
4
+ consent: ConsentState;
5
+ consentDefault: ConsentState;
6
+ consentUpdate: ConsentState;
7
+ };
@@ -0,0 +1,10 @@
1
+ import type { RuntimeState } from "../types.ts";
2
+ /**
3
+ * Tracks effective `analytics_storage` and emits a best-effort ping when it changes.
4
+ *
5
+ * Behavior:
6
+ * - Only fires if at least one property is configured.
7
+ * - Emits `user_engagement` with `consent_update=1` as an event param.
8
+ * - Uses effective consent (prefers mirrored gtag/GTM consent if present).
9
+ */
10
+ export declare function maybeEmitConsentUpdatePing(getState: () => RuntimeState): void;
@@ -0,0 +1,11 @@
1
+ export declare function createD8aGlobal({ windowRef, dataLayerName, }: {
2
+ windowRef: import("../types.ts").WindowLike;
3
+ dataLayerName?: string;
4
+ }): {
5
+ (..._args: unknown[]): void;
6
+ js(date: unknown): void;
7
+ config(propertyId: unknown, params: unknown): void;
8
+ event(eventName: unknown, params: unknown): void;
9
+ set(a: unknown, b?: unknown): void;
10
+ consent(action: unknown, state: unknown): void;
11
+ };
@@ -0,0 +1,6 @@
1
+ export declare function createDebugLogger({ enabled }: {
2
+ enabled?: boolean;
3
+ }): {
4
+ enabled: boolean;
5
+ log: (...args: unknown[]) => void;
6
+ };
@@ -0,0 +1,18 @@
1
+ import type { RuntimeState, WindowLike } from "../types.ts";
2
+ export declare function createDispatcher({ windowRef, getState, }: {
3
+ windowRef: WindowLike;
4
+ getState: () => RuntimeState;
5
+ }): {
6
+ enqueueEvent: (name: string, params: Record<string, unknown>) => void;
7
+ flush: ({ useBeacon }: {
8
+ useBeacon: boolean;
9
+ }) => Promise<{
10
+ sent: number;
11
+ }>;
12
+ flushNow: ({ useBeacon }?: {
13
+ useBeacon?: boolean;
14
+ }) => Promise<{
15
+ sent: number;
16
+ }>;
17
+ attachLifecycleFlush: () => void;
18
+ };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Engagement timer
3
+ *
4
+ * Counts time only while the page is:
5
+ * - focused
6
+ * - visible
7
+ * - active (not pagehidden)
8
+ *
9
+ */
10
+ import type { WindowLike } from "../types.ts";
11
+ export declare function createEngagementTimer({ windowRef, nowMs, }?: {
12
+ windowRef?: WindowLike;
13
+ nowMs?: () => number;
14
+ }): {
15
+ start: () => void;
16
+ peek: () => number;
17
+ getAndReset: () => number;
18
+ __internal: {
19
+ sync: () => void;
20
+ };
21
+ };
@@ -0,0 +1,14 @@
1
+ import type { RuntimeState, WindowLike } from "../types.ts";
2
+ export declare function createEnhancedMeasurement({ windowRef, getState, dispatcher, }: {
3
+ windowRef: WindowLike;
4
+ getState: () => RuntimeState;
5
+ dispatcher: {
6
+ enqueueEvent: (name: string, params: Record<string, unknown>) => void;
7
+ flushNow?: (opts?: {
8
+ useBeacon?: boolean;
9
+ }) => unknown;
10
+ };
11
+ }): {
12
+ start: () => void;
13
+ onConfig: () => void;
14
+ };
@@ -0,0 +1,9 @@
1
+ import type { RuntimeState, WindowLike } from "../types.ts";
2
+ export declare function createGtagConsentBridge({ windowRef, getState, dataLayerName, }: {
3
+ windowRef?: WindowLike;
4
+ getState: () => RuntimeState;
5
+ dataLayerName?: string;
6
+ }): {
7
+ start: () => void;
8
+ stop: () => void;
9
+ };
@@ -0,0 +1,53 @@
1
+ import type { IncomingDlPayload, LinkerConfig, LinkerUrlPosition, RuntimeState, WindowLike } from "../types.ts";
2
+ declare function resolveLinkerConfig(cfg: LinkerConfig): Required<LinkerConfig>;
3
+ declare function stripParamFromUrl(url: string, name: string): string;
4
+ declare function setParamInUrl(url: string, name: string, value: string, pos: LinkerUrlPosition): string;
5
+ declare function encodeDl({ cookies, ts, windowRef, }: {
6
+ cookies: Record<string, string>;
7
+ ts: number;
8
+ windowRef: WindowLike;
9
+ }): string;
10
+ declare function decodeDl({ value, windowRef, ttlMs, }: {
11
+ value: string;
12
+ windowRef: WindowLike;
13
+ ttlMs?: number;
14
+ }): IncomingDlPayload | null;
15
+ type SharedLinkerCoordinator = ReturnType<typeof createSharedLinkerCoordinator>;
16
+ declare function createSharedLinkerCoordinator({ windowRef }: {
17
+ windowRef: WindowLike;
18
+ }): {
19
+ start: () => void;
20
+ stop: () => void;
21
+ applyIncomingIfReady: () => void;
22
+ registerRuntime: (getState: () => RuntimeState) => () => void;
23
+ updateConfigPatch: (patch: unknown) => void;
24
+ __internal: {
25
+ encodeDl: typeof encodeDl;
26
+ decodeDl: typeof decodeDl;
27
+ decorateUrlIfNeeded: (rawUrl: string) => string;
28
+ stripParamFromUrl: typeof stripParamFromUrl;
29
+ setParamInUrl: typeof setParamInUrl;
30
+ resolveLinkerConfig: typeof resolveLinkerConfig;
31
+ };
32
+ };
33
+ export declare function getSharedLinkerCoordinator({ windowRef, }: {
34
+ windowRef: WindowLike;
35
+ }): SharedLinkerCoordinator;
36
+ export declare function createLinker({ windowRef, getState, }: {
37
+ windowRef: WindowLike;
38
+ getState: () => RuntimeState;
39
+ }): {
40
+ start: () => void;
41
+ stop: () => void;
42
+ applyIncomingIfReady: () => void;
43
+ updateConfigPatch: (patch: unknown) => void;
44
+ __internal: {
45
+ encodeDl: typeof encodeDl;
46
+ decodeDl: typeof decodeDl;
47
+ decorateUrlIfNeeded: (rawUrl: string) => string;
48
+ stripParamFromUrl: typeof stripParamFromUrl;
49
+ setParamInUrl: typeof setParamInUrl;
50
+ resolveLinkerConfig: typeof resolveLinkerConfig;
51
+ };
52
+ };
53
+ export {};
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Param resolution helpers with precedence rules:
3
+ * - event params (per-event) override
4
+ * - config params (per-property) fallback
5
+ * - set params (global defaults) fallback
6
+ *
7
+ * `resolveString` returns a trimmed, non-empty string or null.
8
+ * `resolveBool` returns a boolean or null.
9
+ */
10
+ export declare function resolveWithPrecedence({ key, eventParams, config, setParams, }: {
11
+ key: string;
12
+ eventParams?: Record<string, unknown> | null;
13
+ config?: Record<string, unknown> | null;
14
+ setParams?: Record<string, unknown> | null;
15
+ }): {} | null;
16
+ export declare function resolveString({ key, eventParams, config, setParams, }: {
17
+ key: string;
18
+ eventParams?: Record<string, unknown> | null;
19
+ config?: Record<string, unknown> | null;
20
+ setParams?: Record<string, unknown> | null;
21
+ }): string | null;
22
+ export declare function resolveBool({ key, eventParams, config, setParams, }: {
23
+ key: string;
24
+ eventParams?: Record<string, unknown> | null;
25
+ config?: Record<string, unknown> | null;
26
+ setParams?: Record<string, unknown> | null;
27
+ }): boolean | null;
@@ -0,0 +1,12 @@
1
+ import type { RuntimeState, WindowLike } from "../types.ts";
2
+ export declare function createQueueConsumer({ windowRef, dataLayerName, }: {
3
+ windowRef?: WindowLike;
4
+ dataLayerName?: string;
5
+ }): {
6
+ start: () => void;
7
+ getState: () => RuntimeState;
8
+ setOnEvent: (fn: RuntimeState["__onEvent"]) => void;
9
+ setOnConfig: (fn: RuntimeState["__onConfig"]) => void;
10
+ setOnSet: (fn: RuntimeState["__onSet"]) => void;
11
+ stop: () => void;
12
+ };
@@ -0,0 +1,12 @@
1
+ export declare function resolveDataLayerName({ windowRef, dataLayerName, }: {
2
+ windowRef?: import("../types.ts").WindowLike;
3
+ dataLayerName?: unknown;
4
+ }): string;
5
+ export declare function resolveGlobalName({ windowRef, globalName, }: {
6
+ windowRef?: import("../types.ts").WindowLike;
7
+ globalName?: unknown;
8
+ }): string;
9
+ export declare function resolveGtagDataLayerName({ windowRef, gtagDataLayerName, }: {
10
+ windowRef?: import("../types.ts").WindowLike;
11
+ gtagDataLayerName?: unknown;
12
+ }): string;
@@ -0,0 +1,2 @@
1
+ import type { RuntimeState } from "../types.ts";
2
+ export declare function createRuntimeState(): RuntimeState;
@@ -0,0 +1,31 @@
1
+ type UachFullVersion = {
2
+ brand?: string;
3
+ version?: string;
4
+ };
5
+ type Uach = {
6
+ architecture?: string;
7
+ bitness?: string;
8
+ fullVersionList?: UachFullVersion[];
9
+ mobile?: boolean;
10
+ model?: string;
11
+ platform?: string;
12
+ platformVersion?: string;
13
+ wow64?: boolean;
14
+ };
15
+ type UserAgentDataLike = {
16
+ getHighEntropyValues: (hints: readonly string[]) => Promise<Uach>;
17
+ };
18
+ type WindowLike = import("../types.ts").WindowLike;
19
+ type WindowUachCapable = WindowLike & {
20
+ navigator: NonNullable<WindowLike["navigator"]> & {
21
+ userAgentData: UserAgentDataLike;
22
+ };
23
+ };
24
+ export declare function hasUachApi(w: WindowLike): w is WindowUachCapable;
25
+ export declare function getUachCached(w: WindowLike): Uach | null;
26
+ export declare function fetchUach(w: WindowLike): Promise<Uach> | null;
27
+ export declare function uachToParams(uach: Uach | null): Record<string, string> | null;
28
+ export declare const __internal: {
29
+ HIGH_ENTROPY_KEYS: readonly ["platform", "platformVersion", "architecture", "model", "bitness", "fullVersionList", "wow64", "mobile"];
30
+ };
31
+ export {};
@@ -0,0 +1,20 @@
1
+ import type { WindowLikeTransport } from "../types.ts";
2
+ export declare function sendWithRetries({ url, windowRef, useBeacon, maxRetries, initialBackoffMs, }: {
3
+ url: string;
4
+ windowRef: WindowLikeTransport;
5
+ useBeacon: boolean;
6
+ maxRetries?: number;
7
+ initialBackoffMs?: number;
8
+ }): Promise<{
9
+ ok: boolean;
10
+ via: "beacon";
11
+ status?: undefined;
12
+ } | {
13
+ ok: boolean;
14
+ via: "fetch";
15
+ status: number;
16
+ } | {
17
+ ok: boolean;
18
+ via: "fetch";
19
+ status: null;
20
+ }>;
@@ -0,0 +1,144 @@
1
+ import type { SessionToken } from "./cookies/d8a_cookies.ts";
2
+ export type ConsentValue = "granted" | "denied";
3
+ export type ConsentKey = "ad_storage" | "analytics_storage" | "ad_user_data" | "ad_personalization";
4
+ export type ConsentState = Partial<Record<ConsentKey, ConsentValue>> & Record<string, unknown>;
5
+ export type RuntimeEvent = {
6
+ name: string;
7
+ params: Record<string, unknown>;
8
+ };
9
+ export type BrowserContext = {
10
+ dl: string;
11
+ dt: string;
12
+ dr: string;
13
+ dh: string;
14
+ ul: string;
15
+ sr: string;
16
+ };
17
+ export type PropertyConfig = Record<string, unknown> & {
18
+ server_container_url?: string;
19
+ send_page_view?: boolean;
20
+ };
21
+ export type RuntimeState = {
22
+ jsDate: Date | null;
23
+ pageLoadMs: number | null;
24
+ propertyIds: string[];
25
+ propertyConfigs: Record<string, PropertyConfig>;
26
+ primaryPropertyId: string;
27
+ consent: ConsentState;
28
+ consentDefault: ConsentState;
29
+ consentUpdate: ConsentState;
30
+ consentGtag: ConsentState;
31
+ consentDefaultGtag: ConsentState;
32
+ consentUpdateGtag: ConsentState;
33
+ userId: string | null;
34
+ set: Record<string, unknown>;
35
+ linker: LinkerConfig;
36
+ incomingDl: IncomingDlPayload | null;
37
+ events: RuntimeEvent[];
38
+ __onEvent: null | ((name: string, params: Record<string, unknown>) => void);
39
+ __onConfig: null | ((propertyId: string, patchCfg: Record<string, unknown>) => void);
40
+ __onSet: null | ((args: SetCommandArgs) => void);
41
+ hitCounter: number;
42
+ sessionEngagementMs: number;
43
+ sessionEngaged: boolean;
44
+ anonCid: string | null;
45
+ cookieAttrsSig: Record<string, string> | null;
46
+ sharedSessionTokens: SessionToken[] | null;
47
+ sharedSessionValue: string | null;
48
+ emInstalled: boolean;
49
+ emSiteSearchFired: boolean;
50
+ __lastEffectiveAnalyticsStorage: ConsentValue | undefined;
51
+ __consentPingInitScheduled?: boolean;
52
+ __consentPingInitDone?: boolean;
53
+ };
54
+ export type D8aTagData = Record<string, unknown> & {
55
+ __d8aInstallResults?: Record<string, unknown>;
56
+ __d8aInstallResultsByDataLayer?: Record<string, unknown>;
57
+ };
58
+ export type WindowLike = {
59
+ d8aDataLayerName?: unknown;
60
+ d8aGlobalName?: unknown;
61
+ d8aGtagDataLayerName?: unknown;
62
+ document: {
63
+ cookie: string;
64
+ title?: string;
65
+ hidden?: boolean;
66
+ visibilityState?: string;
67
+ referrer?: string;
68
+ currentScript?: unknown;
69
+ hasFocus?: () => boolean;
70
+ addEventListener?: (type: string, listener: (...args: unknown[]) => void, options?: boolean | {
71
+ capture?: boolean;
72
+ passive?: boolean;
73
+ once?: boolean;
74
+ }) => void;
75
+ removeEventListener?: (type: string, listener: (...args: unknown[]) => void, options?: boolean | {
76
+ capture?: boolean;
77
+ passive?: boolean;
78
+ once?: boolean;
79
+ }) => void;
80
+ };
81
+ location?: {
82
+ href?: string;
83
+ hostname?: string;
84
+ protocol?: string;
85
+ search?: string;
86
+ pathname?: string;
87
+ };
88
+ history?: {
89
+ replaceState?: (data: unknown, unused: string, url?: string) => void;
90
+ };
91
+ navigator?: {
92
+ language?: string;
93
+ userAgent?: string;
94
+ userLanguage?: string;
95
+ userAgentData?: unknown;
96
+ sendBeacon?: null | ((url: string | URL, data?: SendBeaconData) => boolean);
97
+ };
98
+ screen?: {
99
+ width?: number;
100
+ height?: number;
101
+ };
102
+ addEventListener?: (type: string, listener: (...args: unknown[]) => void, options?: boolean | {
103
+ capture?: boolean;
104
+ passive?: boolean;
105
+ once?: boolean;
106
+ }) => void;
107
+ removeEventListener?: (type: string, listener: (...args: unknown[]) => void, options?: boolean | {
108
+ capture?: boolean;
109
+ passive?: boolean;
110
+ once?: boolean;
111
+ }) => void;
112
+ setTimeout: (handler: (...args: unknown[]) => void, timeout?: number) => number;
113
+ clearTimeout: (id: number) => void;
114
+ d8a_tag_data?: D8aTagData;
115
+ hasFocus?: () => boolean;
116
+ };
117
+ export type LinkerUrlPosition = "query" | "fragment";
118
+ export type LinkerConfig = {
119
+ domains: string[];
120
+ accept_incoming?: boolean;
121
+ decorate_forms?: boolean;
122
+ url_position?: LinkerUrlPosition;
123
+ };
124
+ export type IncomingDlPayload = {
125
+ ts: number;
126
+ cookies: Record<string, string>;
127
+ };
128
+ export type SetCommandArgs = {
129
+ type: "object";
130
+ obj: Record<string, unknown>;
131
+ } | {
132
+ type: "field";
133
+ field: string;
134
+ value: unknown;
135
+ };
136
+ export type WindowLikeTransport = {
137
+ navigator?: {
138
+ sendBeacon?: null | ((url: string | URL, data?: SendBeaconData) => boolean);
139
+ };
140
+ fetch?: (url: string, opts?: unknown) => Promise<{
141
+ status?: number;
142
+ }>;
143
+ };
144
+ export type SendBeaconData = string | Blob | FormData | URLSearchParams | ArrayBuffer | null | undefined;
@@ -0,0 +1,14 @@
1
+ declare function isProbablyUrl(s: unknown): boolean;
2
+ /**
3
+ * Resolves the final tracking URL.
4
+ *
5
+ * `server_container_url` is required and is treated as the final endpoint URL.
6
+ * Examples:
7
+ * - Cloud: "https://global.t.d8a.tech/<property_id>/d/c"
8
+ * - On-prem: "https://example.org/d/c"
9
+ */
10
+ export declare function resolveTrackingUrl(configOrUrl?: unknown): string;
11
+ export declare const __internal: {
12
+ isProbablyUrl: typeof isProbablyUrl;
13
+ };
14
+ export {};
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Small helpers used to implement a gtag-compatible integration surface.
3
+ *
4
+ * Important: this code is a clean reimplementation of behaviors we need for compatibility
5
+ * (e.g. cookie domain candidate ordering).
6
+ */
7
+ export declare function getCookieDomainCandidates(hostname: unknown): string[];
8
+ export declare function stripTrailingSlashes(s: unknown): string;
@@ -0,0 +1 @@
1
+ export declare function isRecord(v: unknown): v is Record<string, unknown>;
@@ -0,0 +1,4 @@
1
+ import type { WindowLike } from "../types.ts";
2
+ export declare function getWindowSlot<T = unknown>(w: WindowLike, key: string): T | undefined;
3
+ export declare function setWindowSlot<T = unknown>(w: WindowLike, key: string, value: T): void;
4
+ export declare function ensureArraySlot<T = unknown>(w: WindowLike, key: string): T[];