@xenia-martech/sdk-js 1.0.0-dev.26 → 1.0.0-dev.28

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 (37) hide show
  1. package/CSS_VARIABLES.md +7 -0
  2. package/README.md +71 -2
  3. package/dist/{actions-DFLoSXO_.d.cts → actions-CcBYV--3.d.cts} +242 -6
  4. package/dist/{actions-DFLoSXO_.d.ts → actions-CcBYV--3.d.ts} +242 -6
  5. package/dist/{chunk-3KYKKIIG.cjs → chunk-WYM4CQVG.cjs} +126 -4
  6. package/dist/chunk-WYM4CQVG.cjs.map +1 -0
  7. package/dist/{chunk-D37RD3UC.js → chunk-XXNDHYAS.js} +125 -5
  8. package/dist/chunk-XXNDHYAS.js.map +1 -0
  9. package/dist/client/index.cjs +613 -35
  10. package/dist/client/index.cjs.map +1 -1
  11. package/dist/client/index.d.cts +112 -3
  12. package/dist/client/index.d.ts +112 -3
  13. package/dist/client/index.js +610 -36
  14. package/dist/client/index.js.map +1 -1
  15. package/dist/client/react/index.cjs +609 -35
  16. package/dist/client/react/index.cjs.map +1 -1
  17. package/dist/client/react/index.d.cts +2 -2
  18. package/dist/client/react/index.d.ts +2 -2
  19. package/dist/client/react/index.js +609 -35
  20. package/dist/client/react/index.js.map +1 -1
  21. package/dist/{cookie-names-LgNDAreS.d.cts → cookie-names-B3b0XNc2.d.cts} +187 -1
  22. package/dist/{cookie-names-LgNDAreS.d.ts → cookie-names-B3b0XNc2.d.ts} +187 -1
  23. package/dist/index.cjs +23 -19
  24. package/dist/index.d.cts +23 -3
  25. package/dist/index.d.ts +23 -3
  26. package/dist/index.js +1 -1
  27. package/dist/server/index.cjs +53 -22
  28. package/dist/server/index.cjs.map +1 -1
  29. package/dist/server/index.d.cts +31 -11
  30. package/dist/server/index.d.ts +31 -11
  31. package/dist/server/index.js +43 -12
  32. package/dist/server/index.js.map +1 -1
  33. package/dist/xenia-sdk.iife.js +37 -3
  34. package/dist/xenia-sdk.iife.js.map +1 -1
  35. package/package.json +1 -1
  36. package/dist/chunk-3KYKKIIG.cjs.map +0 -1
  37. package/dist/chunk-D37RD3UC.js.map +0 -1
@@ -86,6 +86,23 @@ interface XeniaConfig {
86
86
  * cookie read via `getVisitorId()`.
87
87
  */
88
88
  visitorId?: string;
89
+ /**
90
+ * The ambient request context for a **server** client — the SDK-provided page/campaign fields
91
+ * (`path`, `query`, `url`, `referrer`, `utmSource`/`utmMedium`/`utmCampaign`/`utmContent`/`utmId`)
92
+ * that get attached to EVERY `resolve()`/`resolveBatch()`/`webhook()` made with this client, so
93
+ * journey rules can gate on `query.<name>` or `path` without any per-call wiring.
94
+ *
95
+ * The browser client needs nothing here — it reads these off `window.location` itself. A server
96
+ * runtime has no ambient request, so bind it once when constructing the per-request client:
97
+ *
98
+ * ```ts
99
+ * createXeniaServer({ …, context: contextFromUrl(currentUrl, referrer) })
100
+ * ```
101
+ *
102
+ * Lowest precedence: a per-call `context`/`identity` overrides it, and the SDK-owned `visitorId`
103
+ * still wins over everything.
104
+ */
105
+ context?: EventContext;
89
106
  /**
90
107
  * Persist the SDK visitor id to a first-party `xenia_vid` cookie so your
91
108
  * **same-origin** server can read it (`getVisitorId(cookieHeader)`) and bind
@@ -304,6 +321,23 @@ interface ResolveOptions {
304
321
  locale?: string;
305
322
  /** When true, ask the server to splice and return `content`. */
306
323
  merge?: boolean;
324
+ /**
325
+ * Caller-supplied identity fields (`deviceId`/`visitorId`/`customerId`/
326
+ * `email`), merged into `data` the same way `ServerWebhookOptions.identity`
327
+ * is merged for `webhook()`. Only relevant server-side — the browser client
328
+ * collects these ambiently instead and ignores this field. The SDK-owned
329
+ * `visitorId` (from `config.visitorId`) still wins over a value supplied
330
+ * here, same precedence as `webhook()`.
331
+ */
332
+ identity?: EventIdentity;
333
+ /**
334
+ * Caller-supplied page context (`path`/`query`/`url`/`referrer`/`utm*`),
335
+ * merged into `data` the same way `ServerWebhookOptions.context` is merged
336
+ * for `webhook()`. There's no ambient `window`/`document` server-side, so a
337
+ * server caller who wants these SDK-provided fields on a resolve() call
338
+ * must pass them explicitly (e.g. from the current request's headers).
339
+ */
340
+ context?: EventContext;
307
341
  }
308
342
  /** Body posted to `POST /api/events/v1/identify` — binds visitor to a known user. */
309
343
  interface IdentifyRequest {
@@ -347,6 +381,109 @@ interface MessageCta {
347
381
  /** Optional event fired when the CTA is clicked. */
348
382
  event?: string;
349
383
  }
384
+ /**
385
+ * Widget-specific rendering/interaction behavior for a message-placement action —
386
+ * ORTHOGONAL to `type` (the existing `banner|popup|modal|inline` placement enum, which
387
+ * stays exactly as-is). `type` says WHERE it renders; `widgetType` says WHAT it is.
388
+ * Keeping these separate is what lets `core/actions.ts`'s `MESSAGE_TYPES` allowlist AND
389
+ * the PHP SDK's `XeniaActions::KNOWN_TYPES` allowlist (same value set) stay completely
390
+ * unchanged — the PHP SDK needs zero code changes for widget support.
391
+ *
392
+ * `"standard"` (or omitted) is a plain message/popup — the existing card path, unmodified.
393
+ * A future 3rd widget type is one new literal here + one new dispatch-table entry in
394
+ * `client/widgets/index.ts`, not a rewrite.
395
+ */
396
+ type WidgetType = "standard" | "spin-wheel";
397
+ /**
398
+ * A prize/outcome segment shown to the visitor for a spin-wheel widget — label/color ONLY.
399
+ * Real weight/prize-code are marketer-authored server-side config (`config.widgetSubmissions`)
400
+ * and never leave the backend; they never appear here.
401
+ */
402
+ interface WidgetSegment {
403
+ id: string;
404
+ label: string;
405
+ colorHex?: string;
406
+ /** Marks this segment as a non-winning outcome (e.g. "Try Again") — drives which of the
407
+ * win/loss reveal screens (see WidgetStyle) the widget shows once this segment resolves. */
408
+ isLoss?: boolean;
409
+ }
410
+ /**
411
+ * The SAFE runtime envelope describing how a widget's captured form submission is
412
+ * dispatched — never a credential, never a prize weight/code (see the cross-repo
413
+ * contract). The SDK does not branch on `mode`'s value itself; it only follows whichever
414
+ * ref field is present (`flowRef` vs `bindingRef`) to pick an endpoint — `mode`/`ref` are
415
+ * otherwise relayed to the backend verbatim, uninterpreted.
416
+ */
417
+ interface WidgetFormSubmit {
418
+ /** `true` for spin-wheel (server must resolve an outcome before anything renders). */
419
+ requiresResolve: boolean;
420
+ /** `"journey"` or `"endpoint"` — informational only; the SDK never branches on this value. */
421
+ mode: "journey" | "endpoint" | (string & {});
422
+ /** Present only when `mode === "journey" && !requiresResolve` — the direct `/flow` fast path, no secret. */
423
+ flowRef?: string;
424
+ /** Present whenever `requiresResolve || mode === "endpoint"`. */
425
+ bindingRef?: string;
426
+ /**
427
+ * Minimum time (ms) to keep the success state visible after a submit resolves, before the
428
+ * card dismisses itself — configured marketer-side on the webhook-response node's
429
+ * Form-submission panel. The real dispatch typically responds in well under 100ms, which
430
+ * would otherwise make the card vanish before a visitor registers it succeeded at all.
431
+ * Defaults to 900 when absent (an older/unconfigured binding).
432
+ */
433
+ successDisplayMs?: number;
434
+ }
435
+ /**
436
+ * Per-action visual overrides for a widget's own window chrome (spin-wheel).
437
+ * Deliberately narrow — everything about the widget's actual CONTENT (spinner/win/loss screens)
438
+ * is full marketer/AI-authored HTML (`spinnerHtml`/`winHtml`/`lossHtml` on `XeniaAction`, same
439
+ * pattern as a popup's `body`), not a field here. This only covers the two things that live
440
+ * OUTSIDE that HTML, in the SDK's own generated chrome around it.
441
+ */
442
+ interface WidgetStyle {
443
+ /**
444
+ * Hides the built-in close (×) button. No spin-wheel renderer draws one of its own anymore
445
+ * (see `spin-wheel.ts`'s `html()`) — every screen's own `spinnerHtml`/`winHtml`/`lossHtml`
446
+ * carries its own close affordance, matched by the same heuristic every custom-HTML surface
447
+ * honors (`wireCloseAffordances`). Currently vestigial: not exposed in Content Studio's AI
448
+ * schema, and not read by any widget renderer's `html()`.
449
+ */
450
+ hideCloseButton?: boolean;
451
+ /** Hides the dimmed backdrop behind the modal/popup/banner. Defaults to shown. */
452
+ hideOverlay?: boolean;
453
+ }
454
+ /**
455
+ * Server-resolved outcome for a spin-wheel submission
456
+ * (`XeniaClient.submitWidgetForm`'s response). Absent for a plain form submit.
457
+ * `segmentId` matches an `id` in the action's `segments` list. Never the whole prize
458
+ * config (weight/internal code) — only what the backend decides is safe to reveal.
459
+ */
460
+ interface WidgetPrize {
461
+ segmentId?: string;
462
+ label?: string;
463
+ colorHex?: string;
464
+ [key: string]: JsonValue | undefined;
465
+ }
466
+ /**
467
+ * Response from a widget form submission (`XeniaClient.submitWidgetForm`) — whichever
468
+ * endpoint was actually hit (the `/flow` fast path or `/widget-submissions`), normalized
469
+ * to one shape. `actions` flows through the existing `parseActions()`/`ActionRenderer.apply()`
470
+ * pipeline unchanged; `prize` is read directly by the spin-wheel widget module to drive
471
+ * its reveal.
472
+ */
473
+ interface WidgetSubmitResponse {
474
+ status: number;
475
+ body: JsonValue;
476
+ actions: XeniaAction[];
477
+ prize?: WidgetPrize;
478
+ /** True when this visitor already played and the stored result is being replayed, not re-rolled. */
479
+ alreadyPlayed?: boolean;
480
+ /** Whether the configured dispatch (journey invoke / outbound endpoint call) actually fired. */
481
+ dispatched?: boolean;
482
+ /** Present when `dispatched` is false and the server attempted but failed the configured dispatch. */
483
+ dispatchError?: string;
484
+ widgetType?: WidgetType;
485
+ receivedAt: number;
486
+ }
350
487
  /**
351
488
  * A render directive the SDK executes in the browser. Marketers emit these in
352
489
  * a `webhook-response` node body under the `xeniaActions` key.
@@ -382,6 +519,43 @@ type XeniaAction = {
382
519
  /** Anchor within the placement (see {@link MessagePosition}). Defaults to the
383
520
  * SDK's built-in default per type (popup: bottom-right; banner: bottom). */
384
521
  position?: MessagePosition;
522
+ /** Orthogonal widget-behavior driver — see {@link WidgetType}. Omitted/`"standard"` renders
523
+ * exactly like today. */
524
+ widgetType?: WidgetType;
525
+ /** Label/color-only outcome segments for `spin-wheel` widgets. */
526
+ segments?: WidgetSegment[];
527
+ /** Safe form-submission envelope — see {@link WidgetFormSubmit}. Absent when the action has
528
+ * no capturable outcome. */
529
+ formSubmit?: WidgetFormSubmit;
530
+ /** Per-action visual overrides for the widget's own window — see {@link WidgetStyle}. */
531
+ style?: WidgetStyle;
532
+ /**
533
+ * Full marketer/AI-authored HTML for `spin-wheel`'s pre-spin face (title/subtitle/spin
534
+ * button/background — the whole visual design) — independent of the generic `html` field
535
+ * above, which spin-wheel never reads. The primary, ordinary way this screen
536
+ * is authored (same role `body` plays for a popup) — there is no separate generated
537
+ * template to fall back to. To keep the wheel and spin button working, include an element
538
+ * carrying `data-xenia-wheel-slot` (the SDK mounts the generated SVG wheel + pointer
539
+ * there) and one carrying `data-xenia-spin` (the SDK wires the spin click there) —
540
+ * omitting either simply drops that capability, same as any other custom-HTML widget.
541
+ */
542
+ spinnerHtml?: string;
543
+ /**
544
+ * Full marketer/AI-authored HTML for the win-reveal screen (`spin-wheel`), shown once a
545
+ * spin resolves to a non-`isLoss` segment — the primary way this screen is authored,
546
+ * same role as {@link spinnerHtml}. Include `data-xenia-wheel-prize` on any element to
547
+ * receive the resolved prize label, and `data-xenia-wheel-cta` on a button to wire its
548
+ * click to dismiss (same close-affordance heuristics as any other custom-HTML widget also
549
+ * apply here — see `wireCloseAffordances`).
550
+ */
551
+ winHtml?: string;
552
+ /**
553
+ * Full marketer/AI-authored HTML for the loss/"try again" screen, shown once a
554
+ * spin resolves to a segment with {@link WidgetSegment.isLoss} set. Same hooks and
555
+ * same primary-authoring role as {@link winHtml} (a losing outcome still has a `label`,
556
+ * e.g. "Try Again", so `data-xenia-wheel-prize` is still honored here).
557
+ */
558
+ lossHtml?: string;
385
559
  } | {
386
560
  type: "redirect";
387
561
  url: string;
@@ -418,6 +592,18 @@ declare class XeniaApi {
418
592
  * duplicate the journey run.
419
593
  */
420
594
  webhook(triggerId: string, data?: JsonValue, method?: "GET" | "POST"): Promise<WebhookResponse>;
595
+ /**
596
+ * Widget form submission — `POST /widget-submissions?ref={bindingRef}`. Used whenever the
597
+ * action's `formSubmit.requiresResolve` is true (spin-wheel, which must have a
598
+ * server-resolved outcome before anything renders) or `mode === "endpoint"` — the common
599
+ * plain-popup case (`mode === "journey" && !requiresResolve`) bypasses this entirely and calls
600
+ * {@link webhook} against `flowRef` instead (see `XeniaClient.submitWidgetForm`'s endpoint
601
+ * selection).
602
+ *
603
+ * Not retried (`noRetry: true`), styled like {@link webhook} — a retried POST must never
604
+ * double-fire a journey or double-resolve a prize server-side.
605
+ */
606
+ submitWidget(ref: string, body?: JsonValue): Promise<WidgetSubmitResponse>;
421
607
  /**
422
608
  * Unified event batch (max 100/request per the backend) — `POST /api/events/v1`.
423
609
  * Records analytics for every event and matches/advances a journey for any
@@ -494,4 +680,4 @@ declare const VISITOR_COOKIE: string;
494
680
  */
495
681
  declare const CONSENT_COOKIE: string;
496
682
 
497
- export { type AnalyticsContext as A, CONSENT_COOKIE as C, DEFAULT_PREFIX as D, type EventContext as E, type HttpMethod as H, type IdentifyRequest as I, type JsonValue as J, type MessageCta as M, type PersonalizationSwap as P, type RetryConfig as R, type TrackOptions as T, VISITOR_COOKIE as V, type WebhookResponse as W, type XeniaAction as X, type AnalyticsEventName as a, type AnalyticsIdentity as b, type AnalyticsIngestResponse as c, type ConsentState as d, type EventIdentity as e, type IdentifyResponse as f, type InteractionType as g, type JsonObject as h, type MessagePlacement as i, type ResolveBatchItem as j, type ResolveBatchResult as k, type ResolveOptions as l, type ResolveResult as m, XeniaApi as n, type XeniaConfig as o, type XeniaEvent as p, consentCookieName as q, parseActions as r, type CallerIdentity as s, visitorCookieName as v };
683
+ export { type AnalyticsContext as A, CONSENT_COOKIE as C, DEFAULT_PREFIX as D, type EventContext as E, type HttpMethod as H, type IdentifyRequest as I, type JsonValue as J, type MessageCta as M, type PersonalizationSwap as P, type RetryConfig as R, type TrackOptions as T, VISITOR_COOKIE as V, type WebhookResponse as W, type XeniaAction as X, type AnalyticsEventName as a, type AnalyticsIdentity as b, type AnalyticsIngestResponse as c, type ConsentState as d, type EventIdentity as e, type IdentifyResponse as f, type InteractionType as g, type JsonObject as h, type MessagePlacement as i, type ResolveBatchItem as j, type ResolveBatchResult as k, type ResolveOptions as l, type ResolveResult as m, type WidgetFormSubmit as n, type WidgetPrize as o, type WidgetSegment as p, type WidgetSubmitResponse as q, type WidgetType as r, XeniaApi as s, type XeniaConfig as t, type XeniaEvent as u, consentCookieName as v, parseActions as w, visitorCookieName as x, type CallerIdentity as y };
@@ -86,6 +86,23 @@ interface XeniaConfig {
86
86
  * cookie read via `getVisitorId()`.
87
87
  */
88
88
  visitorId?: string;
89
+ /**
90
+ * The ambient request context for a **server** client — the SDK-provided page/campaign fields
91
+ * (`path`, `query`, `url`, `referrer`, `utmSource`/`utmMedium`/`utmCampaign`/`utmContent`/`utmId`)
92
+ * that get attached to EVERY `resolve()`/`resolveBatch()`/`webhook()` made with this client, so
93
+ * journey rules can gate on `query.<name>` or `path` without any per-call wiring.
94
+ *
95
+ * The browser client needs nothing here — it reads these off `window.location` itself. A server
96
+ * runtime has no ambient request, so bind it once when constructing the per-request client:
97
+ *
98
+ * ```ts
99
+ * createXeniaServer({ …, context: contextFromUrl(currentUrl, referrer) })
100
+ * ```
101
+ *
102
+ * Lowest precedence: a per-call `context`/`identity` overrides it, and the SDK-owned `visitorId`
103
+ * still wins over everything.
104
+ */
105
+ context?: EventContext;
89
106
  /**
90
107
  * Persist the SDK visitor id to a first-party `xenia_vid` cookie so your
91
108
  * **same-origin** server can read it (`getVisitorId(cookieHeader)`) and bind
@@ -304,6 +321,23 @@ interface ResolveOptions {
304
321
  locale?: string;
305
322
  /** When true, ask the server to splice and return `content`. */
306
323
  merge?: boolean;
324
+ /**
325
+ * Caller-supplied identity fields (`deviceId`/`visitorId`/`customerId`/
326
+ * `email`), merged into `data` the same way `ServerWebhookOptions.identity`
327
+ * is merged for `webhook()`. Only relevant server-side — the browser client
328
+ * collects these ambiently instead and ignores this field. The SDK-owned
329
+ * `visitorId` (from `config.visitorId`) still wins over a value supplied
330
+ * here, same precedence as `webhook()`.
331
+ */
332
+ identity?: EventIdentity;
333
+ /**
334
+ * Caller-supplied page context (`path`/`query`/`url`/`referrer`/`utm*`),
335
+ * merged into `data` the same way `ServerWebhookOptions.context` is merged
336
+ * for `webhook()`. There's no ambient `window`/`document` server-side, so a
337
+ * server caller who wants these SDK-provided fields on a resolve() call
338
+ * must pass them explicitly (e.g. from the current request's headers).
339
+ */
340
+ context?: EventContext;
307
341
  }
308
342
  /** Body posted to `POST /api/events/v1/identify` — binds visitor to a known user. */
309
343
  interface IdentifyRequest {
@@ -347,6 +381,109 @@ interface MessageCta {
347
381
  /** Optional event fired when the CTA is clicked. */
348
382
  event?: string;
349
383
  }
384
+ /**
385
+ * Widget-specific rendering/interaction behavior for a message-placement action —
386
+ * ORTHOGONAL to `type` (the existing `banner|popup|modal|inline` placement enum, which
387
+ * stays exactly as-is). `type` says WHERE it renders; `widgetType` says WHAT it is.
388
+ * Keeping these separate is what lets `core/actions.ts`'s `MESSAGE_TYPES` allowlist AND
389
+ * the PHP SDK's `XeniaActions::KNOWN_TYPES` allowlist (same value set) stay completely
390
+ * unchanged — the PHP SDK needs zero code changes for widget support.
391
+ *
392
+ * `"standard"` (or omitted) is a plain message/popup — the existing card path, unmodified.
393
+ * A future 3rd widget type is one new literal here + one new dispatch-table entry in
394
+ * `client/widgets/index.ts`, not a rewrite.
395
+ */
396
+ type WidgetType = "standard" | "spin-wheel";
397
+ /**
398
+ * A prize/outcome segment shown to the visitor for a spin-wheel widget — label/color ONLY.
399
+ * Real weight/prize-code are marketer-authored server-side config (`config.widgetSubmissions`)
400
+ * and never leave the backend; they never appear here.
401
+ */
402
+ interface WidgetSegment {
403
+ id: string;
404
+ label: string;
405
+ colorHex?: string;
406
+ /** Marks this segment as a non-winning outcome (e.g. "Try Again") — drives which of the
407
+ * win/loss reveal screens (see WidgetStyle) the widget shows once this segment resolves. */
408
+ isLoss?: boolean;
409
+ }
410
+ /**
411
+ * The SAFE runtime envelope describing how a widget's captured form submission is
412
+ * dispatched — never a credential, never a prize weight/code (see the cross-repo
413
+ * contract). The SDK does not branch on `mode`'s value itself; it only follows whichever
414
+ * ref field is present (`flowRef` vs `bindingRef`) to pick an endpoint — `mode`/`ref` are
415
+ * otherwise relayed to the backend verbatim, uninterpreted.
416
+ */
417
+ interface WidgetFormSubmit {
418
+ /** `true` for spin-wheel (server must resolve an outcome before anything renders). */
419
+ requiresResolve: boolean;
420
+ /** `"journey"` or `"endpoint"` — informational only; the SDK never branches on this value. */
421
+ mode: "journey" | "endpoint" | (string & {});
422
+ /** Present only when `mode === "journey" && !requiresResolve` — the direct `/flow` fast path, no secret. */
423
+ flowRef?: string;
424
+ /** Present whenever `requiresResolve || mode === "endpoint"`. */
425
+ bindingRef?: string;
426
+ /**
427
+ * Minimum time (ms) to keep the success state visible after a submit resolves, before the
428
+ * card dismisses itself — configured marketer-side on the webhook-response node's
429
+ * Form-submission panel. The real dispatch typically responds in well under 100ms, which
430
+ * would otherwise make the card vanish before a visitor registers it succeeded at all.
431
+ * Defaults to 900 when absent (an older/unconfigured binding).
432
+ */
433
+ successDisplayMs?: number;
434
+ }
435
+ /**
436
+ * Per-action visual overrides for a widget's own window chrome (spin-wheel).
437
+ * Deliberately narrow — everything about the widget's actual CONTENT (spinner/win/loss screens)
438
+ * is full marketer/AI-authored HTML (`spinnerHtml`/`winHtml`/`lossHtml` on `XeniaAction`, same
439
+ * pattern as a popup's `body`), not a field here. This only covers the two things that live
440
+ * OUTSIDE that HTML, in the SDK's own generated chrome around it.
441
+ */
442
+ interface WidgetStyle {
443
+ /**
444
+ * Hides the built-in close (×) button. No spin-wheel renderer draws one of its own anymore
445
+ * (see `spin-wheel.ts`'s `html()`) — every screen's own `spinnerHtml`/`winHtml`/`lossHtml`
446
+ * carries its own close affordance, matched by the same heuristic every custom-HTML surface
447
+ * honors (`wireCloseAffordances`). Currently vestigial: not exposed in Content Studio's AI
448
+ * schema, and not read by any widget renderer's `html()`.
449
+ */
450
+ hideCloseButton?: boolean;
451
+ /** Hides the dimmed backdrop behind the modal/popup/banner. Defaults to shown. */
452
+ hideOverlay?: boolean;
453
+ }
454
+ /**
455
+ * Server-resolved outcome for a spin-wheel submission
456
+ * (`XeniaClient.submitWidgetForm`'s response). Absent for a plain form submit.
457
+ * `segmentId` matches an `id` in the action's `segments` list. Never the whole prize
458
+ * config (weight/internal code) — only what the backend decides is safe to reveal.
459
+ */
460
+ interface WidgetPrize {
461
+ segmentId?: string;
462
+ label?: string;
463
+ colorHex?: string;
464
+ [key: string]: JsonValue | undefined;
465
+ }
466
+ /**
467
+ * Response from a widget form submission (`XeniaClient.submitWidgetForm`) — whichever
468
+ * endpoint was actually hit (the `/flow` fast path or `/widget-submissions`), normalized
469
+ * to one shape. `actions` flows through the existing `parseActions()`/`ActionRenderer.apply()`
470
+ * pipeline unchanged; `prize` is read directly by the spin-wheel widget module to drive
471
+ * its reveal.
472
+ */
473
+ interface WidgetSubmitResponse {
474
+ status: number;
475
+ body: JsonValue;
476
+ actions: XeniaAction[];
477
+ prize?: WidgetPrize;
478
+ /** True when this visitor already played and the stored result is being replayed, not re-rolled. */
479
+ alreadyPlayed?: boolean;
480
+ /** Whether the configured dispatch (journey invoke / outbound endpoint call) actually fired. */
481
+ dispatched?: boolean;
482
+ /** Present when `dispatched` is false and the server attempted but failed the configured dispatch. */
483
+ dispatchError?: string;
484
+ widgetType?: WidgetType;
485
+ receivedAt: number;
486
+ }
350
487
  /**
351
488
  * A render directive the SDK executes in the browser. Marketers emit these in
352
489
  * a `webhook-response` node body under the `xeniaActions` key.
@@ -382,6 +519,43 @@ type XeniaAction = {
382
519
  /** Anchor within the placement (see {@link MessagePosition}). Defaults to the
383
520
  * SDK's built-in default per type (popup: bottom-right; banner: bottom). */
384
521
  position?: MessagePosition;
522
+ /** Orthogonal widget-behavior driver — see {@link WidgetType}. Omitted/`"standard"` renders
523
+ * exactly like today. */
524
+ widgetType?: WidgetType;
525
+ /** Label/color-only outcome segments for `spin-wheel` widgets. */
526
+ segments?: WidgetSegment[];
527
+ /** Safe form-submission envelope — see {@link WidgetFormSubmit}. Absent when the action has
528
+ * no capturable outcome. */
529
+ formSubmit?: WidgetFormSubmit;
530
+ /** Per-action visual overrides for the widget's own window — see {@link WidgetStyle}. */
531
+ style?: WidgetStyle;
532
+ /**
533
+ * Full marketer/AI-authored HTML for `spin-wheel`'s pre-spin face (title/subtitle/spin
534
+ * button/background — the whole visual design) — independent of the generic `html` field
535
+ * above, which spin-wheel never reads. The primary, ordinary way this screen
536
+ * is authored (same role `body` plays for a popup) — there is no separate generated
537
+ * template to fall back to. To keep the wheel and spin button working, include an element
538
+ * carrying `data-xenia-wheel-slot` (the SDK mounts the generated SVG wheel + pointer
539
+ * there) and one carrying `data-xenia-spin` (the SDK wires the spin click there) —
540
+ * omitting either simply drops that capability, same as any other custom-HTML widget.
541
+ */
542
+ spinnerHtml?: string;
543
+ /**
544
+ * Full marketer/AI-authored HTML for the win-reveal screen (`spin-wheel`), shown once a
545
+ * spin resolves to a non-`isLoss` segment — the primary way this screen is authored,
546
+ * same role as {@link spinnerHtml}. Include `data-xenia-wheel-prize` on any element to
547
+ * receive the resolved prize label, and `data-xenia-wheel-cta` on a button to wire its
548
+ * click to dismiss (same close-affordance heuristics as any other custom-HTML widget also
549
+ * apply here — see `wireCloseAffordances`).
550
+ */
551
+ winHtml?: string;
552
+ /**
553
+ * Full marketer/AI-authored HTML for the loss/"try again" screen, shown once a
554
+ * spin resolves to a segment with {@link WidgetSegment.isLoss} set. Same hooks and
555
+ * same primary-authoring role as {@link winHtml} (a losing outcome still has a `label`,
556
+ * e.g. "Try Again", so `data-xenia-wheel-prize` is still honored here).
557
+ */
558
+ lossHtml?: string;
385
559
  } | {
386
560
  type: "redirect";
387
561
  url: string;
@@ -418,6 +592,18 @@ declare class XeniaApi {
418
592
  * duplicate the journey run.
419
593
  */
420
594
  webhook(triggerId: string, data?: JsonValue, method?: "GET" | "POST"): Promise<WebhookResponse>;
595
+ /**
596
+ * Widget form submission — `POST /widget-submissions?ref={bindingRef}`. Used whenever the
597
+ * action's `formSubmit.requiresResolve` is true (spin-wheel, which must have a
598
+ * server-resolved outcome before anything renders) or `mode === "endpoint"` — the common
599
+ * plain-popup case (`mode === "journey" && !requiresResolve`) bypasses this entirely and calls
600
+ * {@link webhook} against `flowRef` instead (see `XeniaClient.submitWidgetForm`'s endpoint
601
+ * selection).
602
+ *
603
+ * Not retried (`noRetry: true`), styled like {@link webhook} — a retried POST must never
604
+ * double-fire a journey or double-resolve a prize server-side.
605
+ */
606
+ submitWidget(ref: string, body?: JsonValue): Promise<WidgetSubmitResponse>;
421
607
  /**
422
608
  * Unified event batch (max 100/request per the backend) — `POST /api/events/v1`.
423
609
  * Records analytics for every event and matches/advances a journey for any
@@ -494,4 +680,4 @@ declare const VISITOR_COOKIE: string;
494
680
  */
495
681
  declare const CONSENT_COOKIE: string;
496
682
 
497
- export { type AnalyticsContext as A, CONSENT_COOKIE as C, DEFAULT_PREFIX as D, type EventContext as E, type HttpMethod as H, type IdentifyRequest as I, type JsonValue as J, type MessageCta as M, type PersonalizationSwap as P, type RetryConfig as R, type TrackOptions as T, VISITOR_COOKIE as V, type WebhookResponse as W, type XeniaAction as X, type AnalyticsEventName as a, type AnalyticsIdentity as b, type AnalyticsIngestResponse as c, type ConsentState as d, type EventIdentity as e, type IdentifyResponse as f, type InteractionType as g, type JsonObject as h, type MessagePlacement as i, type ResolveBatchItem as j, type ResolveBatchResult as k, type ResolveOptions as l, type ResolveResult as m, XeniaApi as n, type XeniaConfig as o, type XeniaEvent as p, consentCookieName as q, parseActions as r, type CallerIdentity as s, visitorCookieName as v };
683
+ export { type AnalyticsContext as A, CONSENT_COOKIE as C, DEFAULT_PREFIX as D, type EventContext as E, type HttpMethod as H, type IdentifyRequest as I, type JsonValue as J, type MessageCta as M, type PersonalizationSwap as P, type RetryConfig as R, type TrackOptions as T, VISITOR_COOKIE as V, type WebhookResponse as W, type XeniaAction as X, type AnalyticsEventName as a, type AnalyticsIdentity as b, type AnalyticsIngestResponse as c, type ConsentState as d, type EventIdentity as e, type IdentifyResponse as f, type InteractionType as g, type JsonObject as h, type MessagePlacement as i, type ResolveBatchItem as j, type ResolveBatchResult as k, type ResolveOptions as l, type ResolveResult as m, type WidgetFormSubmit as n, type WidgetPrize as o, type WidgetSegment as p, type WidgetSubmitResponse as q, type WidgetType as r, XeniaApi as s, type XeniaConfig as t, type XeniaEvent as u, consentCookieName as v, parseActions as w, visitorCookieName as x, type CallerIdentity as y };
package/dist/index.cjs CHANGED
@@ -1,80 +1,84 @@
1
1
  'use strict';
2
2
 
3
- var chunk3KYKKIIG_cjs = require('./chunk-3KYKKIIG.cjs');
3
+ var chunkWYM4CQVG_cjs = require('./chunk-WYM4CQVG.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "CONSENT_COOKIE", {
8
8
  enumerable: true,
9
- get: function () { return chunk3KYKKIIG_cjs.CONSENT_COOKIE; }
9
+ get: function () { return chunkWYM4CQVG_cjs.CONSENT_COOKIE; }
10
10
  });
11
11
  Object.defineProperty(exports, "DEFAULT_PREFIX", {
12
12
  enumerable: true,
13
- get: function () { return chunk3KYKKIIG_cjs.DEFAULT_PREFIX; }
13
+ get: function () { return chunkWYM4CQVG_cjs.DEFAULT_PREFIX; }
14
14
  });
15
15
  Object.defineProperty(exports, "HttpClient", {
16
16
  enumerable: true,
17
- get: function () { return chunk3KYKKIIG_cjs.HttpClient; }
17
+ get: function () { return chunkWYM4CQVG_cjs.HttpClient; }
18
18
  });
19
19
  Object.defineProperty(exports, "HttpError", {
20
20
  enumerable: true,
21
- get: function () { return chunk3KYKKIIG_cjs.HttpError; }
21
+ get: function () { return chunkWYM4CQVG_cjs.HttpError; }
22
22
  });
23
23
  Object.defineProperty(exports, "LocalStorageResponseStore", {
24
24
  enumerable: true,
25
- get: function () { return chunk3KYKKIIG_cjs.LocalStorageResponseStore; }
25
+ get: function () { return chunkWYM4CQVG_cjs.LocalStorageResponseStore; }
26
26
  });
27
27
  Object.defineProperty(exports, "MAX_EVENT_ID_LENGTH", {
28
28
  enumerable: true,
29
- get: function () { return chunk3KYKKIIG_cjs.MAX_EVENT_ID_LENGTH; }
29
+ get: function () { return chunkWYM4CQVG_cjs.MAX_EVENT_ID_LENGTH; }
30
30
  });
31
31
  Object.defineProperty(exports, "MemoryResponseStore", {
32
32
  enumerable: true,
33
- get: function () { return chunk3KYKKIIG_cjs.MemoryResponseStore; }
33
+ get: function () { return chunkWYM4CQVG_cjs.MemoryResponseStore; }
34
34
  });
35
35
  Object.defineProperty(exports, "VISITOR_COOKIE", {
36
36
  enumerable: true,
37
- get: function () { return chunk3KYKKIIG_cjs.VISITOR_COOKIE; }
37
+ get: function () { return chunkWYM4CQVG_cjs.VISITOR_COOKIE; }
38
38
  });
39
39
  Object.defineProperty(exports, "XeniaApi", {
40
40
  enumerable: true,
41
- get: function () { return chunk3KYKKIIG_cjs.XeniaApi; }
41
+ get: function () { return chunkWYM4CQVG_cjs.XeniaApi; }
42
42
  });
43
43
  Object.defineProperty(exports, "buildUrl", {
44
44
  enumerable: true,
45
- get: function () { return chunk3KYKKIIG_cjs.buildUrl; }
45
+ get: function () { return chunkWYM4CQVG_cjs.buildUrl; }
46
46
  });
47
47
  Object.defineProperty(exports, "consentCookieName", {
48
48
  enumerable: true,
49
- get: function () { return chunk3KYKKIIG_cjs.consentCookieName; }
49
+ get: function () { return chunkWYM4CQVG_cjs.consentCookieName; }
50
+ });
51
+ Object.defineProperty(exports, "contextFromUrl", {
52
+ enumerable: true,
53
+ get: function () { return chunkWYM4CQVG_cjs.contextFromUrl; }
50
54
  });
51
55
  Object.defineProperty(exports, "extractContentSwaps", {
52
56
  enumerable: true,
53
- get: function () { return chunk3KYKKIIG_cjs.extractContentSwaps; }
57
+ get: function () { return chunkWYM4CQVG_cjs.extractContentSwaps; }
54
58
  });
55
59
  Object.defineProperty(exports, "generateUlid", {
56
60
  enumerable: true,
57
- get: function () { return chunk3KYKKIIG_cjs.generateUlid; }
61
+ get: function () { return chunkWYM4CQVG_cjs.generateUlid; }
58
62
  });
59
63
  Object.defineProperty(exports, "isBrowser", {
60
64
  enumerable: true,
61
- get: function () { return chunk3KYKKIIG_cjs.isBrowser; }
65
+ get: function () { return chunkWYM4CQVG_cjs.isBrowser; }
62
66
  });
63
67
  Object.defineProperty(exports, "parseActions", {
64
68
  enumerable: true,
65
- get: function () { return chunk3KYKKIIG_cjs.parseActions; }
69
+ get: function () { return chunkWYM4CQVG_cjs.parseActions; }
66
70
  });
67
71
  Object.defineProperty(exports, "spliceSlots", {
68
72
  enumerable: true,
69
- get: function () { return chunk3KYKKIIG_cjs.spliceSlots; }
73
+ get: function () { return chunkWYM4CQVG_cjs.spliceSlots; }
70
74
  });
71
75
  Object.defineProperty(exports, "toEventId", {
72
76
  enumerable: true,
73
- get: function () { return chunk3KYKKIIG_cjs.toEventId; }
77
+ get: function () { return chunkWYM4CQVG_cjs.toEventId; }
74
78
  });
75
79
  Object.defineProperty(exports, "visitorCookieName", {
76
80
  enumerable: true,
77
- get: function () { return chunk3KYKKIIG_cjs.visitorCookieName; }
81
+ get: function () { return chunkWYM4CQVG_cjs.visitorCookieName; }
78
82
  });
79
83
  //# sourceMappingURL=index.cjs.map
80
84
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as RetryConfig, H as HttpMethod, J as JsonValue, W as WebhookResponse } from './cookie-names-LgNDAreS.cjs';
2
- export { A as AnalyticsContext, a as AnalyticsEventName, b as AnalyticsIdentity, c as AnalyticsIngestResponse, C as CONSENT_COOKIE, d as ConsentState, D as DEFAULT_PREFIX, E as EventContext, e as EventIdentity, I as IdentifyRequest, f as IdentifyResponse, g as InteractionType, h as JsonObject, M as MessageCta, i as MessagePlacement, P as PersonalizationSwap, j as ResolveBatchItem, k as ResolveBatchResult, l as ResolveOptions, m as ResolveResult, T as TrackOptions, V as VISITOR_COOKIE, X as XeniaAction, n as XeniaApi, o as XeniaConfig, p as XeniaEvent, q as consentCookieName, r as parseActions, v as visitorCookieName } from './cookie-names-LgNDAreS.cjs';
1
+ import { R as RetryConfig, H as HttpMethod, J as JsonValue, E as EventContext, W as WebhookResponse } from './cookie-names-B3b0XNc2.cjs';
2
+ export { A as AnalyticsContext, a as AnalyticsEventName, b as AnalyticsIdentity, c as AnalyticsIngestResponse, C as CONSENT_COOKIE, d as ConsentState, D as DEFAULT_PREFIX, e as EventIdentity, I as IdentifyRequest, f as IdentifyResponse, g as InteractionType, h as JsonObject, M as MessageCta, i as MessagePlacement, P as PersonalizationSwap, j as ResolveBatchItem, k as ResolveBatchResult, l as ResolveOptions, m as ResolveResult, T as TrackOptions, V as VISITOR_COOKIE, n as WidgetFormSubmit, o as WidgetPrize, p as WidgetSegment, q as WidgetSubmitResponse, r as WidgetType, X as XeniaAction, s as XeniaApi, t as XeniaConfig, u as XeniaEvent, v as consentCookieName, w as parseActions, x as visitorCookieName } from './cookie-names-B3b0XNc2.cjs';
3
3
 
4
4
  /** Returns true when running in a browser environment (SSR-safe). */
5
5
  declare function isBrowser(): boolean;
@@ -121,6 +121,26 @@ declare function spliceSlots(slots: Record<string, JsonValue>, swaps: ContentSwa
121
121
  /** Extract `xeniaContentSwaps` from a webhook-response body, if present and well-formed. */
122
122
  declare function extractContentSwaps(body: JsonValue): ContentSwap[] | undefined;
123
123
 
124
+ /**
125
+ * Derive the SDK-provided page/campaign fields from a URL — the server-side counterpart to the
126
+ * browser client's `Identity.collectContext()`, which reads the same fields off `window.location`.
127
+ *
128
+ * Exists because a server runtime has no ambient `window`: a Node client is constructed per request,
129
+ * so the one thing it needs handed over is the URL being served. Everything a journey rule can
130
+ * reference — `path`, `query.<name>`, `url`, `referrer`, `utmSource`/`utmMedium`/`utmCampaign`/
131
+ * `utmContent`/`utmId` — is derived here rather than by each app, so a server-rendered page gets the
132
+ * same field set a browser page does without hand-rolling UTM parsing at every call site.
133
+ *
134
+ * Field names and semantics deliberately mirror `collectContext()` exactly: `query` is the flattened
135
+ * search params, UTMs come from the standard `utm_*` params, and absent values are omitted rather
136
+ * than set to `""` (a blank string is a value a condition could accidentally match).
137
+ *
138
+ * @param url Absolute URL of the request being served (e.g. `https://shop.example/product/x?ref=a`).
139
+ * A relative or unparseable value yields an empty context rather than throwing.
140
+ * @param referrer Optional referring URL, typically the request's `Referer` header.
141
+ */
142
+ declare function contextFromUrl(url: string | null | undefined, referrer?: string | null): EventContext;
143
+
124
144
  /**
125
145
  * Persists webhook responses the SDK receives, keyed by an arbitrary string
126
146
  * (typically the eventId, triggerId, or journeyId). Lets the app read back the
@@ -155,4 +175,4 @@ declare class LocalStorageResponseStore implements ResponseStore {
155
175
  clear(): void;
156
176
  }
157
177
 
158
- export { type ContentSwap, HttpClient, type HttpClientOptions, HttpError, HttpMethod, type HttpResult, JsonValue, LocalStorageResponseStore, MAX_EVENT_ID_LENGTH, MemoryResponseStore, type RequestOptions, type ResponseStore, RetryConfig, WebhookResponse, buildUrl, extractContentSwaps, generateUlid, isBrowser, spliceSlots, toEventId };
178
+ export { type ContentSwap, EventContext, HttpClient, type HttpClientOptions, HttpError, HttpMethod, type HttpResult, JsonValue, LocalStorageResponseStore, MAX_EVENT_ID_LENGTH, MemoryResponseStore, type RequestOptions, type ResponseStore, RetryConfig, WebhookResponse, buildUrl, contextFromUrl, extractContentSwaps, generateUlid, isBrowser, spliceSlots, toEventId };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as RetryConfig, H as HttpMethod, J as JsonValue, W as WebhookResponse } from './cookie-names-LgNDAreS.js';
2
- export { A as AnalyticsContext, a as AnalyticsEventName, b as AnalyticsIdentity, c as AnalyticsIngestResponse, C as CONSENT_COOKIE, d as ConsentState, D as DEFAULT_PREFIX, E as EventContext, e as EventIdentity, I as IdentifyRequest, f as IdentifyResponse, g as InteractionType, h as JsonObject, M as MessageCta, i as MessagePlacement, P as PersonalizationSwap, j as ResolveBatchItem, k as ResolveBatchResult, l as ResolveOptions, m as ResolveResult, T as TrackOptions, V as VISITOR_COOKIE, X as XeniaAction, n as XeniaApi, o as XeniaConfig, p as XeniaEvent, q as consentCookieName, r as parseActions, v as visitorCookieName } from './cookie-names-LgNDAreS.js';
1
+ import { R as RetryConfig, H as HttpMethod, J as JsonValue, E as EventContext, W as WebhookResponse } from './cookie-names-B3b0XNc2.js';
2
+ export { A as AnalyticsContext, a as AnalyticsEventName, b as AnalyticsIdentity, c as AnalyticsIngestResponse, C as CONSENT_COOKIE, d as ConsentState, D as DEFAULT_PREFIX, e as EventIdentity, I as IdentifyRequest, f as IdentifyResponse, g as InteractionType, h as JsonObject, M as MessageCta, i as MessagePlacement, P as PersonalizationSwap, j as ResolveBatchItem, k as ResolveBatchResult, l as ResolveOptions, m as ResolveResult, T as TrackOptions, V as VISITOR_COOKIE, n as WidgetFormSubmit, o as WidgetPrize, p as WidgetSegment, q as WidgetSubmitResponse, r as WidgetType, X as XeniaAction, s as XeniaApi, t as XeniaConfig, u as XeniaEvent, v as consentCookieName, w as parseActions, x as visitorCookieName } from './cookie-names-B3b0XNc2.js';
3
3
 
4
4
  /** Returns true when running in a browser environment (SSR-safe). */
5
5
  declare function isBrowser(): boolean;
@@ -121,6 +121,26 @@ declare function spliceSlots(slots: Record<string, JsonValue>, swaps: ContentSwa
121
121
  /** Extract `xeniaContentSwaps` from a webhook-response body, if present and well-formed. */
122
122
  declare function extractContentSwaps(body: JsonValue): ContentSwap[] | undefined;
123
123
 
124
+ /**
125
+ * Derive the SDK-provided page/campaign fields from a URL — the server-side counterpart to the
126
+ * browser client's `Identity.collectContext()`, which reads the same fields off `window.location`.
127
+ *
128
+ * Exists because a server runtime has no ambient `window`: a Node client is constructed per request,
129
+ * so the one thing it needs handed over is the URL being served. Everything a journey rule can
130
+ * reference — `path`, `query.<name>`, `url`, `referrer`, `utmSource`/`utmMedium`/`utmCampaign`/
131
+ * `utmContent`/`utmId` — is derived here rather than by each app, so a server-rendered page gets the
132
+ * same field set a browser page does without hand-rolling UTM parsing at every call site.
133
+ *
134
+ * Field names and semantics deliberately mirror `collectContext()` exactly: `query` is the flattened
135
+ * search params, UTMs come from the standard `utm_*` params, and absent values are omitted rather
136
+ * than set to `""` (a blank string is a value a condition could accidentally match).
137
+ *
138
+ * @param url Absolute URL of the request being served (e.g. `https://shop.example/product/x?ref=a`).
139
+ * A relative or unparseable value yields an empty context rather than throwing.
140
+ * @param referrer Optional referring URL, typically the request's `Referer` header.
141
+ */
142
+ declare function contextFromUrl(url: string | null | undefined, referrer?: string | null): EventContext;
143
+
124
144
  /**
125
145
  * Persists webhook responses the SDK receives, keyed by an arbitrary string
126
146
  * (typically the eventId, triggerId, or journeyId). Lets the app read back the
@@ -155,4 +175,4 @@ declare class LocalStorageResponseStore implements ResponseStore {
155
175
  clear(): void;
156
176
  }
157
177
 
158
- export { type ContentSwap, HttpClient, type HttpClientOptions, HttpError, HttpMethod, type HttpResult, JsonValue, LocalStorageResponseStore, MAX_EVENT_ID_LENGTH, MemoryResponseStore, type RequestOptions, type ResponseStore, RetryConfig, WebhookResponse, buildUrl, extractContentSwaps, generateUlid, isBrowser, spliceSlots, toEventId };
178
+ export { type ContentSwap, EventContext, HttpClient, type HttpClientOptions, HttpError, HttpMethod, type HttpResult, JsonValue, LocalStorageResponseStore, MAX_EVENT_ID_LENGTH, MemoryResponseStore, type RequestOptions, type ResponseStore, RetryConfig, WebhookResponse, buildUrl, contextFromUrl, extractContentSwaps, generateUlid, isBrowser, spliceSlots, toEventId };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { CONSENT_COOKIE, DEFAULT_PREFIX, HttpClient, HttpError, LocalStorageResponseStore, MAX_EVENT_ID_LENGTH, MemoryResponseStore, VISITOR_COOKIE, XeniaApi, buildUrl, consentCookieName, extractContentSwaps, generateUlid, isBrowser, parseActions, spliceSlots, toEventId, visitorCookieName } from './chunk-D37RD3UC.js';
1
+ export { CONSENT_COOKIE, DEFAULT_PREFIX, HttpClient, HttpError, LocalStorageResponseStore, MAX_EVENT_ID_LENGTH, MemoryResponseStore, VISITOR_COOKIE, XeniaApi, buildUrl, consentCookieName, contextFromUrl, extractContentSwaps, generateUlid, isBrowser, parseActions, spliceSlots, toEventId, visitorCookieName } from './chunk-XXNDHYAS.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map