@vio-live/web-sdk 0.23.1 → 0.26.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.
@@ -36,6 +36,25 @@ interface VioConfig {
36
36
  contentId?: string | number;
37
37
  /** Human-readable title of that content (`content_title`); see `contentId`. */
38
38
  contentTitle?: string;
39
+ /**
40
+ * The campaign this PAGE belongs to (ADR-0034, amendment 3) — an editorial
41
+ * page (a Vev article, a Replit article) that is part of one campaign. Its
42
+ * slots are declared with it (the micro assigns them unless the dashboard
43
+ * already did) and, until that round-trips, the elements already resolve to
44
+ * it: assignment → page campaign → default. DOM alternative, inheritable:
45
+ * `data-vio-campaign` on any ancestor, or `vio-campaign` on the element.
46
+ */
47
+ campaignId?: number;
48
+ /** Log the SDK's slot/attribution decisions at `console.debug` (manifest assignments per slot). */
49
+ debug?: boolean;
50
+ /**
51
+ * The surface's privacy mode, when the host knows it (ADR-0035): `minimal`
52
+ * keeps the entry context (referrer, utm, landing page) off the order
53
+ * attribution. Without it the SDK asks the surface itself
54
+ * (`GET /v2/mobile/surface`), once per page load; a host-set `minimal`
55
+ * always wins.
56
+ */
57
+ privacyMode?: 'standard' | 'minimal';
39
58
  /** Override REST API base. Defaults are env-aware. */
40
59
  apiBase?: string;
41
60
  /** Override GraphQL base. Defaults are env-aware. */
@@ -71,6 +90,9 @@ interface ResolvedConfig {
71
90
  platform: VioPlatform;
72
91
  contentId?: string | number;
73
92
  contentTitle?: string;
93
+ campaignId?: number;
94
+ debug: boolean;
95
+ privacyMode?: 'standard' | 'minimal';
74
96
  apiBase: string;
75
97
  graphQLBase: string;
76
98
  eventsBase: string;
@@ -194,6 +216,8 @@ interface BootstrapSlot {
194
216
  platform?: string | null;
195
217
  startDate?: string | null;
196
218
  endDate?: string | null;
219
+ /** Who assigned it: the dashboard (always wins) or a page's own campaign (campaigns micro PR #16). */
220
+ source?: 'dashboard' | 'page' | null;
197
221
  }
198
222
  /**
199
223
  * One entry of `campaigns[]`: every active campaign of the surface, with its
@@ -231,6 +255,12 @@ interface BootstrapResponse {
231
255
  countryCode: string;
232
256
  currencyCode: string;
233
257
  };
258
+ /**
259
+ * The surface of the key, when the bootstrap says it (the campaigns
260
+ * service answers it on `/v2/mobile/surface` today; here when it adds it).
261
+ * Its `privacyMode` decides what the order attribution may carry.
262
+ */
263
+ surface?: SurfaceResponse['surface'];
234
264
  }
235
265
  /**
236
266
  * A slot this page declares to the campaigns service (ADR-0027 / ADR-0034):
@@ -240,6 +270,10 @@ interface BootstrapResponse {
240
270
  interface ManifestLocation {
241
271
  id: string;
242
272
  displayName?: string;
273
+ /** The campaign this location belongs to when it differs from the page's (`ManifestRequest.campaignId`). */
274
+ campaignId?: number;
275
+ /** The kind of element the slot holds — `card` | `carousel` | `detail` for the SDK's, a host's own word otherwise. For the dashboard. */
276
+ kind?: string;
243
277
  }
244
278
  /**
245
279
  * Where something happened, as `Vio.attribution(slot)` answers it — the ONE
@@ -254,6 +288,29 @@ interface Attribution {
254
288
  sponsorId?: number;
255
289
  contentId?: string;
256
290
  contentTitle?: string;
291
+ /** The page's URL within the 2 048 cap (`content_url`) — what Commerce keeps on the order and its lines. */
292
+ contentUrl?: string;
293
+ }
294
+ /**
295
+ * How much context analytics and Commerce may keep of a visit to this
296
+ * surface. `minimal` drops what says WHICH screen someone was on and WHY —
297
+ * the page (`content_url`, `content_title`), the slot (`location_id`) and
298
+ * the entry (referrer, utm, landing page) — the collector drops it from the
299
+ * events on its side (vio-analytics `privacy.ts`); the SDK keeps it off the
300
+ * order and off the cart lines it sends to Commerce. What measures the
301
+ * funnel and bills the sale stays: the surface, the campaign, the kind of
302
+ * component, the products and the amounts. A mode the SDK could not learn
303
+ * counts as `minimal`.
304
+ */
305
+ type SurfacePrivacyMode = 'standard' | 'minimal';
306
+ /** Response of `GET /v2/mobile/surface`: what the key may know of its own surface. */
307
+ interface SurfaceResponse {
308
+ surface?: {
309
+ id?: number;
310
+ name?: string;
311
+ status?: string;
312
+ privacyMode?: SurfacePrivacyMode | string | null;
313
+ } | null;
257
314
  }
258
315
  /** Body of `POST /v2/mobile/components/manifest`. */
259
316
  interface ManifestRequest {
@@ -265,6 +322,12 @@ interface ManifestRequest {
265
322
  */
266
323
  mode: 'merge' | 'replace';
267
324
  locations: ManifestLocation[];
325
+ /**
326
+ * The campaign the PAGE belongs to (`Vio.init({ campaignId })`): the micro
327
+ * assigns every declared location to it (`source: 'page'`) unless the
328
+ * dashboard already assigned that slot.
329
+ */
330
+ campaignId?: number;
268
331
  }
269
332
  /** Response of `POST /v2/mobile/components/manifest`. */
270
333
  interface ManifestResult {
@@ -275,6 +338,12 @@ interface ManifestResult {
275
338
  id: number | string;
276
339
  locationId: string;
277
340
  displayName?: string | null;
341
+ /**
342
+ * What the micro did with the page's campaign for this slot: `created` /
343
+ * `kept` / `replaced` a page assignment, `dashboard` (the dashboard's
344
+ * assignment stands — the page's campaign is ignored there), `none`.
345
+ */
346
+ assignment?: 'created' | 'kept' | 'replaced' | 'dashboard' | 'none';
278
347
  }>;
279
348
  deprecatedCount: number;
280
349
  warnings: Array<{
@@ -353,6 +422,12 @@ declare class VioApi {
353
422
  * sends `mode: 'merge'`; see `Vio.declareSlots()` for the dedupe on top.
354
423
  */
355
424
  declareManifest(body: ManifestRequest): Promise<ManifestResult>;
425
+ /**
426
+ * The surface of the key (`GET /v2/mobile/surface`): its id, name, status
427
+ * and `privacyMode` — what decides whether the order attribution may carry
428
+ * the entry context (ADR-0035). A 404 means a service that predates it.
429
+ */
430
+ surface(): Promise<SurfaceResponse>;
356
431
  /**
357
432
  * Get placement components for a campaign. Used by the carousel auto-fetch
358
433
  * mode (`<vio-product-carousel campaign-id="36" location="news-favorites">`).
@@ -440,15 +515,29 @@ declare function createCommerceClient(options: CommerceClientOptions): CommerceC
440
515
  * mental model stays consistent across platforms.
441
516
  */
442
517
  /**
443
- * Where a unit in the cart came from (ADR-0027 / ADR-0034): the campaign
444
- * the place showed when it was added, the place (`slot`) and the content
445
- * (article). What `Vio.attribution(slot)` answers, minus the sponsor and the
446
- * title. The purchase is split per campaign from these.
518
+ * Where a unit in the cart came from (ADR-0027 / ADR-0034 / ADR-0035): the
519
+ * campaign the place showed when it was added, the place (`slot`), the kind
520
+ * of element it was added from, and the content (article: its id, URL and
521
+ * title). What `Vio.attribution(slot)` answers, minus the sponsor, plus the
522
+ * element's kind. The purchase is split per campaign from these, and since
523
+ * 0.26 Commerce receives them with every add (`origin` on the line, ADR-0035
524
+ * phase B) so the order knows where each unit was sold from.
447
525
  */
448
526
  interface CartOrigin {
449
527
  campaignId?: number;
450
528
  slot?: string;
451
529
  contentId?: string;
530
+ /**
531
+ * The kind of component the units were added from, as Commerce and the
532
+ * collector name it: `card` | `carousel` | `detail` for the SDK's elements
533
+ * (`componentKindOf()` — from the element's `componentTemplateId`, else
534
+ * the kind word in the slot id).
535
+ */
536
+ componentKind?: string;
537
+ /** The page the units were added from (`content_url`, ≤ 2 048), kept so a later +1 from the cart credits the same page. */
538
+ contentUrl?: string;
539
+ /** Its title (`content_title`, ≤ 255). */
540
+ contentTitle?: string;
452
541
  }
453
542
  /** One origin of a line and how many of its units came from it. */
454
543
  interface CartLineOrigin extends CartOrigin {
@@ -509,9 +598,10 @@ interface SponsorCartState {
509
598
  * CustomEvent that UI components subscribe to (Web Components react via
510
599
  * `requestUpdate()`).
511
600
  *
512
- * Server-side cart sync (Vio Commerce GraphQL CreateCart / AddToCart
513
- * mutations) is deferred to checkout time via the CheckoutManager —
514
- * this manager is purely client-side state for now.
601
+ * The backend cart (Vio Commerce GraphQL CreateCart / AddItem / UpdateItem /
602
+ * DeleteItem) is kept in sync optimistically from here; since 0.26 every add
603
+ * and every increase tells it where the units come from (`origin`, ADR-0035
604
+ * phase B) so the order is born attributed — see `origin-wire.ts`.
515
605
  */
516
606
 
517
607
  interface CartChangeDetail {
@@ -660,12 +750,15 @@ declare class CartManager extends EventTarget {
660
750
  origin?: CartOrigin;
661
751
  }): void;
662
752
  /** Send a line's target quantity to the backend — ONE request in flight per
663
- * line. A target that arrives while one is in flight replaces any earlier
664
- * waiting one and goes out when the current request settles, so the server
665
- * ends on the last intent and never sees two updates racing each other.
666
- * While the sync is active the line keeps its optimistic quantity through
667
- * any backend response (see `updateFromBackendCart`); a rejection drops
668
- * what was queued and reconciles the cart from the server. */
753
+ * line. Targets that arrive while one is in flight queue behind it as
754
+ * steps (`queueStep`): reduced like the line's origins, sent in order once
755
+ * the current request settles — one request per queued increase from a
756
+ * different origin, one for a net decrease — so the server ends on the
757
+ * last intent, credits every increase to its own origin, and never sees two
758
+ * updates racing each other. While the sync is active the line keeps its
759
+ * optimistic quantity through any backend response (see
760
+ * `updateFromBackendCart`); a rejection drops what was queued and
761
+ * reconciles the cart from the server. */
669
762
  private syncQuantity;
670
763
  removeItem(lineItemId: string, sponsorId: number): void;
671
764
  clearSponsorCart(sponsorId: number): void;
@@ -690,9 +783,15 @@ declare class CartManager extends EventTarget {
690
783
  private loadFromStorage;
691
784
  private emit;
692
785
  }
693
- /** Only the three attribution fields, trimmed; `{}` when nothing is known. */
786
+ /**
787
+ * Only the attribution fields, trimmed; `{}` when nothing is known. The kind
788
+ * of element is kept as Commerce and the collector name it (`card`,
789
+ * `carousel`, `detail` — `componentKindOf`), from `componentKind` or from
790
+ * the `componentTemplateId` an element's attribution carries (`product-card`);
791
+ * the page as origin + path (`contentUrl`) and its title, within Commerce's caps.
792
+ */
694
793
  declare function normalizeOrigin(origin: CartOrigin | null | undefined): CartOrigin;
695
- /** Two origins are the same place when campaign, slot and content all match. */
794
+ /** Two origins are the same place when campaign, slot, content and kind of element all match (the page's URL and title are attributes of the place, not its identity). */
696
795
  declare function sameOrigin(a: CartOrigin, b: CartOrigin): boolean;
697
796
  /**
698
797
  * The origins of a line for reporting: what it carries, plus an empty origin
@@ -702,188 +801,983 @@ declare function sameOrigin(a: CartOrigin, b: CartOrigin): boolean;
702
801
  declare function lineOrigins(line: Pick<CartLineItem, 'origins' | 'quantity'>): CartLineOrigin[];
703
802
 
704
803
  /**
705
- * Vipps MobilePay Payment Adapter — GraphQL Integration & Types.
804
+ * What the commerce gateway may not know yet.
706
805
  *
707
- * Vipps payment integration uses 2 GraphQL operations:
708
- *
709
- * 1. `CreatePaymentVipps` mutation:
710
- * Initiates a Vipps payment session for a checkout and returns `payment_url`.
806
+ * The SDK ships ahead of the gateway more than once a quarter: a selection
807
+ * (`buyer_ref`, 2026-10-19), an argument (`origin` on the cart lines,
808
+ * `attribution` on the checkout — ADR-0035 phase B). A gateway that does not
809
+ * have the field refuses the WHOLE operation at validation — before anything
810
+ * runs, with no `data` — so each such operation is sent again without the
811
+ * field, once, and the answer remembered for the page load. An operation that
812
+ * DID run and failed is never repeated: for a mutation that would be a second
813
+ * charge, a second line in the cart.
711
814
  *
712
- * 2. `GetVippsStatus` query:
713
- * Queries Vipps payment state directly for a checkout (`state`).
815
+ * One mechanism for all of them, so the next field costs a token here and a
816
+ * call to `withGatewayFeature`, not a new copy of the retry.
714
817
  */
715
-
818
+ type GatewayFeature = 'buyer_ref' | 'line_origin' | 'checkout_attribution';
819
+ /** Whether this page load still expects the gateway to know `feature` (false once it refused it). */
820
+ declare function gatewayHas(feature: GatewayFeature): boolean;
821
+ /** Forget what this page load learned (tests). One feature, or all of them. */
822
+ declare function resetGatewayFeatures(feature?: GatewayFeature): void;
716
823
  /**
717
- * GraphQL mutation to create a Vipps payment session.
824
+ * True when `err` is the gateway refusing something it does not know, named
825
+ * `token` (`Cannot query field "buyer_ref" on type …`, `Unknown argument
826
+ * "origin" on field …`, `Unknown type "CartLineOriginInput"`, `Field "origin" is
827
+ * not defined by type "LineItemInput"`): a validation error, with no `data`
828
+ * and no `path` because nothing ran — safe to send again without it, a
829
+ * mutation included. Anything that ran (data present, or an error with a
830
+ * path) or any other message is not.
718
831
  */
719
- declare const CREATE_PAYMENT_VIPPS_MUTATION = "\nmutation CreatePaymentVipps($checkoutId: String!, $email: String, $returnUrl: String!, $express: Boolean) {\n Payment {\n CreatePaymentVipps(checkout_id: $checkoutId, email: $email, return_url: $returnUrl, express: $express) {\n payment_url\n reference\n express\n reason\n }\n }\n}\n";
832
+ declare function isUnknownTokenError(err: unknown, token: string): boolean;
833
+ /** `isUnknownTokenError` for any of the names a feature goes by. */
834
+ declare function isUnknownFeatureError(err: unknown, feature: GatewayFeature): boolean;
720
835
  /**
721
- * GraphQL query to fetch current Vipps payment status.
836
+ * Runs `request(true)` (the operation with the feature); when the gateway
837
+ * does not know it, `request(false)` (without it) — and from then on, for
838
+ * this page load, straight to the latter. Said once in the console: a
839
+ * gateway behind the SDK is worth knowing about, and so is a renamed type.
722
840
  */
723
- declare const GET_VIPPS_STATUS_QUERY = "\nquery GetVippsStatus($checkoutId: String!) {\n Payment {\n GetVippsStatus(checkout_id: $checkoutId) {\n state\n duplicate_of\n }\n }\n}\n";
724
- interface CreatePaymentVippsVariables extends Record<string, unknown> {
725
- checkoutId: string;
726
- /** Optional since Express: Vipps hands the email back with the payment. */
727
- email?: string;
728
- returnUrl: string;
841
+ declare function withGatewayFeature<T>(feature: GatewayFeature, request: (supported: boolean) => Promise<T>): Promise<T>;
842
+
843
+ /**
844
+ * A line origin as Commerce receives it (ADR-0035 phase B): `origin` on each
845
+ * line of `AddItem` and, when the quantity goes UP, on `UpdateItem` — the
846
+ * origin of the units that update adds. shopcart keeps every origin of a
847
+ * line with its units (`cart_item.origins`) and writes the order from them:
848
+ * `order_item.campaign_id` / `location_id` / `component_kind`, and the
849
+ * order's page when the checkout does not name one.
850
+ *
851
+ * snake_case on the wire, the caps of shopcart's `LineOriginDto` enforced
852
+ * here, once. Pure: `lineOriginWire()` takes the origin and the page.
853
+ */
854
+
855
+ /** The largest `Int` GraphQL coerces; a bigger id would fail the whole mutation. */
856
+ declare const GRAPHQL_INT_MAX = 2147483647;
857
+ /** `LineOriginDto` (shopcart `cart/dtos/send/line-origin.dto.ts`). */
858
+ interface LineOriginWire {
859
+ campaign_id?: number;
860
+ location_id?: string;
861
+ component_kind?: string;
862
+ content_url?: string;
863
+ content_title?: string;
864
+ }
865
+ /** The caps of `LineOriginDto` — a longer value is refused whole by the API, so it is cut here. */
866
+ declare const LINE_ORIGIN_CAPS: Readonly<{
867
+ locationId: 100;
868
+ componentKind: 32;
869
+ contentUrl: 2048;
870
+ contentTitle: 255;
871
+ }>;
872
+ /** The page the units are added from, for an origin that does not carry its own. */
873
+ interface OriginPage {
874
+ contentUrl?: string;
875
+ contentTitle?: string;
876
+ }
877
+ interface LineOriginWireOptions {
878
+ /** The current page, for an origin that does not carry its own. */
879
+ page?: OriginPage;
729
880
  /**
730
- * `true` asks for Express — address and delivery chosen inside the Vipps
731
- * app. When the cart cannot have it, no payment is created and the answer
732
- * says `express: false` with the reason; the caller then opens the
733
- * ordinary checkout.
881
+ * The surface's privacy mode. Only on a `standard` surface do the slot
882
+ * (`location_id`) and the page (`content_url`, `content_title`) travel —
883
+ * which screen a unit was sold from is what `minimal` keeps private, the
884
+ * same promise the collector keeps for the events. `campaign_id` and
885
+ * `component_kind` always do. Default `unknown`: fail closed.
734
886
  */
735
- express?: boolean;
736
- }
737
- interface CreatePaymentVippsResponse {
738
- /** Absent when Express was asked for and refused. */
739
- payment_url?: string;
740
- /** The reference the seller reads in its Vipps portal. */
741
- reference?: string;
742
- express?: boolean;
743
- reason?: string;
744
- }
745
- interface GetVippsStatusVariables extends Record<string, unknown> {
746
- checkoutId: string;
747
- }
748
- interface VippsStatusResult {
749
- state: string;
750
- /** Set when this checkout was closed as a duplicate: the checkout that paid the cart. */
751
- duplicate_of?: string | null;
887
+ privacyMode?: SurfacePrivacyMode | 'unknown';
752
888
  }
753
- type VippsPaymentState = 'CREATED' | 'INITIATED' | 'AUTHORIZED' | 'TERMINATED' | 'EXPIRED' | string;
754
889
  /**
755
- * Executes the `CreatePaymentVipps` GraphQL mutation.
890
+ * The origin for the wire, or `undefined` when the SDK knows no PLACE for the
891
+ * units — no campaign, no slot, no kind of element (a host adding with no
892
+ * attribution): then nothing is sent and the line inherits the order's
893
+ * campaign on the server. The page is the origin's own when it has one — the
894
+ * page the units were added from — else the current page's, as origin + path;
895
+ * `campaign_id` only as a positive `Int` (the DTO's `@IsInt() @Min(1)`, the
896
+ * gateway's 32-bit coercion).
756
897
  */
757
- declare function createPaymentVipps(variables: CreatePaymentVippsVariables | Record<string, unknown>, options?: CartQueryOptions): Promise<CreatePaymentVippsResponse | null>;
898
+ declare function lineOriginWire(origin: CartOrigin | null | undefined, options?: LineOriginWireOptions): LineOriginWire | undefined;
899
+
758
900
  /**
759
- * Executes the `GetVippsStatus` GraphQL query.
901
+ * The `client` block — the standard context of the visit (EVENTS_CONTRACT
902
+ * "client", 2026-10-19): language, where the session landed from (the
903
+ * referrer and `utm_*` of the LANDING page, remembered for the session),
904
+ * screen size and time zone. What the collector derives from the request
905
+ * itself — device type, OS, browser, country — is NOT sent: no User-Agent
906
+ * parsing here, no duplicate of what the server knows better.
907
+ *
908
+ * Pure like `content.ts`: everything takes the globals it reads (defaults to
909
+ * the real ones), never throws, and answers `{}` where there is no browser
910
+ * (SSR, old engines). Capped to the collector's limits in ONE place: an
911
+ * over-long value is cut — none of these is an identity, so a cut referrer
912
+ * is still the right dimension.
913
+ *
914
+ * Landing memory: the first page of a session writes its referrer and utm
915
+ * parameters to `sessionStorage`; later pages read them back, so an event on
916
+ * page three still says the visit came from the newsletter — their own
917
+ * `document.referrer` (an internal page) is never a source. The referrer is
918
+ * kept as origin + path (no query, no fragment: a referrer's query is its
919
+ * tracking tail, not where the visit came from) and dropped altogether when
920
+ * it is this same host (a self-referral says nothing about the entry). A URL
921
+ * with utm parameters is a new landing (another campaign click) that replaces
922
+ * the memory — unless it was reached from this same host, i.e. an internal
923
+ * link that propagates utm, which keeps the landing that was. Without
924
+ * storage, or without consent to persist, each page stands alone.
760
925
  */
761
- declare function getVippsStatus(variables: GetVippsStatusVariables | Record<string, unknown>, options?: CartQueryOptions): Promise<VippsStatusResult | null>;
762
-
763
- declare const CREATE_CART_MUTATION = "\nmutation CreateCart($customerSessionId: String!, $currency: String!, $shippingCountry: String) {\n Cart {\n CreateCart(customer_session_id: $customerSessionId, currency: $currency, shipping_country: $shippingCountry) {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n }\n}\n";
764
- declare const ADD_ITEM_MUTATION = "\nmutation AddItem($cartId: String!, $lineItems: [LineItemInput!]!) {\n Cart {\n AddItem(cart_id: $cartId, line_items: $lineItems) {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n }\n}\n";
765
- declare const DELETE_ITEM_MUTATION = "\nmutation DeleteItem($cartId: String!, $cartItemId: String!) {\n Cart {\n DeleteItem(cart_id: $cartId, cart_item_id: $cartItemId) {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n }\n}\n";
766
- declare const UPDATE_ITEM_MUTATION = "\nmutation UpdateItem($cartId: String!, $cartItemId: String!, $shippingId: String, $qty: Int) {\n Cart {\n UpdateItem(cart_id: $cartId, cart_item_id: $cartItemId, shipping_id: $shippingId, qty: $qty) {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n }\n}\n";
767
- declare const GET_CART_QUERY = "\nquery GetCart($cartId: String!) {\n Cart {\n GetCart(cart_id: $cartId) {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n }\n}\n";
768
- declare const GET_LINE_ITEMS_BY_SUPPLIER_QUERY = "\nquery GetLineItemsBySupplier($cartId: String!) {\n Cart {\n GetLineItemsBySupplier(cart_id: $cartId) {\n supplier {\n id\n name\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n }\n }\n}\n";
769
- declare const UPDATE_SHIPPINGS_BY_SUPPLIER_MUTATION = "\nmutation UpdateShippingsBySupplier($cartId: String!, $data: [DataUpdateShippingsBySupplier!]!) {\n Cart {\n UpdateShippingsBySupplier(cart_id: $cartId, data: $data) {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n }\n}\n";
770
- declare const CREATE_CHECKOUT_MUTATION = "\nmutation CreateCheckout($cartId: String!) {\n Checkout {\n CreateCheckout(cart_id: $cartId) {\n buyer_accepts_purchase_conditions\n buyer_accepts_terms_conditions\n created_at\n updated_at\n id\n deleted_at\n success_url\n cancel_url\n payment_method\n email\n status\n checkout_url\n origin_payment_id\n billing_address {\n id\n first_name\n last_name\n phone_code\n phone\n company\n address1\n address2\n city\n province\n province_code\n country\n country_code\n zip\n }\n shipping_address {\n id\n first_name\n last_name\n phone_code\n phone\n company\n address1\n address2\n city\n province\n province_code\n country\n country_code\n zip\n }\n available_payment_methods {\n name\n }\n discount_code\n cart {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n totals {\n currency_code\n subtotal\n shipping\n total\n taxes\n tax_rate\n discounts\n }\n }\n }\n}\n";
771
- declare const UPDATE_CHECKOUT_MUTATION = "\nmutation UpdateCheckout($checkoutId: String!, $status: String, $successUrl: String, $email: String, $cancelUrl: String, $paymentMethod: String, $shippingAddress: AddressArgs, $billingAddress: AddressArgs, $buyerAcceptsPurchaseConditions: Boolean, $buyerAcceptsTermsConditions: Boolean) {\n Checkout {\n UpdateCheckout(checkout_id: $checkoutId, status: $status, success_url: $successUrl, email: $email, cancel_url: $cancelUrl, payment_method: $paymentMethod, shipping_address: $shippingAddress, billing_address: $billingAddress, buyer_accepts_purchase_conditions: $buyerAcceptsPurchaseConditions, buyer_accepts_terms_conditions: $buyerAcceptsTermsConditions) {\n buyer_accepts_purchase_conditions\n buyer_accepts_terms_conditions\n created_at\n updated_at\n id\n deleted_at\n success_url\n cancel_url\n payment_method\n email\n status\n checkout_url\n origin_payment_id\n billing_address {\n id\n first_name\n last_name\n phone_code\n phone\n company\n address1\n address2\n city\n province\n province_code\n country\n country_code\n zip\n }\n shipping_address {\n id\n first_name\n last_name\n phone_code\n phone\n company\n address1\n address2\n city\n province\n province_code\n country\n country_code\n zip\n }\n available_payment_methods {\n name\n }\n discount_code\n cart {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n totals {\n currency_code\n subtotal\n shipping\n total\n taxes\n tax_rate\n discounts\n }\n }\n }\n}\n";
772
- declare const GET_CHECKOUT_QUERY = "\nquery GetCheckout($checkoutId: String!) {\n Checkout {\n GetCheckout(checkout_id: $checkoutId) {\n buyer_accepts_purchase_conditions\n buyer_accepts_terms_conditions\n created_at\n updated_at\n id\n deleted_at\n success_url\n cancel_url\n payment_method\n email\n status\n checkout_url\n origin_payment_id\n duplicate_of\n billing_address {\n id\n first_name\n last_name\n phone_code\n phone\n company\n address1\n address2\n city\n province\n province_code\n country\n country_code\n zip\n }\n shipping_address {\n id\n first_name\n last_name\n phone_code\n phone\n company\n address1\n address2\n city\n province\n province_code\n country\n country_code\n zip\n }\n available_payment_methods {\n name\n }\n discount_code\n cart {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n totals {\n currency_code\n subtotal\n shipping\n total\n taxes\n tax_rate\n discounts\n }\n }\n }\n}\n";
773
- declare const GET_AVAILABLE_PAYMENT_METHODS_QUERY = "\nquery Config {\n Payment {\n GetAvailablePaymentMethods {\n config {\n name\n type\n value\n }\n name\n }\n }\n}\n";
774
- /** Transport options for a cart/checkout GraphQL call. */
775
- interface CartQueryOptions {
776
- endpoint?: string;
777
- apiKey?: string;
778
- /** Sponsor commerce key — goes in the Authorization header. */
779
- commerceKey?: string;
780
- /** True when the commerce key came from a resolved sponsor (bootstrap).
781
- * False = we fell back to the host apiKey — writes like CreateCart should
782
- * NOT proceed with the wrong key (the cart would be orphaned). */
783
- sponsorResolved?: boolean;
784
- }
926
+ interface ClientContext {
927
+ language?: string;
928
+ referrer?: string;
929
+ utm_source?: string;
930
+ utm_medium?: string;
931
+ utm_campaign?: string;
932
+ utm_term?: string;
933
+ utm_content?: string;
934
+ screen_w?: number;
935
+ screen_h?: number;
936
+ tz?: string;
937
+ }
938
+ declare const UTM_KEYS: readonly ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"];
939
+ type UtmKey = (typeof UTM_KEYS)[number];
940
+ /** Commerce's cap for the landing page on the order's entry context (`entry.landing_url`, ADR-0035). */
941
+ declare const CLIENT_LANDING_URL_MAX_LENGTH = 2048;
785
942
  /**
786
- * Resolve endpoint + keys for cart GraphQL calls. Awaits Vio.bootstrap() once
787
- * if it hasn't run yet (the sponsor commerce keys come from bootstrap), then
788
- * uses the sponsor's commerce apiKey (via the Vio facade on globalThis,
789
- * avoiding an import cycle); falls back to the host apiKey.
943
+ * What a session remembers of the page it landed on. `url` is the landing
944
+ * page itself — origin + path, like the referrer: no query (the utm are kept
945
+ * apart, the rest is a tracking tail), no fragment — for the order's entry
946
+ * context; the events do not carry it (the collector derives the landing).
790
947
  */
791
- declare function getCartGraphQLOptions(sponsorId?: number): Promise<CartQueryOptions>;
792
- /** Stable per-browser customer session id (backend CreateCart requires one). */
793
- declare function getCustomerSessionId(): string;
794
- interface GraphQLEnvelope {
795
- data?: Record<string, Record<string, unknown>>;
796
- errors?: Array<{
797
- message?: string;
798
- }>;
948
+ interface Landing {
949
+ referrer?: string;
950
+ utm?: Partial<Record<UtmKey, string>>;
951
+ url?: string;
952
+ }
953
+ interface StorageLike {
954
+ getItem(key: string): string | null;
955
+ setItem(key: string, value: string): void;
956
+ removeItem?(key: string): void;
957
+ }
958
+ /** The globals the block is read from — injectable for tests; defaults to the real ones. */
959
+ interface ClientEnvironment {
960
+ navigator?: {
961
+ language?: unknown;
962
+ } | null;
963
+ document?: {
964
+ referrer?: unknown;
965
+ } | null;
966
+ location?: {
967
+ search?: unknown;
968
+ host?: unknown;
969
+ href?: unknown;
970
+ } | null;
971
+ screen?: {
972
+ width?: unknown;
973
+ height?: unknown;
974
+ } | null;
975
+ /** The session memory for the landing; `null` = none (SSR, private mode, blocked). */
976
+ storage?: StorageLike | null;
977
+ /** The time zone; defaults to `Intl.DateTimeFormat().resolvedOptions().timeZone`. */
978
+ timeZone?: () => unknown;
799
979
  }
800
- /** Execute a GraphQL query/mutation against the configured commerce endpoint.
801
- * Callers that skip `getCartGraphQLOptions()` (or pass a bare sponsorId) get
802
- * it resolved here instead of silently sending an unauthenticated request.
803
- * Rejects after `CART_GRAPHQL_TIMEOUT_MS` (and aborts the fetch). */
804
- declare function executeCartGraphQL(query: string, variables: Record<string, unknown>, options?: CartQueryOptions | number | undefined): Promise<GraphQLEnvelope>;
805
- declare function createCart(customerSessionId: string, currency: string, shippingCountry?: string | null, options?: CartQueryOptions): Promise<any>;
806
- declare function addItem(cartId: string, lineItems: unknown[], options?: CartQueryOptions): Promise<any>;
807
- declare function deleteItem(cartId: string, cartItemId: string, options?: CartQueryOptions): Promise<any>;
808
- declare function updateItem(cartId: string, cartItemId: string, shippingId?: string | null, qty?: number | null, options?: CartQueryOptions): Promise<any>;
809
- declare function getCart(cartId: string, options?: CartQueryOptions): Promise<any>;
810
- declare function getLineItemsBySupplier(cartId: string, options?: CartQueryOptions): Promise<any>;
811
- declare function updateShippingsBySupplier(cartId: string, data: unknown[], options?: CartQueryOptions): Promise<any>;
812
- declare function createCheckout(cartId: string, options?: CartQueryOptions): Promise<any>;
813
- declare function updateCheckout(variables: Record<string, unknown>, options?: CartQueryOptions): Promise<any>;
814
- declare function getCheckout(checkoutId: string, options?: CartQueryOptions): Promise<any>;
815
- declare function getAvailablePaymentMethods(options?: CartQueryOptions): Promise<any>;
816
- declare const CREATE_PAYMENT_STRIPE_MUTATION = "\nmutation CreatePaymentStripe($checkoutId: String!, $successUrl: String!, $paymentMethod: String!, $email: String!) {\n Payment {\n CreatePaymentStripe(checkout_id: $checkoutId, success_url: $successUrl, payment_method: $paymentMethod, email: $email) {\n order_id\n checkout_url\n }\n }\n}\n";
817
- declare function createPaymentStripe(variables: Record<string, unknown>, options?: CartQueryOptions): Promise<any>;
980
+ /**
981
+ * The landing of this session: what is remembered — unless this page is a
982
+ * landing itself (utm parameters in its URL, reached from outside this host)
983
+ * or nothing is remembered yet, when this page's referrer and utm are taken
984
+ * (and, with `persist`, kept).
985
+ */
986
+ declare function resolveLanding(env?: ClientEnvironment, persist?: boolean): Landing;
987
+ /** The landing page as the landing keeps it: origin + path, no query, no fragment; capped. */
988
+ declare function landingUrl(raw: unknown): string | undefined;
989
+ /**
990
+ * The landing this session REMEMBERS — what was written by the first page —
991
+ * or null when nothing is stored (no storage, no consent, analytics never
992
+ * started). Read only: for the order's entry context, which must not take the
993
+ * page the shopper pays on for the page they came in through.
994
+ */
995
+ declare function storedLanding(storage?: StorageLike | null | undefined): Landing | null;
996
+ /** The block for the wire — read once per page load by the manager and reused on every event. */
997
+ declare function resolveClientContext(env?: ClientEnvironment, landing?: Landing): ClientContext;
818
998
 
819
999
  /**
820
- * Stripe on our own page — the Payment Element, no redirect.
1000
+ * Slots — the pure half of ADR-0027 / ADR-0034 on the web.
821
1001
  *
822
- * The older web flow minted a Stripe Payment Link and sent the shopper to a
823
- * page hosted by Stripe. This one keeps them here (Angelo, 2026-09-24):
1002
+ * A slot is a NAME for a place on a page. The page declares its slots to the
1003
+ * campaigns service (`Vio.declareSlots()` / `Vio.registerSlot()` in client.ts),
1004
+ * the dashboard assigns a campaign to each one, optionally with a date window,
1005
+ * and `GET /v2/mobile/config` answers with `campaigns[].slots[]` — only the
1006
+ * assignments whose window is open NOW. Whatever no slot names shows the
1007
+ * surface's default campaign (`campaign`).
824
1008
  *
825
- * 1. Vio Commerce creates a PaymentIntent for the checkout
826
- * (`Payment { CreatePaymentIntentStripe }`) and answers with its client
827
- * secret AND the publishable key of the account that minted it — the
828
- * seller's when they brought both keys, ours otherwise. The two are
829
- * halves of one account: the browser confirms with the key what the
830
- * server minted with the secret one.
831
- * 2. Stripe's Payment Element is mounted in a LIGHT-DOM container, the way
832
- * the other embedded widgets are. Card fields are Stripe's own iframes,
833
- * so card data never touches this SDK or our servers.
834
- * 3. `confirm()` pays. A 3-D Secure challenge opens in Stripe's own modal
835
- * over the page: `redirect: 'if_required'` keeps the shopper here for
836
- * cards, and still redirects for a method that has no other way.
837
- * 4. The Commerce order is NOT born here. Stripe's `payment_intent.succeeded`
838
- * webhook creates it, verified server-side; the checkout is polled for
839
- * its status afterwards, exactly as the redirect return does.
1009
+ * Everything here is side-effect free and never throws on a malformed
1010
+ * bootstrap: a broken `campaigns[]` must never blank a product block or break
1011
+ * `track()`.
840
1012
  */
841
1013
 
842
- /** What the backend hands over to pay a checkout on our page. */
843
- interface StripeIntent {
844
- /** `pi_..._secret_...`: what the browser confirms. */
845
- client_secret: string;
846
- /** The key of the SAME account that minted the secret. */
847
- publishable_key: string;
848
- customer?: string;
849
- /**
850
- * Stripe Connect (ADR-0022): the seller's connected account, where the
851
- * intent lives. The browser must name it or Stripe answers "no such
852
- * payment_intent". Absent for every seller not on Connect.
853
- */
854
- stripe_account?: string;
855
- }
856
- /** What `confirm()` answers. The browser's word is never the order. */
857
- type StripeConfirmOutcome = {
858
- status: 'succeeded';
859
- paymentIntentId?: string;
860
- }
861
- /** Authorised but not settled yet, or Stripe redirected and will return. */
862
- | {
863
- status: 'pending';
864
- paymentIntentId?: string;
865
- } | {
866
- status: 'failed';
867
- message?: string;
868
- code?: string;
1014
+ /** What `Vio.declareSlots()` accepts per slot. */
1015
+ type SlotInput = string | {
1016
+ id: string;
1017
+ displayName?: string;
1018
+ campaignId?: number;
1019
+ kind?: string;
869
1020
  };
870
- interface StripeElementHandle {
871
- confirm(): Promise<StripeConfirmOutcome>;
872
- unmount(): void;
1021
+ /** The third argument of `Vio.registerSlot(id, displayName, …)`: the element's own campaign and what kind of element it is. */
1022
+ interface RegisterSlotOptions {
1023
+ campaignId?: number | string | null;
1024
+ /** `card` | `carousel` | `detail` for the SDK's elements; a host may name its own kind. */
1025
+ kind?: string;
873
1026
  }
1027
+ /**
1028
+ * The kind of component some units were sold from, as Commerce keeps it on
1029
+ * the order line (`order_item.component_kind`, ≤ 32) — the SAME rule the
1030
+ * collector applies for `breakdown?by=component_kind` (vio-analytics
1031
+ * `componentKind`), so the order and the events agree: what the element says
1032
+ * it is (`component_template_id`: `product-card`, `product-carousel`,
1033
+ * `product-detail`, a Vev block's `vev-card`) lower-cased and without its
1034
+ * `product-` / `vev-` prefix, else the kind word in the slot id the page
1035
+ * declared (`card-<key>`, `<scope>-carousel-2`, `detail-1`); `undefined` when
1036
+ * neither says.
1037
+ */
1038
+ declare function componentKindOf(templateId: unknown, slot?: unknown): string | undefined;
1039
+ /** The kind as the manifest carries it: trimmed, lower-case, cut at 32 chars; `undefined` for nothing. */
1040
+ declare function normalizeSlotKind(value: unknown): string | undefined;
1041
+ type BootLike = Pick<BootstrapResponse, 'campaign' | 'campaigns' | 'primarySponsor' | 'secondarySponsors'>;
1042
+ /**
1043
+ * The campaign a slot shows right now. Among the `status === 'active'`
1044
+ * entries of `campaigns[]`, the one with an assignment named `slot` for this
1045
+ * platform (`platform` null on the assignment, or equal to `platform`) whose
1046
+ * window contains `now` (`startDate <= now < endDate`, null = open). When
1047
+ * several qualify, the surface's default campaign wins, else the first the
1048
+ * backend lists.
1049
+ *
1050
+ * No assignment → the PAGE's campaign (`pageCampaignId`: the element's own
1051
+ * `vio-campaign`, an ancestor's `data-vio-campaign`, or `Vio.init({ campaignId })`)
1052
+ * when `campaigns[]` lists it as active — an editorial page resolves to its
1053
+ * campaign before (and regardless of) the manifest round-trip. Else the
1054
+ * default campaign: the `campaigns[]` entry whose id is `campaign.id`, or a
1055
+ * minimal entry built from `campaign` (+ the top-level sponsors) when the
1056
+ * list does not carry it. No bootstrap → null.
1057
+ */
1058
+ declare function resolveSlotCampaign(boot: BootLike | null | undefined, slot: string | null | undefined, now?: number, platform?: string | null, pageCampaignId?: CampaignHint, sponsorId?: number | null): BootstrapCampaignEntry | null;
1059
+ /**
1060
+ * The sponsor rule: the active campaign of `campaigns[]` the sponsor takes
1061
+ * part in, as its primary or one of its secondaries — when it is in several,
1062
+ * the surface's default campaign if it is one of them, else the first one
1063
+ * the backend lists. Null when none (or on a malformed list).
1064
+ */
1065
+ declare function sponsorCampaignEntry(boot: BootLike | null | undefined, sponsorId: number | null | undefined): BootstrapCampaignEntry | null;
1066
+ /**
1067
+ * A page campaign as the callers give it: one id, or the candidates in
1068
+ * precedence order (the element's `vio-campaign`, an ancestor's
1069
+ * `data-vio-campaign`, `Vio.init`'s). An unusable level (invalid, paused,
1070
+ * unknown) falls through to the next one; `0`, `null`, `''` mean unset.
1071
+ */
1072
+ type CampaignHint = number | string | null | undefined | ReadonlyArray<number | string | null | undefined>;
1073
+ /**
1074
+ * A campaign id as the SDK accepts it: a positive safe integer, given as a
1075
+ * number or as a string of decimal digits (an attribute). Anything else —
1076
+ * `true`, `'0x10'`, `'1e3'`, an array, a float — is "absent".
1077
+ */
1078
+ declare function toCampaignId(value: unknown): number | undefined;
1079
+ /** The usable ids of a hint, in order, without duplicates. */
1080
+ declare function campaignCandidates(hint: CampaignHint): number[];
1081
+ /**
1082
+ * The first candidate of `hint` that `campaigns[]` lists as ACTIVE (and, when
1083
+ * `sponsorId` is given, that the sponsor takes part in — primary or
1084
+ * secondary); null when none — a paused, ended or unknown page campaign is
1085
+ * ignored and the resolution moves on.
1086
+ */
1087
+ declare function activeCampaignEntry(boot: BootLike | null | undefined, hint: CampaignHint, sponsorId?: number): BootstrapCampaignEntry | null;
1088
+ /** The kinds of Vio element that register themselves. */
1089
+ type SlotKind = 'card' | 'carousel' | 'detail';
1090
+ /**
1091
+ * The id an element gets when the host set no `vio-slot`:
1092
+ * `${scope ? scope + '-' : ''}${kind}-${ordinal + 1}` (`carousel-1`, `card-3`,
1093
+ * `article-123-carousel-1`), `ordinal` being the element's index among the
1094
+ * same-kind Vio elements WITH THE SAME SCOPE, in document order at connect
1095
+ * time. The scope is inherited from the DOM (`vio-scope` on the element, else
1096
+ * the nearest `data-vio-scope` ancestor): a Vev page or a Replit article
1097
+ * (`<body data-vio-scope="article-123">`) gets per-page slots with one line
1098
+ * and no per-element naming; a template that wants slots shared across
1099
+ * articles simply sets no scope. On purpose there is NO page path in the id:
1100
+ * the article goes to analytics as `content_id`, not into the slot. Stable
1101
+ * across reloads while the layout is; a layout change leaves a stale entry,
1102
+ * which ADR-0034 accepts.
1103
+ */
1104
+ declare function autoSlotId(kind: SlotKind, ordinal: number, scope?: string | null): string;
1105
+ /** `"Carousel 1"`, `"Card 3"` — with ` · ${scopeName}` when the scope has a human label. */
1106
+ declare function autoSlotDisplayName(kind: SlotKind, ordinal: number, scopeName?: string | null): string;
1107
+ /** A scope value fit for an id: trimmed, inner whitespace → `-`. */
1108
+ declare function normalizeScope(scope: string | null | undefined): string;
874
1109
 
875
1110
  /**
876
- * Apple Pay on the Web — via Stripe Payment Request API.
1111
+ * Vio.analytics — the web SDK's half of the Vio Analytics pipeline.
877
1112
  *
878
- * Architecture decision (matches iOS Vio SDK pattern):
879
- * - One Stripe **publishable key** for the Vio platform (global, set
880
- * via `Vio.init({ stripePublishableKey })`).
881
- * - One **Stripe Connect account id** per sponsor — sourced from
882
- * `Vio.bootstrap()` response. Without it, the payment lands on the
883
- * platform account instead of the merchant.
1113
+ * Events flow to the Vio collector (`POST <eventsBase>/v1/events`, repo
1114
+ * vio-live/vio-analytics) which owns raw storage (ClickHouse) and vendor
1115
+ * fan-out (Mixpanel today). THE SDK NEVER TALKS TO VENDORS — swapping or
1116
+ * dropping a vendor is a server-side change, zero client releases.
1117
+ * Wire contract: vio-analytics `docs/EVENTS_CONTRACT.md` (v1, snake_case).
884
1118
  *
885
- * Apple Pay on the Web prerequisites (Stripe-managed for us):
886
- * - Stripe Connect account is enabled for Apple Pay
1119
+ * Design rules:
1120
+ * - SIDE-EFFECT-FREE MODULE. Nothing runs at import time (tsup/tree-shaking
1121
+ * contract, see lessons/web-sdk-tsup-singleton-and-build). Listeners are
1122
+ * installed by an explicit `Vio.analytics.start()`.
1123
+ * - `track()` works BEFORE `Vio.init()` — events queue and flush once the
1124
+ * SDK is configured (transport resolves at flush time, not at track time).
1125
+ * - SSR-safe: without `window` every call is a silent no-op.
1126
+ * - Retries are safe: `event_id` is stable per event, the collector
1127
+ * dedupes. Queue is bounded (drop-oldest) so a dead collector can never
1128
+ * grow memory unbounded.
1129
+ * - Anti-double-count: the SDK only reports what the server can't see.
1130
+ * Votes/participations are server truth; `ad_activation`/`cart_intent`
1131
+ * are mirrored server-side, never from here.
1132
+ *
1133
+ * Three sinks, matching the Vev precedent (vio-vev analytics.ts, which
1134
+ * becomes an adapter over this in F3):
1135
+ * 1. collector (default ON once started)
1136
+ * 2. window.dataLayer — GA4/GTM (opt-in `start({ dataLayer: true })`,
1137
+ * the publisher-facing feature; NOT part of the Vio pipeline)
1138
+ * 3. `vio:analytics` DOM event — always when started (inspector/bridges)
1139
+ */
1140
+
1141
+ declare const ANALYTICS_EVENT_NAMES: readonly ["view_item_list", "select_item", "view_item", "add_to_cart", "remove_from_cart", "view_cart", "begin_checkout", "purchase", "component_impression", "component_click", "ad_impression", "ad_click", "poll_impression", "contest_impression", "session_start", "session_end", "checkout_error", "sdk_error"];
1142
+ type AnalyticsEventName = (typeof ANALYTICS_EVENT_NAMES)[number];
1143
+ /** Camel-case for DX; mapped to the snake_case wire format at build time. */
1144
+ interface AnalyticsContext {
1145
+ campaignId?: number;
1146
+ broadcastId?: string;
1147
+ campaignComponentId?: number;
1148
+ appPlacementId?: number;
1149
+ locationId?: string;
1150
+ componentTemplateId?: string;
1151
+ sponsorId?: number;
1152
+ activationId?: number;
1153
+ contentUrl?: string;
1154
+ /**
1155
+ * The host's own id for the piece of content the component sits in — an
1156
+ * article id in a CMS, a page id in a site builder. Carried verbatim so the
1157
+ * host can join Vio's funnel back onto its own per-article reporting
1158
+ * (revenue stops being an estimate). Left alone by the SDK.
1159
+ */
1160
+ contentId?: string | number;
1161
+ /** Human-readable content snapshot; auto-filled from document.title. */
1162
+ contentTitle?: string;
1163
+ /** Código corto del fallo (`sdk_error` / `checkout_error`). */
1164
+ errorCode?: string;
1165
+ variant?: string;
1166
+ /**
1167
+ * The slot (ADR-0027) the component sits in — its `vio-slot`. Attribution
1168
+ * follows it: the event's `campaign_id` is the campaign assigned to the slot
1169
+ * right now, before the sponsor rule. On the wire it fills `location_id`
1170
+ * when no explicit `locationId` is given (a slot IS a location id to the
1171
+ * campaigns service).
1172
+ */
1173
+ slot?: string;
1174
+ }
1175
+ interface AnalyticsItemInput {
1176
+ productId: number | string;
1177
+ name?: string;
1178
+ brand?: string;
1179
+ variantId?: number | string;
1180
+ price?: number;
1181
+ quantity?: number;
1182
+ }
1183
+ interface AnalyticsCommerce {
1184
+ items?: AnalyticsItemInput[];
1185
+ value?: number;
1186
+ currency?: string;
1187
+ orderId?: string;
1188
+ paymentMethod?: string;
1189
+ /**
1190
+ * The buyer reference (`buyer_id` on the wire): shopcart's `buyer_ref`, a
1191
+ * keyed hash of the buyer's email — one person, one ref across orders and
1192
+ * devices, nothing reversible. Never an email (see core/buyer-ref.ts).
1193
+ */
1194
+ buyerId?: string;
1195
+ }
1196
+ interface TrackOptions {
1197
+ context?: AnalyticsContext;
1198
+ commerce?: AnalyticsCommerce;
1199
+ props?: Record<string, unknown>;
1200
+ }
1201
+ interface AnalyticsStartOptions {
1202
+ /** Where the SDK is embedded: 'vev' | 'replit' | 'custom' | … Default 'custom'. */
1203
+ host?: string;
1204
+ /**
1205
+ * Arrancar en modo cookieless hasta que el host llame `setConsent(true)`.
1206
+ * Default false: el SDK asume que el CMP del publisher ya decidió si nos
1207
+ * carga. Los publishers EU que necesitan medir antes del consentimiento
1208
+ * (o no pueden persistir sin él) ponen true.
1209
+ */
1210
+ requireConsent?: boolean;
1211
+ /**
1212
+ * Install the automatic funnel listeners (vio:added-to-cart,
1213
+ * vio:checkout-open, vio:open-cart, vio:payment-success). Default true.
1214
+ * Hosts with their OWN instrumentation choke point (e.g. the Vev module,
1215
+ * which forwards every event through trackEvent()) set false so the same
1216
+ * user action is never tracked twice — they keep the session/batching/
1217
+ * transport engine and call track() themselves.
1218
+ */
1219
+ autoTrack?: boolean;
1220
+ /**
1221
+ * Adopt the host's session id instead of minting one. A host that already
1222
+ * tracks its readers (its own impressions, dwell, clicks) needs Vio's
1223
+ * purchases to land in the SAME session, or the two datasets cannot be
1224
+ * joined. Pass the id the host already stores; omit it and the SDK keeps
1225
+ * its own rotating session.
1226
+ */
1227
+ sessionId?: string;
1228
+ /** Send to the Vio collector. Default true. */
1229
+ collector?: boolean;
1230
+ /** Also push GA4 e-commerce events to window.dataLayer (publisher feature). */
1231
+ dataLayer?: boolean;
1232
+ /** console.debug every event. */
1233
+ debug?: boolean;
1234
+ }
1235
+ declare class AnalyticsManager extends EventTarget {
1236
+ private started;
1237
+ private options;
1238
+ private queue;
1239
+ private flushTimer;
1240
+ private retryAttempt;
1241
+ private retryNotBefore;
1242
+ private externalUserId;
1243
+ private sessionId;
1244
+ private requireConsent;
1245
+ private consentGranted;
1246
+ private anonIdCache;
1247
+ /** Set via start({ sessionId }) — the host owns the session, we follow. */
1248
+ private externalSessionId;
1249
+ private sessionStartedAt;
1250
+ /** Impression once-per-(session, component) guard; reset on session rotation. */
1251
+ private impressedComponents;
1252
+ /** Last NON-EMPTY cart snapshot — `purchase` uses it because several flows
1253
+ * (Apple Pay) clear the cart BEFORE `vio:payment-success` fires. */
1254
+ private lastCartSnapshot;
1255
+ /** The `client` block (language, landing referrer / utm, screen, tz): read once per page load, reused on every event. */
1256
+ private client;
1257
+ /** The landing it was read from — persisted later when consent arrives after the first event. */
1258
+ private landing;
1259
+ /** The landing this manager resolved on this page load (the first event's), or null before it; read only — for the order's entry context when nothing is stored yet. */
1260
+ get currentLanding(): Landing | null;
1261
+ private teardown;
1262
+ /**
1263
+ * Install listeners + begin flushing. Explicit on purpose (no module
1264
+ * side-effects). Safe to call twice (second call only updates options).
1265
+ */
1266
+ /**
1267
+ * Consentimiento (ePrivacy/GDPR). Por defecto el SDK asume que el host ya
1268
+ * lo gestionó — su CMP decide si nos carga. Con `requireConsent: true`
1269
+ * arranca en modo **cookieless**: mide la visita con ids efímeros en
1270
+ * memoria y NO escribe nada en localStorage hasta que el host llame
1271
+ * `setConsent(true)`. Retirarlo borra lo persistido.
1272
+ */
1273
+ setConsent(granted: boolean): void;
1274
+ /** ¿Podemos escribir en el dispositivo? */
1275
+ private get canPersist();
1276
+ start(options?: AnalyticsStartOptions): void;
1277
+ /** Stop timers + listeners (tests / SPA unmount). Queue survives. */
1278
+ stop(): void;
1279
+ /** Attach the partner's user id (opaque) to all subsequent events. */
1280
+ identify(externalUserId: string | null): void;
1281
+ /** Queue one event. Works pre-init and pre-start (SSR: no-op). */
1282
+ track(name: AnalyticsEventName, opts?: TrackOptions): void;
1283
+ /**
1284
+ * Impression helper: observes an element and tracks ONE
1285
+ * `component_impression` per (session, campaignComponentId) when the
1286
+ * contract's rule is met (≥50% visible, ≥1s dwell). Returns an
1287
+ * unobserve function.
1288
+ */
1289
+ observeImpression(element: Element, context?: AnalyticsContext, opts?: {
1290
+ name?: Extract<AnalyticsEventName, 'component_impression' | 'ad_impression'>;
1291
+ /** Dedupe key override. Defaults to the strongest id available:
1292
+ * campaignComponentId → locationId → componentTemplateId. */
1293
+ key?: string;
1294
+ /** Called the one time the impression is tracked (e.g. to fire a
1295
+ * companion view_item_list). */
1296
+ onImpression?: () => void;
1297
+ }): () => void;
1298
+ /** Force a flush (mostly for tests). */
1299
+ flush(): Promise<void>;
1300
+ private buildEvent;
1301
+ /**
1302
+ * The `client` block: read once — the landing is remembered for the session
1303
+ * only when we may persist — then the same (frozen) object on every event.
1304
+ * `null` when there is nothing to say (no browser).
1305
+ */
1306
+ private clientBlock;
1307
+ /** Guarda la sesión solo si podemos escribir en el dispositivo. */
1308
+ private persistSession;
1309
+ private anonId;
1310
+ /** Rolling session: renewed by activity, rotated after 30 min idle. */
1311
+ private ensureSession;
1312
+ private trackSessionEnd;
1313
+ private flushWithBeacon;
1314
+ /**
1315
+ * Auto-instrumentation over the SDK's own DOM events — the host app
1316
+ * writes ZERO tracking code for the commerce funnel.
1317
+ */
1318
+ private installAutoListeners;
1319
+ /** The lines of the cart (current, else the pre-clear snapshot), optionally one sponsor's. */
1320
+ private cartLines;
1321
+ /**
1322
+ * The cart split per campaign — the shared rule of cart/slices.ts over the
1323
+ * current cart (else the pre-clear snapshot), plus whether any unit named
1324
+ * its campaign itself (a cart without origins is reported as before).
1325
+ */
1326
+ private cartSlices;
1327
+ /**
1328
+ * The context of one of several per-campaign events: the slice's campaign,
1329
+ * slot and content — only its own; when the slice spans several slots or
1330
+ * articles the event names none rather than the one the click came from.
1331
+ */
1332
+ private sliceContext;
1333
+ /**
1334
+ * The context of a single-campaign checkout/purchase: when the cart's origins
1335
+ * say which campaign they came from, the event says it too (plus the slot /
1336
+ * content when unique) — a cart without origins is exactly as before.
1337
+ */
1338
+ private singleSliceContext;
1339
+ /** Current cart → commerce payload; falls back to the pre-clear snapshot. */
1340
+ private cartCommerce;
1341
+ private findLine;
1342
+ }
1343
+ /**
1344
+ * The `campaign_id` of an event. In order: the context's explicit id; the
1345
+ * campaign assigned to the context's `slot` right now (ADR-0027 — only an
1346
+ * open assignment for the init platform counts, see `findSlotAssignment`);
1347
+ * the PAGE's campaign (`opts.pageCampaignId`, else `Vio.init({ campaignId })`)
1348
+ * when `campaigns[]` lists it as active (ADR-0034, amendment 3);
1349
+ * the active campaign of `campaigns[]` the event's sponsor takes part in, as
1350
+ * its primary or one of its secondaries — when it is in several, the
1351
+ * surface's default campaign if it is one of them, else the first one the
1352
+ * backend lists; the default campaign (`campaign.id`). `/v2/mobile/config`
1353
+ * has no top-level `campaignId` — reading one is why every event used to
1354
+ * leave with `campaign_id: 0` and the campaigns screen stayed empty.
1355
+ *
1356
+ * A malformed `campaigns[]` (not an array, a null entry) never breaks
1357
+ * `track()`: it falls back to `campaign.id`.
1358
+ */
1359
+ declare function resolveCampaignId(ctx: Pick<AnalyticsContext, 'campaignId' | 'sponsorId' | 'slot'>, boot: Pick<BootstrapResponse, 'campaign' | 'campaigns'> | null | undefined, opts?: {
1360
+ pageCampaignId?: CampaignHint;
1361
+ }): number | undefined;
1362
+ /**
1363
+ * `detail` of `vio:payment-success` as the checkout emits it. Four paths,
1364
+ * three shapes: a redirect return (`orderId` = Vio's checkout id), the
1365
+ * confirmation drawer and a provider's own receipt (`result` from the
1366
+ * provider or the backend, plus Vio's `checkoutId`), and Apple Pay express
1367
+ * from the cart (`result` with the backend's `confirmation`, no sponsor).
1368
+ */
1369
+ interface PaymentSuccessDetail {
1370
+ method?: string;
1371
+ sponsorId?: number | string;
1372
+ /** The slot the purchase started from, when the emitter knows it. */
1373
+ slot?: string;
1374
+ /** The campaign the emitter attributed the purchase to (its `Vio.attribution`). */
1375
+ campaignId?: number;
1376
+ /** Per-element content override (`vio-content-id` / `vio-content-title`), when the emitter carries one. */
1377
+ contentId?: string | number;
1378
+ contentTitle?: string;
1379
+ /** Redirect return: Vio's checkout id (the name predates `checkoutId`). */
1380
+ orderId?: string | number;
1381
+ /** Vio's checkout id — from the checkout state or the return URL. */
1382
+ checkoutId?: string | number;
1383
+ /**
1384
+ * The buyer reference the emitter learned with the payment — shopcart's
1385
+ * `buyer_ref`, a keyed hash of the email (`buyerRef` from the SDK's own
1386
+ * checkout; `buyer_ref` when a host passes the backend's answer through).
1387
+ * Becomes `commerce.buyer_id`; never an email.
1388
+ */
1389
+ buyerRef?: string | null;
1390
+ buyer_ref?: string | null;
1391
+ result?: PaymentSuccessResult | null;
1392
+ }
1393
+ /**
1394
+ * What the checkout attaches as `result`. Only `confirmation` carries a Vio
1395
+ * id: the order `ConfirmPaymentApplePay` created. `order.orderId` / `orderId`
1396
+ * are the PROVIDER's references (Qliro's, Walley's — the checkout itself
1397
+ * shows them as `providerRef`), and `chargedTotal` includes shipping on some
1398
+ * methods only. Analytics reads none of those.
1399
+ */
1400
+ interface PaymentSuccessResult {
1401
+ confirmation?: {
1402
+ orderId?: string | number | null;
1403
+ status?: string;
1404
+ buyerRef?: string | null;
1405
+ buyer_ref?: string | null;
1406
+ } | null;
1407
+ /** The checkout as a host's backend answered it, when the host passes it through. */
1408
+ checkout?: {
1409
+ buyerRef?: string | null;
1410
+ buyer_ref?: string | null;
1411
+ } | null;
1412
+ buyerRef?: string | null;
1413
+ buyer_ref?: string | null;
1414
+ [key: string]: unknown;
1415
+ }
1416
+ /**
1417
+ * The buyer reference of a `vio:payment-success` / `vio:checkout-open`
1418
+ * detail, wherever its emitter put it: top-level (`buyerRef`, or `buyer_ref`
1419
+ * as the backend spells it), on the result, on the result's `confirmation`
1420
+ * (Apple Pay) or `checkout`. Only a reference survives — never an email
1421
+ * (`normalizeBuyerRef`).
1422
+ */
1423
+ declare function buyerRefOf(d: {
1424
+ buyerRef?: unknown;
1425
+ buyer_ref?: unknown;
1426
+ result?: PaymentSuccessResult | null;
1427
+ } | null | undefined): string | undefined;
1428
+ /**
1429
+ * The `order_id` and `buyer_id` of a `purchase`. The id is ALWAYS a Vio id, never a provider's
1430
+ * reference. Normalized across every emitter: `orderId` (redirect return) →
1431
+ * `result.confirmation.orderId` (Apple Pay) → `checkoutId`. `value` and
1432
+ * `currency` are deliberately NOT read from the result: on every path they
1433
+ * come from the cart snapshot (sum of the items, no shipping), so revenue
1434
+ * stays comparable across payment methods — the charged total will arrive
1435
+ * through the server-side `order_paid` event. With nothing to say it
1436
+ * returns `{}`, so the cart snapshot keeps its keys.
1437
+ */
1438
+ declare function purchaseFromPaymentSuccess(d: PaymentSuccessDetail): Pick<AnalyticsCommerce, 'orderId' | 'buyerId'>;
1439
+
1440
+ /**
1441
+ * The cart split per campaign (ADR-0034) — ONE rule, shared by the SDK's own
1442
+ * `begin_checkout` / `purchase` events, by `Vio.cartSlices()` and so by any
1443
+ * host with its own analytics sink (Vev).
1444
+ *
1445
+ * Every unit of every line goes to the campaign of its origin — the one the
1446
+ * place showed when it was added — and units without one to the campaign the
1447
+ * caller's rule resolves for the line's sponsor (`resolveCampaign`). One slice
1448
+ * per campaign: its items (quantities from the origins, merged per product +
1449
+ * variant), its value with two decimals, and `slot` / `contentId` /
1450
+ * `sponsorId` only when they are the same for the whole slice. A cart with
1451
+ * one campaign is one slice. Pure; never throws on odd lines.
1452
+ */
1453
+
1454
+ /** An item of a slice — the analytics item shape (ids as given, normalized on the wire). */
1455
+ type VioItem = AnalyticsItemInput;
1456
+ /** One campaign's share of the cart. */
1457
+ interface CartSlice {
1458
+ campaignId?: number;
1459
+ sponsorId?: number;
1460
+ slot?: string;
1461
+ contentId?: string;
1462
+ items: VioItem[];
1463
+ value: number;
1464
+ currency?: string;
1465
+ /** 1-based position of this slice and how many there are. */
1466
+ slice: number;
1467
+ slices: number;
1468
+ }
1469
+ /** The campaign of a unit without an explicit one: the caller's rule (slot assignment → sponsor → default). */
1470
+ type ResolveCampaign = (slot: string | undefined, sponsorId: number) => number | undefined;
1471
+ declare function cartSlicesFrom(lines: ReadonlyArray<CartLineItem>, resolveCampaign: ResolveCampaign, fallbackCurrency?: string): CartSlice[];
1472
+
1473
+ /**
1474
+ * The attribution of a checkout (ADR-0035 phase B): what the order is born
1475
+ * knowing about the surface it was sold from, the campaign of the page, the
1476
+ * page itself and where the shopper came in from. Sent as `attribution` on
1477
+ * `CreateCheckout` and on the `UpdateCheckout` right before paying; shopcart
1478
+ * keeps it on the checkout (`checkout.attribution`, merged key by key) and
1479
+ * writes `order.surface_id` / `campaign_id` / `content_url` / `content_title`
1480
+ * / `entry_source` from it when the order is created. The surface itself is
1481
+ * checked there against the cart's channel: a page cannot credit a sale to
1482
+ * somebody else's surface.
1483
+ *
1484
+ * Pure: `checkoutAttributionOf()` takes what the facade gathered. snake_case
1485
+ * on the wire, the caps of shopcart's `CheckoutAttributionDto` enforced here.
1486
+ */
1487
+
1488
+ /** `EntryContextDto`: what the page knew when the shopper came in (the SDK's landing memory). */
1489
+ interface EntryContextWire {
1490
+ referrer?: string;
1491
+ utm_source?: string;
1492
+ utm_medium?: string;
1493
+ utm_campaign?: string;
1494
+ landing_url?: string;
1495
+ }
1496
+ /** `CheckoutAttributionDto` (shopcart `checkout/dtos/checkout-attribution.dto.ts`). */
1497
+ interface CheckoutAttributionWire {
1498
+ surface_key?: string;
1499
+ campaign_id?: number;
1500
+ content_url?: string;
1501
+ content_title?: string;
1502
+ entry?: EntryContextWire;
1503
+ }
1504
+ /** The caps of `CheckoutAttributionDto` / `EntryContextDto`. */
1505
+ declare const CHECKOUT_ATTRIBUTION_CAPS: Readonly<{
1506
+ surfaceKey: 255;
1507
+ contentUrl: 2048;
1508
+ contentTitle: 255;
1509
+ referrer: 2048;
1510
+ utm: 128;
1511
+ landingUrl: 2048;
1512
+ }>;
1513
+ interface CheckoutAttributionInput {
1514
+ /** The surface's SDK key (`Vio.init({ apiKey })`) — shopcart resolves the surface from it. */
1515
+ surfaceKey?: string;
1516
+ /** The campaign the PAGE belongs to, when the bootstrap lists it as active (`Vio.pageCampaign()`). */
1517
+ pageCampaignId?: number;
1518
+ /** The cart split per campaign (`Vio.cartSlices(sponsorId)`), for the campaign that explains most units when the page has none. */
1519
+ slices?: ReadonlyArray<CartSlice>;
1520
+ /** The page at pay time: `Vio.content()`'s url and title. */
1521
+ content?: {
1522
+ url?: string;
1523
+ title?: string;
1524
+ };
1525
+ /** Where the session came in (`resolveLanding()`): referrer, utm, landing page. */
1526
+ landing?: Landing | null;
1527
+ /**
1528
+ * The surface's privacy mode. Only on a `standard` surface do the page
1529
+ * (`content_url`, `content_title`) and the entry context travel: which
1530
+ * screen the sale was made on and why the shopper was there is what
1531
+ * `minimal` keeps private — the same promise the collector keeps for the
1532
+ * events. `unknown` (it could not be learnt) counts as `minimal`: what can
1533
+ * reveal it is only sent when the surface is known to allow it. The surface
1534
+ * and the campaign always travel.
1535
+ */
1536
+ privacyMode?: SurfacePrivacyMode | 'unknown';
1537
+ }
1538
+ /**
1539
+ * The attribution for the wire, or `undefined` when there is nothing to say.
1540
+ * The campaign is the page's; without one, the campaign that explains most
1541
+ * units of the cart under the same rule `purchase` is split by (ties: the
1542
+ * higher value, then the first). The page (origin + path) and the entry go
1543
+ * only on a `standard` surface.
1544
+ */
1545
+ declare function checkoutAttributionOf(input: CheckoutAttributionInput): CheckoutAttributionWire | undefined;
1546
+ /** The landing as `entry`, capped; `undefined` when it says nothing. */
1547
+ declare function entryContextOf(landing: Landing | null | undefined): EntryContextWire | undefined;
1548
+ /**
1549
+ * The campaign that explains most units of the cart — over the slices
1550
+ * `purchase` is split by, so the order names the campaign the biggest
1551
+ * purchase event names. Ties go to the higher value, then to the first
1552
+ * slice. Units nobody attributes (a slice without campaign) never win.
1553
+ */
1554
+ declare function dominantCampaignOf(slices: ReadonlyArray<CartSlice> | null | undefined): number | undefined;
1555
+
1556
+ /**
1557
+ * Vipps MobilePay Payment Adapter — GraphQL Integration & Types.
1558
+ *
1559
+ * Vipps payment integration uses 2 GraphQL operations:
1560
+ *
1561
+ * 1. `CreatePaymentVipps` mutation:
1562
+ * Initiates a Vipps payment session for a checkout and returns `payment_url`.
1563
+ *
1564
+ * 2. `GetVippsStatus` query:
1565
+ * Queries Vipps payment state directly for a checkout (`state`).
1566
+ */
1567
+
1568
+ /**
1569
+ * GraphQL mutation to create a Vipps payment session.
1570
+ */
1571
+ declare const CREATE_PAYMENT_VIPPS_MUTATION = "\nmutation CreatePaymentVipps($checkoutId: String!, $email: String, $returnUrl: String!, $express: Boolean) {\n Payment {\n CreatePaymentVipps(checkout_id: $checkoutId, email: $email, return_url: $returnUrl, express: $express) {\n payment_url\n reference\n express\n reason\n }\n }\n}\n";
1572
+ /**
1573
+ * GraphQL query to fetch current Vipps payment status.
1574
+ */
1575
+ declare const GET_VIPPS_STATUS_QUERY = "\nquery GetVippsStatus($checkoutId: String!) {\n Payment {\n GetVippsStatus(checkout_id: $checkoutId) {\n state\n duplicate_of\n }\n }\n}\n";
1576
+ interface CreatePaymentVippsVariables extends Record<string, unknown> {
1577
+ checkoutId: string;
1578
+ /** Optional since Express: Vipps hands the email back with the payment. */
1579
+ email?: string;
1580
+ returnUrl: string;
1581
+ /**
1582
+ * `true` asks for Express — address and delivery chosen inside the Vipps
1583
+ * app. When the cart cannot have it, no payment is created and the answer
1584
+ * says `express: false` with the reason; the caller then opens the
1585
+ * ordinary checkout.
1586
+ */
1587
+ express?: boolean;
1588
+ }
1589
+ interface CreatePaymentVippsResponse {
1590
+ /** Absent when Express was asked for and refused. */
1591
+ payment_url?: string;
1592
+ /** The reference the seller reads in its Vipps portal. */
1593
+ reference?: string;
1594
+ express?: boolean;
1595
+ reason?: string;
1596
+ }
1597
+ interface GetVippsStatusVariables extends Record<string, unknown> {
1598
+ checkoutId: string;
1599
+ }
1600
+ interface VippsStatusResult {
1601
+ state: string;
1602
+ /** Set when this checkout was closed as a duplicate: the checkout that paid the cart. */
1603
+ duplicate_of?: string | null;
1604
+ }
1605
+ type VippsPaymentState = 'CREATED' | 'INITIATED' | 'AUTHORIZED' | 'TERMINATED' | 'EXPIRED' | string;
1606
+ /**
1607
+ * Executes the `CreatePaymentVipps` GraphQL mutation.
1608
+ */
1609
+ declare function createPaymentVipps(variables: CreatePaymentVippsVariables | Record<string, unknown>, options?: CartQueryOptions): Promise<CreatePaymentVippsResponse | null>;
1610
+ /**
1611
+ * Executes the `GetVippsStatus` GraphQL query.
1612
+ */
1613
+ declare function getVippsStatus(variables: GetVippsStatusVariables | Record<string, unknown>, options?: CartQueryOptions): Promise<VippsStatusResult | null>;
1614
+
1615
+ declare const CREATE_CART_MUTATION = "\nmutation CreateCart($customerSessionId: String!, $currency: String!, $shippingCountry: String) {\n Cart {\n CreateCart(customer_session_id: $customerSessionId, currency: $currency, shipping_country: $shippingCountry) {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n }\n}\n";
1616
+ declare const ADD_ITEM_MUTATION = "\nmutation AddItem($cartId: String!, $lineItems: [LineItemInput!]!) {\n Cart {\n AddItem(cart_id: $cartId, line_items: $lineItems) {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n }\n}\n";
1617
+ declare const DELETE_ITEM_MUTATION = "\nmutation DeleteItem($cartId: String!, $cartItemId: String!) {\n Cart {\n DeleteItem(cart_id: $cartId, cart_item_id: $cartItemId) {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n }\n}\n";
1618
+ declare const UPDATE_ITEM_MUTATION: string;
1619
+ /** `UpdateItem` with the `origin` of the added units (`CartLineOriginInput`, snake_case fields — see `lineOriginWire`). */
1620
+ declare const UPDATE_ITEM_WITH_ORIGIN_MUTATION: string;
1621
+ declare const GET_CART_QUERY = "\nquery GetCart($cartId: String!) {\n Cart {\n GetCart(cart_id: $cartId) {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n }\n}\n";
1622
+ declare const GET_LINE_ITEMS_BY_SUPPLIER_QUERY = "\nquery GetLineItemsBySupplier($cartId: String!) {\n Cart {\n GetLineItemsBySupplier(cart_id: $cartId) {\n supplier {\n id\n name\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n }\n }\n}\n";
1623
+ declare const UPDATE_SHIPPINGS_BY_SUPPLIER_MUTATION = "\nmutation UpdateShippingsBySupplier($cartId: String!, $data: [DataUpdateShippingsBySupplier!]!) {\n Cart {\n UpdateShippingsBySupplier(cart_id: $cartId, data: $data) {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n }\n}\n";
1624
+ declare const CREATE_CHECKOUT_MUTATION: string;
1625
+ /** `CreateCheckout` with the checkout's `attribution` (`CheckoutAttributionInput`, snake_case fields — see `checkoutAttributionOf`). */
1626
+ declare const CREATE_CHECKOUT_WITH_ATTRIBUTION_MUTATION: string;
1627
+ declare const UPDATE_CHECKOUT_MUTATION: string;
1628
+ /** `UpdateCheckout` with the checkout's `attribution` (`CheckoutAttributionInput`). */
1629
+ declare const UPDATE_CHECKOUT_WITH_ATTRIBUTION_MUTATION: string;
1630
+ declare const GET_CHECKOUT_QUERY = "\nquery GetCheckout($checkoutId: String!) {\n Checkout {\n GetCheckout(checkout_id: $checkoutId) {\n buyer_accepts_purchase_conditions\n buyer_accepts_terms_conditions\n created_at\n updated_at\n id\n deleted_at\n success_url\n cancel_url\n payment_method\n email\n status\n checkout_url\n origin_payment_id\n duplicate_of\n billing_address {\n id\n first_name\n last_name\n phone_code\n phone\n company\n address1\n address2\n city\n province\n province_code\n country\n country_code\n zip\n }\n shipping_address {\n id\n first_name\n last_name\n phone_code\n phone\n company\n address1\n address2\n city\n province\n province_code\n country\n country_code\n zip\n }\n available_payment_methods {\n name\n }\n discount_code\n cart {\n cart_id\n customer_session_id\n shipping_country\n line_items {\n id\n supplier\n image {\n id\n url\n width\n height\n }\n sku\n barcode\n brand\n product_id\n title\n variant_id\n variant_title\n variant {\n option\n value\n }\n quantity\n price {\n amount\n currency_code\n discount\n compare_at\n compare_at_incl_taxes\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n shipping {\n id\n name\n description\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n available_shippings {\n id\n name\n description\n country_code\n price {\n amount\n currency_code\n amount_incl_taxes\n tax_amount\n tax_rate\n }\n }\n }\n subtotal\n shipping\n currency\n available_shipping_countries\n }\n totals {\n currency_code\n subtotal\n shipping\n total\n taxes\n tax_rate\n discounts\n }\n }\n }\n}\n";
1631
+ declare const GET_AVAILABLE_PAYMENT_METHODS_QUERY = "\nquery Config {\n Payment {\n GetAvailablePaymentMethods {\n config {\n name\n type\n value\n }\n name\n }\n }\n}\n";
1632
+
1633
+ /** Transport options for a cart/checkout GraphQL call. */
1634
+ interface CartQueryOptions {
1635
+ endpoint?: string;
1636
+ apiKey?: string;
1637
+ /** Sponsor commerce key — goes in the Authorization header. */
1638
+ commerceKey?: string;
1639
+ /** True when the commerce key came from a resolved sponsor (bootstrap).
1640
+ * False = we fell back to the host apiKey — writes like CreateCart should
1641
+ * NOT proceed with the wrong key (the cart would be orphaned). */
1642
+ sponsorResolved?: boolean;
1643
+ }
1644
+ /**
1645
+ * Resolve endpoint + keys for cart GraphQL calls. Awaits Vio.bootstrap() once
1646
+ * if it hasn't run yet (the sponsor commerce keys come from bootstrap), then
1647
+ * uses the sponsor's commerce apiKey (via the Vio facade on globalThis,
1648
+ * avoiding an import cycle); falls back to the host apiKey.
1649
+ */
1650
+ declare function getCartGraphQLOptions(sponsorId?: number): Promise<CartQueryOptions>;
1651
+ /** Stable per-browser customer session id (backend CreateCart requires one). */
1652
+ declare function getCustomerSessionId(): string;
1653
+ interface GraphQLEnvelope {
1654
+ data?: Record<string, Record<string, unknown>> | null;
1655
+ errors?: Array<{
1656
+ message?: string;
1657
+ path?: unknown;
1658
+ }>;
1659
+ }
1660
+ /** Execute a GraphQL query/mutation against the configured commerce endpoint.
1661
+ * Callers that skip `getCartGraphQLOptions()` (or pass a bare sponsorId) get
1662
+ * it resolved here instead of silently sending an unauthenticated request.
1663
+ * Rejects after `CART_GRAPHQL_TIMEOUT_MS` (and aborts the fetch). */
1664
+ declare function executeCartGraphQL(query: string, variables: Record<string, unknown>, options?: CartQueryOptions | number | undefined): Promise<GraphQLEnvelope>;
1665
+ declare function createCart(customerSessionId: string, currency: string, shippingCountry?: string | null, options?: CartQueryOptions): Promise<any>;
1666
+ /**
1667
+ * `AddItem`. A line may carry `origin` (`LineOriginWire`: where its units
1668
+ * come from — ADR-0035 phase B). A gateway that predates the field refuses
1669
+ * the whole mutation at validation (`LineItemInput` has no `origin`), so the
1670
+ * lines are sent again without it, once per page load — see gateway-features.
1671
+ */
1672
+ declare function addItem(cartId: string, lineItems: unknown[], options?: CartQueryOptions): Promise<any>;
1673
+ declare function deleteItem(cartId: string, cartItemId: string, options?: CartQueryOptions): Promise<any>;
1674
+ /**
1675
+ * `UpdateItem`. `extra.origin` is where the units a quantity INCREASE adds
1676
+ * come from (ADR-0035 phase B); the server credits the new units to it. Sent
1677
+ * only with it; a gateway that predates the argument gets the legacy
1678
+ * mutation instead, once per page load — see gateway-features.
1679
+ */
1680
+ declare function updateItem(cartId: string, cartItemId: string, shippingId?: string | null, qty?: number | null, options?: CartQueryOptions, extra?: {
1681
+ origin?: LineOriginWire;
1682
+ }): Promise<any>;
1683
+ declare function getCart(cartId: string, options?: CartQueryOptions): Promise<any>;
1684
+ declare function getLineItemsBySupplier(cartId: string, options?: CartQueryOptions): Promise<any>;
1685
+ declare function updateShippingsBySupplier(cartId: string, data: unknown[], options?: CartQueryOptions): Promise<any>;
1686
+ /**
1687
+ * `CreateCheckout`. With `extra.attribution` (`CheckoutAttributionWire`:
1688
+ * the surface, the page's campaign, the page and the entry — ADR-0035 phase
1689
+ * B) the checkout is born attributed; a gateway that predates the argument
1690
+ * gets the legacy mutation, once per page load — see gateway-features.
1691
+ */
1692
+ declare function createCheckout(cartId: string, options?: CartQueryOptions, extra?: {
1693
+ attribution?: CheckoutAttributionWire;
1694
+ }): Promise<any>;
1695
+ /**
1696
+ * `UpdateCheckout`. `variables.attribution` (`CheckoutAttributionWire`) is
1697
+ * merged key by key over what the checkout has; a gateway that predates the
1698
+ * argument gets the legacy mutation without it, once per page load.
1699
+ */
1700
+ declare function updateCheckout(variables: Record<string, unknown>, options?: CartQueryOptions): Promise<any>;
1701
+ declare function getCheckout(checkoutId: string, options?: CartQueryOptions): Promise<any>;
1702
+ /** What a checkout says of itself after paying: its Vio order number, once the order exists, and its buyer reference. */
1703
+ interface CheckoutReference {
1704
+ orderNumber: number | null;
1705
+ buyerRef: string | null;
1706
+ }
1707
+ /** The order number (null while the order does not exist yet) and the buyer reference (null when the API does not say it). */
1708
+ declare function getCheckoutReference(checkoutId: string, options?: CartQueryOptions): Promise<CheckoutReference>;
1709
+ declare function getAvailablePaymentMethods(options?: CartQueryOptions): Promise<any>;
1710
+ declare const CREATE_PAYMENT_STRIPE_MUTATION = "\nmutation CreatePaymentStripe($checkoutId: String!, $successUrl: String!, $paymentMethod: String!, $email: String!) {\n Payment {\n CreatePaymentStripe(checkout_id: $checkoutId, success_url: $successUrl, payment_method: $paymentMethod, email: $email) {\n order_id\n checkout_url\n }\n }\n}\n";
1711
+ declare function createPaymentStripe(variables: Record<string, unknown>, options?: CartQueryOptions): Promise<any>;
1712
+
1713
+ /**
1714
+ * Stripe on our own page — the Payment Element, no redirect.
1715
+ *
1716
+ * The older web flow minted a Stripe Payment Link and sent the shopper to a
1717
+ * page hosted by Stripe. This one keeps them here (Angelo, 2026-09-24):
1718
+ *
1719
+ * 1. Vio Commerce creates a PaymentIntent for the checkout
1720
+ * (`Payment { CreatePaymentIntentStripe }`) and answers with its client
1721
+ * secret AND the publishable key of the account that minted it — the
1722
+ * seller's when they brought both keys, ours otherwise. The two are
1723
+ * halves of one account: the browser confirms with the key what the
1724
+ * server minted with the secret one.
1725
+ * 2. Stripe's Payment Element is mounted in a LIGHT-DOM container, the way
1726
+ * the other embedded widgets are. Card fields are Stripe's own iframes,
1727
+ * so card data never touches this SDK or our servers.
1728
+ * 3. `confirm()` pays. A 3-D Secure challenge opens in Stripe's own modal
1729
+ * over the page: `redirect: 'if_required'` keeps the shopper here for
1730
+ * cards, and still redirects for a method that has no other way.
1731
+ * 4. The Commerce order is NOT born here. Stripe's `payment_intent.succeeded`
1732
+ * webhook creates it, verified server-side; the checkout is polled for
1733
+ * its status afterwards, exactly as the redirect return does.
1734
+ */
1735
+
1736
+ /** What the backend hands over to pay a checkout on our page. */
1737
+ interface StripeIntent {
1738
+ /** `pi_..._secret_...`: what the browser confirms. */
1739
+ client_secret: string;
1740
+ /** The key of the SAME account that minted the secret. */
1741
+ publishable_key: string;
1742
+ customer?: string;
1743
+ /**
1744
+ * Stripe Connect (ADR-0022): the seller's connected account, where the
1745
+ * intent lives. The browser must name it or Stripe answers "no such
1746
+ * payment_intent". Absent for every seller not on Connect.
1747
+ */
1748
+ stripe_account?: string;
1749
+ }
1750
+ /** What `confirm()` answers. The browser's word is never the order. */
1751
+ type StripeConfirmOutcome = {
1752
+ status: 'succeeded';
1753
+ paymentIntentId?: string;
1754
+ }
1755
+ /** Authorised but not settled yet, or Stripe redirected and will return. */
1756
+ | {
1757
+ status: 'pending';
1758
+ paymentIntentId?: string;
1759
+ } | {
1760
+ status: 'failed';
1761
+ message?: string;
1762
+ code?: string;
1763
+ };
1764
+ interface StripeElementHandle {
1765
+ confirm(): Promise<StripeConfirmOutcome>;
1766
+ unmount(): void;
1767
+ }
1768
+
1769
+ /**
1770
+ * Apple Pay on the Web — via Stripe Payment Request API.
1771
+ *
1772
+ * Architecture decision (matches iOS Vio SDK pattern):
1773
+ * - One Stripe **publishable key** for the Vio platform (global, set
1774
+ * via `Vio.init({ stripePublishableKey })`).
1775
+ * - One **Stripe Connect account id** per sponsor — sourced from
1776
+ * `Vio.bootstrap()` response. Without it, the payment lands on the
1777
+ * platform account instead of the merchant.
1778
+ *
1779
+ * Apple Pay on the Web prerequisites (Stripe-managed for us):
1780
+ * - Stripe Connect account is enabled for Apple Pay
887
1781
  * - Domain registration for Apple Pay (Stripe handles via Dashboard)
888
1782
  * - Safari + macOS/iOS device with Apple Pay configured
889
1783
  *
@@ -1492,8 +2386,20 @@ interface KlarnaPaymentsHandle {
1492
2386
  /** Tear down the mounted widget. */
1493
2387
  unmount(): void;
1494
2388
  }
2389
+ /**
2390
+ * What the facade lends the manager. `orderAttribution` answers the
2391
+ * attribution of the order about to be created for a sponsor's cart
2392
+ * (`Vio.orderAttribution`, ADR-0035 phase B) — the surface, the page's
2393
+ * campaign, the page and the entry; sent as `attribution` on `CreateCheckout`
2394
+ * and on the `UpdateCheckout` before paying. Optional: without it (a manager
2395
+ * built apart from the facade) nothing is sent and nothing changes.
2396
+ */
2397
+ interface CheckoutManagerDeps {
2398
+ orderAttribution?: (sponsorId: number) => Promise<CheckoutAttributionWire | undefined> | CheckoutAttributionWire | undefined;
2399
+ }
1495
2400
  declare class CheckoutManager extends EventTarget {
1496
2401
  private readonly cartManager;
2402
+ private readonly deps;
1497
2403
  private state;
1498
2404
  /** Counts `open()` calls — see CheckoutState.session. */
1499
2405
  private sessionSeq;
@@ -1531,12 +2437,18 @@ declare class CheckoutManager extends EventTarget {
1531
2437
  /** Per-sponsor payment methods cache + in-flight dedupe. */
1532
2438
  private paymentMethodsCache;
1533
2439
  private paymentMethodsPromises;
1534
- constructor(cartManager: CartManager);
2440
+ constructor(cartManager: CartManager, deps?: CheckoutManagerDeps);
1535
2441
  open(sponsorId: number): CheckoutState;
1536
2442
  close(): void;
1537
- /** Create the backend checkout for the sponsor's cart (auto-accepts terms). */
2443
+ /**
2444
+ * The attribution of the order this sponsor's cart is about to become
2445
+ * (ADR-0035 phase B), through the facade; `undefined` when there is none
2446
+ * to give or it fails — attribution never costs a checkout.
2447
+ */
2448
+ private attributionFor;
2449
+ /** Create the backend checkout for the sponsor's cart (auto-accepts terms); born attributed when the facade knows the attribution. */
1538
2450
  createCheckout(sponsorId: number): Promise<any>;
1539
- /** Update the backend checkout (terms are re-asserted unless overridden). */
2451
+ /** Update the backend checkout (terms are re-asserted unless overridden; the attribution rides along unless the caller gives its own). */
1540
2452
  updateCheckout(variables: Record<string, unknown>, sponsorId?: number): Promise<any>;
1541
2453
  getCheckout(checkoutId: string, sponsorId?: number): Promise<any>;
1542
2454
  /**
@@ -1545,6 +2457,15 @@ declare class CheckoutManager extends EventTarget {
1545
2457
  * receipt, and a receipt does not fail for it.
1546
2458
  */
1547
2459
  getOrderNumber(checkoutId: string, sponsorId?: number): Promise<number | null>;
2460
+ /**
2461
+ * What a paid checkout says of itself: the order number (as above) and the
2462
+ * buyer reference — shopcart's keyed hash of the buyer's email, what the
2463
+ * `vio:payment-success` detail carries as `buyerRef` and analytics sends as
2464
+ * `buyer_id`. Never throws; `null` for whatever the API does not say.
2465
+ */
2466
+ getOrderReference(checkoutId: string, sponsorId?: number): Promise<CheckoutReference>;
2467
+ /** In-flight `getOrderReference` per checkout id (see there). */
2468
+ private referenceInFlight;
1548
2469
  /**
1549
2470
  * Payment methods enabled for the sponsor (backend-configured). Memoised per
1550
2471
  * sponsor with in-flight dedupe — several UI components ask on every open.
@@ -1866,339 +2787,60 @@ declare class CheckoutManager extends EventTarget {
1866
2787
  *
1867
2788
  * Returns the button handle so the UI can unmount on teardown.
1868
2789
  */
1869
- mountKlarnaExpress(container: HTMLElement): Promise<KlarnaButtonHandle>;
1870
- /**
1871
- * Klarna Payments — classic widget flow (server client_token). Creates a
1872
- * session on vio-backend, then mounts Klarna's inline widget into
1873
- * `container`. Returns a handle to switch category and to authorize → which
1874
- * on approval creates the order via the same backend /orders route as KEC.
1875
- *
1876
- * Unlike `mountKlarnaExpress`, this needs no public `klarnaClientId` and no
1877
- * origin handshake — auth is the server-side API key.
1878
- */
1879
- mountKlarnaPayments(container: HTMLElement, opts?: {
1880
- withShipping?: boolean;
1881
- shippingId?: string;
1882
- category?: string;
1883
- }): Promise<KlarnaPaymentsHandle>;
1884
- /** True if the Klarna Payments widget lib can load (UI gate). */
1885
- klarnaPaymentsAvailable(): Promise<boolean>;
1886
- /** Cart snapshot + chosen shipping line/amount, for express purchases. */
1887
- private buildKlarnaInstantContext;
1888
- /**
1889
- * Express instant purchase — go straight to Klarna's own modal, no checkout
1890
- * overlay. Creates a session (with shipping options), loads the widget into a
1891
- * hidden container, then authorizes (which opens Klarna's confirm modal). On
1892
- * approval creates the order → `payment-complete` (host shows confirmation);
1893
- * on failure → `payment-error`. Call `open(sponsorId)` first.
1894
- */
1895
- startKlarnaInstant(): Promise<void>;
1896
- /**
1897
- * REDIRECT path: call once on app load. If a Klarna purchase was launched
1898
- * (pending context persisted) and we're back with a token — from the URL or
1899
- * the SDK's resumed `complete` event — finish creating the order + confirm.
1900
- */
1901
- resumeKlarnaReturn(): Promise<void>;
1902
- /** Snapshot of the active cart for redirect recovery (minor units). */
1903
- private buildKlarnaPendingContext;
1904
- /**
1905
- * POST the token + order lines to vio-backend (it holds the secret API key
1906
- * and creates the real Klarna order). On success → `payment-complete`; on
1907
- * failure → `payment-error`. Idempotent: clears the pending key so the
1908
- * popup and redirect paths can't double-fire.
1909
- */
1910
- private completeKlarnaOrder;
1911
- get currentState(): CheckoutState | null;
1912
- get items(): CartLineItem[];
1913
- /**
1914
- * Resolve the Stripe Connect account for the active sponsor — for now
1915
- * pulled from bootstrap cache if present. Returns undefined if not set
1916
- * (Stripe will route to the platform account in that case).
1917
- */
1918
- private findStripeConnectAccount;
1919
- /** The sponsor's connected account, read fresh from its channel config. */
1920
- private resolveStripeConnectAccount;
1921
- private emit;
1922
- }
1923
-
1924
- /**
1925
- * Vio.analytics — the web SDK's half of the Vio Analytics pipeline.
1926
- *
1927
- * Events flow to the Vio collector (`POST <eventsBase>/v1/events`, repo
1928
- * vio-live/vio-analytics) which owns raw storage (ClickHouse) and vendor
1929
- * fan-out (Mixpanel today). THE SDK NEVER TALKS TO VENDORS — swapping or
1930
- * dropping a vendor is a server-side change, zero client releases.
1931
- * Wire contract: vio-analytics `docs/EVENTS_CONTRACT.md` (v1, snake_case).
1932
- *
1933
- * Design rules:
1934
- * - SIDE-EFFECT-FREE MODULE. Nothing runs at import time (tsup/tree-shaking
1935
- * contract, see lessons/web-sdk-tsup-singleton-and-build). Listeners are
1936
- * installed by an explicit `Vio.analytics.start()`.
1937
- * - `track()` works BEFORE `Vio.init()` — events queue and flush once the
1938
- * SDK is configured (transport resolves at flush time, not at track time).
1939
- * - SSR-safe: without `window` every call is a silent no-op.
1940
- * - Retries are safe: `event_id` is stable per event, the collector
1941
- * dedupes. Queue is bounded (drop-oldest) so a dead collector can never
1942
- * grow memory unbounded.
1943
- * - Anti-double-count: the SDK only reports what the server can't see.
1944
- * Votes/participations are server truth; `ad_activation`/`cart_intent`
1945
- * are mirrored server-side, never from here.
1946
- *
1947
- * Three sinks, matching the Vev precedent (vio-vev analytics.ts, which
1948
- * becomes an adapter over this in F3):
1949
- * 1. collector (default ON once started)
1950
- * 2. window.dataLayer — GA4/GTM (opt-in `start({ dataLayer: true })`,
1951
- * the publisher-facing feature; NOT part of the Vio pipeline)
1952
- * 3. `vio:analytics` DOM event — always when started (inspector/bridges)
1953
- */
1954
-
1955
- declare const ANALYTICS_EVENT_NAMES: readonly ["view_item_list", "select_item", "view_item", "add_to_cart", "remove_from_cart", "view_cart", "begin_checkout", "purchase", "component_impression", "component_click", "ad_impression", "ad_click", "poll_impression", "contest_impression", "session_start", "session_end", "checkout_error", "sdk_error"];
1956
- type AnalyticsEventName = (typeof ANALYTICS_EVENT_NAMES)[number];
1957
- /** Camel-case for DX; mapped to the snake_case wire format at build time. */
1958
- interface AnalyticsContext {
1959
- campaignId?: number;
1960
- broadcastId?: string;
1961
- campaignComponentId?: number;
1962
- appPlacementId?: number;
1963
- locationId?: string;
1964
- componentTemplateId?: string;
1965
- sponsorId?: number;
1966
- activationId?: number;
1967
- contentUrl?: string;
1968
- /**
1969
- * The host's own id for the piece of content the component sits in — an
1970
- * article id in a CMS, a page id in a site builder. Carried verbatim so the
1971
- * host can join Vio's funnel back onto its own per-article reporting
1972
- * (revenue stops being an estimate). Left alone by the SDK.
1973
- */
1974
- contentId?: string | number;
1975
- /** Human-readable content snapshot; auto-filled from document.title. */
1976
- contentTitle?: string;
1977
- /** Código corto del fallo (`sdk_error` / `checkout_error`). */
1978
- errorCode?: string;
1979
- variant?: string;
1980
- /**
1981
- * The slot (ADR-0027) the component sits in — its `vio-slot`. Attribution
1982
- * follows it: the event's `campaign_id` is the campaign assigned to the slot
1983
- * right now, before the sponsor rule. On the wire it fills `location_id`
1984
- * when no explicit `locationId` is given (a slot IS a location id to the
1985
- * campaigns service).
1986
- */
1987
- slot?: string;
1988
- }
1989
- interface AnalyticsItemInput {
1990
- productId: number | string;
1991
- name?: string;
1992
- brand?: string;
1993
- variantId?: number | string;
1994
- price?: number;
1995
- quantity?: number;
1996
- }
1997
- interface AnalyticsCommerce {
1998
- items?: AnalyticsItemInput[];
1999
- value?: number;
2000
- currency?: string;
2001
- orderId?: string;
2002
- paymentMethod?: string;
2003
- }
2004
- interface TrackOptions {
2005
- context?: AnalyticsContext;
2006
- commerce?: AnalyticsCommerce;
2007
- props?: Record<string, unknown>;
2008
- }
2009
- interface AnalyticsStartOptions {
2010
- /** Where the SDK is embedded: 'vev' | 'replit' | 'custom' | … Default 'custom'. */
2011
- host?: string;
2012
- /**
2013
- * Arrancar en modo cookieless hasta que el host llame `setConsent(true)`.
2014
- * Default false: el SDK asume que el CMP del publisher ya decidió si nos
2015
- * carga. Los publishers EU que necesitan medir antes del consentimiento
2016
- * (o no pueden persistir sin él) ponen true.
2017
- */
2018
- requireConsent?: boolean;
2019
- /**
2020
- * Install the automatic funnel listeners (vio:added-to-cart,
2021
- * vio:checkout-open, vio:open-cart, vio:payment-success). Default true.
2022
- * Hosts with their OWN instrumentation choke point (e.g. the Vev module,
2023
- * which forwards every event through trackEvent()) set false so the same
2024
- * user action is never tracked twice — they keep the session/batching/
2025
- * transport engine and call track() themselves.
2026
- */
2027
- autoTrack?: boolean;
2028
- /**
2029
- * Adopt the host's session id instead of minting one. A host that already
2030
- * tracks its readers (its own impressions, dwell, clicks) needs Vio's
2031
- * purchases to land in the SAME session, or the two datasets cannot be
2032
- * joined. Pass the id the host already stores; omit it and the SDK keeps
2033
- * its own rotating session.
2034
- */
2035
- sessionId?: string;
2036
- /** Send to the Vio collector. Default true. */
2037
- collector?: boolean;
2038
- /** Also push GA4 e-commerce events to window.dataLayer (publisher feature). */
2039
- dataLayer?: boolean;
2040
- /** console.debug every event. */
2041
- debug?: boolean;
2042
- }
2043
- declare class AnalyticsManager extends EventTarget {
2044
- private started;
2045
- private options;
2046
- private queue;
2047
- private flushTimer;
2048
- private retryAttempt;
2049
- private retryNotBefore;
2050
- private externalUserId;
2051
- private sessionId;
2052
- private requireConsent;
2053
- private consentGranted;
2054
- private anonIdCache;
2055
- /** Set via start({ sessionId }) — the host owns the session, we follow. */
2056
- private externalSessionId;
2057
- private sessionStartedAt;
2058
- /** Impression once-per-(session, component) guard; reset on session rotation. */
2059
- private impressedComponents;
2060
- /** Last NON-EMPTY cart snapshot — `purchase` uses it because several flows
2061
- * (Apple Pay) clear the cart BEFORE `vio:payment-success` fires. */
2062
- private lastCartSnapshot;
2063
- private teardown;
2064
- /**
2065
- * Install listeners + begin flushing. Explicit on purpose (no module
2066
- * side-effects). Safe to call twice (second call only updates options).
2067
- */
2068
- /**
2069
- * Consentimiento (ePrivacy/GDPR). Por defecto el SDK asume que el host ya
2070
- * lo gestionó — su CMP decide si nos carga. Con `requireConsent: true`
2071
- * arranca en modo **cookieless**: mide la visita con ids efímeros en
2072
- * memoria y NO escribe nada en localStorage hasta que el host llame
2073
- * `setConsent(true)`. Retirarlo borra lo persistido.
2074
- */
2075
- setConsent(granted: boolean): void;
2076
- /** ¿Podemos escribir en el dispositivo? */
2077
- private get canPersist();
2078
- start(options?: AnalyticsStartOptions): void;
2079
- /** Stop timers + listeners (tests / SPA unmount). Queue survives. */
2080
- stop(): void;
2081
- /** Attach the partner's user id (opaque) to all subsequent events. */
2082
- identify(externalUserId: string | null): void;
2083
- /** Queue one event. Works pre-init and pre-start (SSR: no-op). */
2084
- track(name: AnalyticsEventName, opts?: TrackOptions): void;
2790
+ mountKlarnaExpress(container: HTMLElement): Promise<KlarnaButtonHandle>;
2085
2791
  /**
2086
- * Impression helper: observes an element and tracks ONE
2087
- * `component_impression` per (session, campaignComponentId) when the
2088
- * contract's rule is met (≥50% visible, ≥1s dwell). Returns an
2089
- * unobserve function.
2792
+ * Klarna Payments — classic widget flow (server client_token). Creates a
2793
+ * session on vio-backend, then mounts Klarna's inline widget into
2794
+ * `container`. Returns a handle to switch category and to authorize → which
2795
+ * on approval creates the order via the same backend /orders route as KEC.
2796
+ *
2797
+ * Unlike `mountKlarnaExpress`, this needs no public `klarnaClientId` and no
2798
+ * origin handshake — auth is the server-side API key.
2090
2799
  */
2091
- observeImpression(element: Element, context?: AnalyticsContext, opts?: {
2092
- name?: Extract<AnalyticsEventName, 'component_impression' | 'ad_impression'>;
2093
- /** Dedupe key override. Defaults to the strongest id available:
2094
- * campaignComponentId → locationId → componentTemplateId. */
2095
- key?: string;
2096
- /** Called the one time the impression is tracked (e.g. to fire a
2097
- * companion view_item_list). */
2098
- onImpression?: () => void;
2099
- }): () => void;
2100
- /** Force a flush (mostly for tests). */
2101
- flush(): Promise<void>;
2102
- private buildEvent;
2103
- /** Guarda la sesión solo si podemos escribir en el dispositivo. */
2104
- private persistSession;
2105
- private anonId;
2106
- /** Rolling session: renewed by activity, rotated after 30 min idle. */
2107
- private ensureSession;
2108
- private trackSessionEnd;
2109
- private flushWithBeacon;
2800
+ mountKlarnaPayments(container: HTMLElement, opts?: {
2801
+ withShipping?: boolean;
2802
+ shippingId?: string;
2803
+ category?: string;
2804
+ }): Promise<KlarnaPaymentsHandle>;
2805
+ /** True if the Klarna Payments widget lib can load (UI gate). */
2806
+ klarnaPaymentsAvailable(): Promise<boolean>;
2807
+ /** Cart snapshot + chosen shipping line/amount, for express purchases. */
2808
+ private buildKlarnaInstantContext;
2110
2809
  /**
2111
- * Auto-instrumentation over the SDK's own DOM events — the host app
2112
- * writes ZERO tracking code for the commerce funnel.
2810
+ * Express instant purchase — go straight to Klarna's own modal, no checkout
2811
+ * overlay. Creates a session (with shipping options), loads the widget into a
2812
+ * hidden container, then authorizes (which opens Klarna's confirm modal). On
2813
+ * approval creates the order → `payment-complete` (host shows confirmation);
2814
+ * on failure → `payment-error`. Call `open(sponsorId)` first.
2113
2815
  */
2114
- private installAutoListeners;
2115
- /** The lines of the cart (current, else the pre-clear snapshot), optionally one sponsor's. */
2116
- private cartLines;
2816
+ startKlarnaInstant(): Promise<void>;
2117
2817
  /**
2118
- * The cart split per campaign — the shared rule of cart/slices.ts over the
2119
- * current cart (else the pre-clear snapshot), plus whether any unit named
2120
- * its campaign itself (a cart without origins is reported as before).
2818
+ * REDIRECT path: call once on app load. If a Klarna purchase was launched
2819
+ * (pending context persisted) and we're back with a token — from the URL or
2820
+ * the SDK's resumed `complete` event — finish creating the order + confirm.
2121
2821
  */
2122
- private cartSlices;
2822
+ resumeKlarnaReturn(): Promise<void>;
2823
+ /** Snapshot of the active cart for redirect recovery (minor units). */
2824
+ private buildKlarnaPendingContext;
2123
2825
  /**
2124
- * The context of one of several per-campaign events: the slice's campaign,
2125
- * slot and content — only its own; when the slice spans several slots or
2126
- * articles the event names none rather than the one the click came from.
2826
+ * POST the token + order lines to vio-backend (it holds the secret API key
2827
+ * and creates the real Klarna order). On success → `payment-complete`; on
2828
+ * failure → `payment-error`. Idempotent: clears the pending key so the
2829
+ * popup and redirect paths can't double-fire.
2127
2830
  */
2128
- private sliceContext;
2831
+ private completeKlarnaOrder;
2832
+ get currentState(): CheckoutState | null;
2833
+ get items(): CartLineItem[];
2129
2834
  /**
2130
- * The context of a single-campaign checkout/purchase: when the cart's origins
2131
- * say which campaign they came from, the event says it too (plus the slot /
2132
- * content when unique) — a cart without origins is exactly as before.
2835
+ * Resolve the Stripe Connect account for the active sponsor — for now
2836
+ * pulled from bootstrap cache if present. Returns undefined if not set
2837
+ * (Stripe will route to the platform account in that case).
2133
2838
  */
2134
- private singleSliceContext;
2135
- /** Current cart → commerce payload; falls back to the pre-clear snapshot. */
2136
- private cartCommerce;
2137
- private findLine;
2138
- }
2139
- /**
2140
- * The `campaign_id` of an event. In order: the context's explicit id; the
2141
- * campaign assigned to the context's `slot` right now (ADR-0027 — only an
2142
- * open assignment for the init platform counts, see `findSlotAssignment`);
2143
- * the active campaign of `campaigns[]` the event's sponsor takes part in, as
2144
- * its primary or one of its secondaries — when it is in several, the
2145
- * surface's default campaign if it is one of them, else the first one the
2146
- * backend lists; the default campaign (`campaign.id`). `/v2/mobile/config`
2147
- * has no top-level `campaignId` — reading one is why every event used to
2148
- * leave with `campaign_id: 0` and the campaigns screen stayed empty.
2149
- *
2150
- * A malformed `campaigns[]` (not an array, a null entry) never breaks
2151
- * `track()`: it falls back to `campaign.id`.
2152
- */
2153
- declare function resolveCampaignId(ctx: Pick<AnalyticsContext, 'campaignId' | 'sponsorId' | 'slot'>, boot: Pick<BootstrapResponse, 'campaign' | 'campaigns'> | null | undefined): number | undefined;
2154
- /**
2155
- * `detail` of `vio:payment-success` as the checkout emits it. Four paths,
2156
- * three shapes: a redirect return (`orderId` = Vio's checkout id), the
2157
- * confirmation drawer and a provider's own receipt (`result` from the
2158
- * provider or the backend, plus Vio's `checkoutId`), and Apple Pay express
2159
- * from the cart (`result` with the backend's `confirmation`, no sponsor).
2160
- */
2161
- interface PaymentSuccessDetail {
2162
- method?: string;
2163
- sponsorId?: number | string;
2164
- /** The slot the purchase started from, when the emitter knows it. */
2165
- slot?: string;
2166
- /** The campaign the emitter attributed the purchase to (its `Vio.attribution`). */
2167
- campaignId?: number;
2168
- /** Per-element content override (`vio-content-id` / `vio-content-title`), when the emitter carries one. */
2169
- contentId?: string | number;
2170
- contentTitle?: string;
2171
- /** Redirect return: Vio's checkout id (the name predates `checkoutId`). */
2172
- orderId?: string | number;
2173
- /** Vio's checkout id — from the checkout state or the return URL. */
2174
- checkoutId?: string | number;
2175
- result?: PaymentSuccessResult | null;
2176
- }
2177
- /**
2178
- * What the checkout attaches as `result`. Only `confirmation` carries a Vio
2179
- * id: the order `ConfirmPaymentApplePay` created. `order.orderId` / `orderId`
2180
- * are the PROVIDER's references (Qliro's, Walley's — the checkout itself
2181
- * shows them as `providerRef`), and `chargedTotal` includes shipping on some
2182
- * methods only. Analytics reads none of those.
2183
- */
2184
- interface PaymentSuccessResult {
2185
- confirmation?: {
2186
- orderId?: string | number | null;
2187
- status?: string;
2188
- } | null;
2189
- [key: string]: unknown;
2839
+ private findStripeConnectAccount;
2840
+ /** The sponsor's connected account, read fresh from its channel config. */
2841
+ private resolveStripeConnectAccount;
2842
+ private emit;
2190
2843
  }
2191
- /**
2192
- * The `order_id` of a `purchase`: ALWAYS a Vio id, never a provider's
2193
- * reference. Normalized across every emitter: `orderId` (redirect return) →
2194
- * `result.confirmation.orderId` (Apple Pay) → `checkoutId`. `value` and
2195
- * `currency` are deliberately NOT read from the result: on every path they
2196
- * come from the cart snapshot (sum of the items, no shipping), so revenue
2197
- * stays comparable across payment methods — the charged total will arrive
2198
- * through the server-side `order_paid` event. With nothing to say it
2199
- * returns `{}`, so the cart snapshot keeps its keys.
2200
- */
2201
- declare function purchaseFromPaymentSuccess(d: PaymentSuccessDetail): Pick<AnalyticsCommerce, 'orderId'>;
2202
2844
 
2203
2845
  /**
2204
2846
  * Content (article) attribution — the other half of "where did this happen".
@@ -2217,11 +2859,32 @@ declare function purchaseFromPaymentSuccess(d: PaymentSuccessDetail): Pick<Analy
2217
2859
  interface ContentRef {
2218
2860
  id?: string;
2219
2861
  title?: string;
2862
+ /** The page's URL as origin + path (no query, no fragment), capped — what the order and the cart's origins carry as `content_url`. */
2863
+ url?: string;
2220
2864
  }
2221
2865
  interface ContentInit {
2222
2866
  contentId?: string | number | null;
2223
2867
  contentTitle?: string | null;
2224
2868
  }
2869
+ /** The collector (and Commerce's `order.content_url`) cap `content_url` at 2 048 chars. */
2870
+ declare const CONTENT_URL_MAX_LENGTH = 2048;
2871
+ /**
2872
+ * A page as the ORDER and the cart's origins name it (`content_url` to
2873
+ * Commerce): origin + path — no query string, no fragment — within the cap.
2874
+ * The query is where a page carries e-mails, tokens and tracking tails
2875
+ * (`?email=…&utm_…#frag`); none of that belongs on an order row. A site whose
2876
+ * article lives in the query or the hash identifies it through `contentId`
2877
+ * (`Vio.init({ contentId })`, `?vio_content=`), not through the URL. Also
2878
+ * the shape of the landing's referrer and page (client-context.ts).
2879
+ */
2880
+ declare function originAndPath(raw: unknown, max?: number): string | undefined;
2881
+ /**
2882
+ * A page URL within the cap for the analytics EVENTS — as is, else without
2883
+ * its query string (a long one is usually the tracking tail, not the page),
2884
+ * else cut. The collector keeps the query there (`page_views` strip it
2885
+ * themselves); the order does not (`originAndPath`).
2886
+ */
2887
+ declare function capContentUrl(value: unknown): string | undefined;
2225
2888
  /**
2226
2889
  * Id: `Vio.init({ contentId })` → `?vio_content=` → `<meta name="vio:content-id">`
2227
2890
  * → `<link rel="canonical">` href or `<meta property="og:url">` (without query
@@ -2235,95 +2898,7 @@ declare function resolveContent(init?: ContentInit | null, doc?: Document | null
2235
2898
  search?: string;
2236
2899
  } | null | undefined): ContentRef;
2237
2900
 
2238
- /**
2239
- * Slots — the pure half of ADR-0027 / ADR-0034 on the web.
2240
- *
2241
- * A slot is a NAME for a place on a page. The page declares its slots to the
2242
- * campaigns service (`Vio.declareSlots()` / `Vio.registerSlot()` in client.ts),
2243
- * the dashboard assigns a campaign to each one, optionally with a date window,
2244
- * and `GET /v2/mobile/config` answers with `campaigns[].slots[]` — only the
2245
- * assignments whose window is open NOW. Whatever no slot names shows the
2246
- * surface's default campaign (`campaign`).
2247
- *
2248
- * Everything here is side-effect free and never throws on a malformed
2249
- * bootstrap: a broken `campaigns[]` must never blank a product block or break
2250
- * `track()`.
2251
- */
2252
-
2253
- /** What `Vio.declareSlots()` accepts per slot. */
2254
- type SlotInput = string | {
2255
- id: string;
2256
- displayName?: string;
2257
- };
2258
- type BootLike = Pick<BootstrapResponse, 'campaign' | 'campaigns' | 'primarySponsor' | 'secondarySponsors'>;
2259
- /**
2260
- * The campaign a slot shows right now. Among the `status === 'active'`
2261
- * entries of `campaigns[]`, the one with an assignment named `slot` for this
2262
- * platform (`platform` null on the assignment, or equal to `platform`) whose
2263
- * window contains `now` (`startDate <= now < endDate`, null = open). When
2264
- * several qualify, the surface's default campaign wins, else the first the
2265
- * backend lists.
2266
- *
2267
- * No slot, or no assignment → the default campaign: the `campaigns[]` entry
2268
- * whose id is `campaign.id`, or a minimal entry built from `campaign` (+ the
2269
- * top-level sponsors) when the list does not carry it. No bootstrap → null.
2270
- */
2271
- declare function resolveSlotCampaign(boot: BootLike | null | undefined, slot: string | null | undefined, now?: number, platform?: string | null): BootstrapCampaignEntry | null;
2272
- /** The kinds of Vio element that register themselves. */
2273
- type SlotKind = 'card' | 'carousel' | 'detail';
2274
- /**
2275
- * The id an element gets when the host set no `vio-slot`:
2276
- * `${scope ? scope + '-' : ''}${kind}-${ordinal + 1}` (`carousel-1`, `card-3`,
2277
- * `article-123-carousel-1`), `ordinal` being the element's index among the
2278
- * same-kind Vio elements WITH THE SAME SCOPE, in document order at connect
2279
- * time. The scope is inherited from the DOM (`vio-scope` on the element, else
2280
- * the nearest `data-vio-scope` ancestor): a Vev page or a Replit article
2281
- * (`<body data-vio-scope="article-123">`) gets per-page slots with one line
2282
- * and no per-element naming; a template that wants slots shared across
2283
- * articles simply sets no scope. On purpose there is NO page path in the id:
2284
- * the article goes to analytics as `content_id`, not into the slot. Stable
2285
- * across reloads while the layout is; a layout change leaves a stale entry,
2286
- * which ADR-0034 accepts.
2287
- */
2288
- declare function autoSlotId(kind: SlotKind, ordinal: number, scope?: string | null): string;
2289
- /** `"Carousel 1"`, `"Card 3"` — with ` · ${scopeName}` when the scope has a human label. */
2290
- declare function autoSlotDisplayName(kind: SlotKind, ordinal: number, scopeName?: string | null): string;
2291
- /** A scope value fit for an id: trimmed, inner whitespace → `-`. */
2292
- declare function normalizeScope(scope: string | null | undefined): string;
2293
-
2294
- /**
2295
- * The cart split per campaign (ADR-0034) — ONE rule, shared by the SDK's own
2296
- * `begin_checkout` / `purchase` events, by `Vio.cartSlices()` and so by any
2297
- * host with its own analytics sink (Vev).
2298
- *
2299
- * Every unit of every line goes to the campaign of its origin — the one the
2300
- * place showed when it was added — and units without one to the campaign the
2301
- * caller's rule resolves for the line's sponsor (`resolveCampaign`). One slice
2302
- * per campaign: its items (quantities from the origins, merged per product +
2303
- * variant), its value with two decimals, and `slot` / `contentId` /
2304
- * `sponsorId` only when they are the same for the whole slice. A cart with
2305
- * one campaign is one slice. Pure; never throws on odd lines.
2306
- */
2307
-
2308
- /** An item of a slice — the analytics item shape (ids as given, normalized on the wire). */
2309
- type VioItem = AnalyticsItemInput;
2310
- /** One campaign's share of the cart. */
2311
- interface CartSlice {
2312
- campaignId?: number;
2313
- sponsorId?: number;
2314
- slot?: string;
2315
- contentId?: string;
2316
- items: VioItem[];
2317
- value: number;
2318
- currency?: string;
2319
- /** 1-based position of this slice and how many there are. */
2320
- slice: number;
2321
- slices: number;
2322
- }
2323
- /** The campaign of a unit without an explicit one: the caller's rule (slot assignment → sponsor → default). */
2324
- type ResolveCampaign = (slot: string | undefined, sponsorId: number) => number | undefined;
2325
- declare function cartSlicesFrom(lines: ReadonlyArray<CartLineItem>, resolveCampaign: ResolveCampaign, fallbackCurrency?: string): CartSlice[];
2326
-
2901
+ type PrivacyAnswer = SurfacePrivacyMode | 'unknown';
2327
2902
  declare class VioFacade {
2328
2903
  private apiInstance;
2329
2904
  private commerceClients;
@@ -2336,8 +2911,11 @@ declare class VioFacade {
2336
2911
  * (another key or environment) is still in flight after a re-init; its answer
2337
2912
  * belongs to that configuration and must not land in this one. */
2338
2913
  private generation;
2339
- /** Slot ids present on the page (`Vio.registerSlot`): how many elements hold each + its display name. */
2914
+ /** Slot ids present on the page (`Vio.registerSlot`): how many elements hold each, its display name, its own campaign and its kind. */
2340
2915
  private slotRegistry;
2916
+ /** Slots already warned about (`dashboard`: the dashboard's assignment stands; `replaced`: this page moved it). */
2917
+ private warnedDashboardSlots;
2918
+ private warnedReplacedSlots;
2341
2919
  /** Pending debounced declaration of the registry. */
2342
2920
  private slotDeclareTimer;
2343
2921
  /** A name appeared (or the key changed) since the registry was last declared. */
@@ -2350,6 +2928,10 @@ declare class VioFacade {
2350
2928
  private cartManager;
2351
2929
  private checkoutManager;
2352
2930
  private analyticsManager;
2931
+ /** What the surface answered of its privacy mode (`GET /v2/mobile/surface`) and when; `unknown` expires after a minute. */
2932
+ private surfaceMode;
2933
+ /** The request in flight for it, if any. */
2934
+ private surfaceRequest;
2353
2935
  init(config: VioConfig): void;
2354
2936
  /**
2355
2937
  * The content (article, page) this SDK instance is rendered in — what every
@@ -2365,7 +2947,7 @@ declare class VioFacade {
2365
2947
  get config(): ResolvedConfig;
2366
2948
  /** Multi-sponsor cart manager. Reactive — listen via addEventListener('change', ...). */
2367
2949
  get cart(): CartManager;
2368
- /** Checkout flow manager. Subscribes to cart state via the CartManager. */
2950
+ /** Checkout flow manager. Subscribes to cart state via the CartManager; asks here for the order's attribution. */
2369
2951
  get checkout(): CheckoutManager;
2370
2952
  /**
2371
2953
  * Analytics — track() queues even pre-init; nothing is sent (and no
@@ -2406,19 +2988,39 @@ declare class VioFacade {
2406
2988
  /**
2407
2989
  * Register a slot present on the page (the `<vio-*>` elements call it with
2408
2990
  * their effective id — the host's `vio-slot` or the auto-generated one —
2409
- * and the optional display name). The registry is declared ONCE, debounced,
2410
- * after the first successful bootstrap — and again whenever a new id or a
2411
- * new display name appears. A `displayName` given later for an id already
2412
- * registered replaces the one kept; `undefined` leaves it alone. The
2413
- * returned function unregisters; removal never re-declares.
2414
- */
2415
- registerSlot(name: string, displayName?: string): () => void;
2991
+ * the optional display name, and the element's own campaign when it has
2992
+ * one: `vio-campaign` or an ancestor's `data-vio-campaign`). The registry is
2993
+ * declared ONCE, debounced, after the first successful bootstrap — and again
2994
+ * whenever a new id, display name, campaign or kind appears. A `displayName` /
2995
+ * `campaignId` given later for an id already registered replaces the one
2996
+ * kept; `undefined` leaves it alone. The third argument is the campaign id
2997
+ * (as before) or `{ campaignId?, kind? }`, and a fourth `{ kind? }` may
2998
+ * follow a positional campaign — the elements call
2999
+ * `registerSlot(id, name, campaignId, { kind })` so a facade from an older
3000
+ * bundle, which reads only three arguments, still gets the campaign. `kind`
3001
+ * is what kind of element holds the slot (`card` | `carousel` | `detail`);
3002
+ * the FIRST kind an id gets stays (the cards a carousel renders share its
3003
+ * id: the slot is the carousel's). The returned function unregisters;
3004
+ * removal never re-declares.
3005
+ */
3006
+ registerSlot(name: string, displayName?: string, campaignIdOrOptions?: number | string | null | RegisterSlotOptions, options?: RegisterSlotOptions): () => void;
2416
3007
  /**
2417
3008
  * The campaign a slot shows now, from the last bootstrap: its assigned and
2418
3009
  * open campaign for the init platform, else the surface's default. With no
2419
3010
  * slot, the default. `null` before the bootstrap. See `resolveSlotCampaign`.
2420
3011
  */
2421
- campaignForSlot(slot?: string | null): BootstrapCampaignEntry | null;
3012
+ campaignForSlot(slot?: string | null, hint?: {
3013
+ campaignId?: CampaignHint;
3014
+ sponsorId?: number | string | null;
3015
+ }): BootstrapCampaignEntry | null;
3016
+ /** The page-campaign candidates in precedence order: the element's (own, ancestor), then `Vio.init`'s. */
3017
+ private pageCampaignCandidates;
3018
+ /**
3019
+ * The campaign the PAGE belongs to (`Vio.init({ campaignId })`, ADR-0034
3020
+ * amendment 3), as the last bootstrap lists it — only when it is there and
3021
+ * active; `null` otherwise (no page campaign, paused, unknown, no bootstrap).
3022
+ */
3023
+ pageCampaign(): BootstrapCampaignEntry | null;
2422
3024
  /**
2423
3025
  * THE attribution helper — the SDK elements, Vev and Replit all use this
2424
3026
  * one. For a place (`slot`): the campaign it shows right now
@@ -2429,12 +3031,69 @@ declare class VioFacade {
2429
3031
  *
2430
3032
  * `hint.sponsorId` — when the caller already knows the sponsor (a card with
2431
3033
  * `sponsor-id`) it is kept as `sponsorId`, and the campaign follows the same
2432
- * cascade analytics uses (slot assignment → the sponsor's active campaign →
2433
- * default), so what the cart remembers matches what the events say.
3034
+ * cascade analytics uses (slot assignment → page campaign → the sponsor's
3035
+ * active campaign → default), so what the cart remembers matches what the
3036
+ * events say — the page campaign applies there only when that sponsor takes
3037
+ * part in it. `hint.campaignId` — the element's own page campaign
3038
+ * candidates (`vio-campaign`, an ancestor's `data-vio-campaign`), ahead of
3039
+ * `Vio.init`'s; an unusable one falls through to the next; `0` = unset.
2434
3040
  */
2435
3041
  attribution(slot?: string | null, hint?: {
2436
3042
  sponsorId?: number | string;
3043
+ campaignId?: CampaignHint;
2437
3044
  }): Attribution;
3045
+ /**
3046
+ * What the surface answered and is still believed: `standard` / `minimal`
3047
+ * for the configuration; `unknown` for a minute after a timeout or a
3048
+ * failure (then it is asked again). `null` = nothing believed.
3049
+ */
3050
+ private believedSurfaceMode;
3051
+ /**
3052
+ * Ask the surface its privacy mode (`GET /v2/mobile/surface`), once —
3053
+ * started at `init()` and again by `bootstrap()`, never by the payment
3054
+ * path, which only reads what is known (`privacyModeNow`). Resolves what
3055
+ * was learnt within 1.5 s: the mode; `standard` for a service that predates
3056
+ * the endpoint (404) or a surface that names none; `unknown` for a word the
3057
+ * SDK does not know, a timeout or any other failure — believed for a
3058
+ * minute, then asked again. An answer that arrives after the cap still
3059
+ * lands for the next step. Never throws.
3060
+ */
3061
+ preloadPrivacyMode(): Promise<PrivacyAnswer>;
3062
+ /**
3063
+ * How much of the visit the order attribution may carry (ADR-0035): the
3064
+ * surface's privacy mode, as known RIGHT NOW, without waiting —
3065
+ * `Vio.init({ privacyMode: 'minimal' })` when the host says so, else what
3066
+ * the bootstrap says of the surface, else what the surface answered to the
3067
+ * ask `init()` started (`preloadPrivacyMode`), else the host's `standard`
3068
+ * once the surface could not tell. `unknown` while nothing is known: then
3069
+ * the page, the slot and the entry stay off what goes to Commerce, because
3070
+ * what can reveal which screen someone was on, and why, is only sent when
3071
+ * the surface is known to allow it. The payment path reads this one.
3072
+ */
3073
+ privacyModeNow(): PrivacyAnswer;
3074
+ /**
3075
+ * `privacyModeNow`, but waiting for the ask in flight when there is one
3076
+ * (at most its 1.5 s cap) — for the cart's lines, which are not the
3077
+ * payment path. Never throws.
3078
+ */
3079
+ privacyMode(): Promise<PrivacyAnswer>;
3080
+ /**
3081
+ * The attribution of the order a sponsor's cart is about to become
3082
+ * (ADR-0035 phase B) — what `CreateCheckout` / `UpdateCheckout` send as
3083
+ * `attribution` and shopcart writes on the order: the surface (its SDK
3084
+ * key), the page's campaign (`pageCampaign()`; without one, the campaign
3085
+ * that explains most units of the cart under the same rule `purchase` is
3086
+ * split by — `cartSlices`) and, on a surface KNOWN to be `standard`
3087
+ * (`privacyModeNow`), the page (`content()`'s url as origin + path, and
3088
+ * title) and where the session came in: the landing the session REMEMBERS
3089
+ * (`storedLanding`, else the one analytics resolved on this page) — never
3090
+ * the page the shopper pays on taken for a landing. Synchronous: nothing
3091
+ * on the way to a payment waits for it. snake_case, capped to Commerce's
3092
+ * limits. `undefined` when there is nothing to say; never throws.
3093
+ */
3094
+ orderAttribution(sponsorId?: number): CheckoutAttributionWire | undefined;
3095
+ /** The landing the session remembers: what the first page stored, else what analytics resolved on this page load (consent pending); null otherwise. */
3096
+ private rememberedLanding;
2438
3097
  /**
2439
3098
  * The cart split per campaign — the SAME rule `begin_checkout` / `purchase`
2440
3099
  * use, for hosts with their own analytics sink (Vev). Every unit of every
@@ -2448,11 +3107,40 @@ declare class VioFacade {
2448
3107
  cartSlices(sponsorId?: number, opts?: {
2449
3108
  items?: CartLineItem[];
2450
3109
  }): CartSlice[];
3110
+ /**
3111
+ * What the micro did with the page's campaign per slot (`assignment`):
3112
+ * `console.debug` when `Vio.init({ debug: true })`; a warning once per
3113
+ * slot when the dashboard's own assignment stands (only for a slot this
3114
+ * page actually sent a campaign for) and once per slot when this page moved
3115
+ * it from an earlier page assignment (`replaced`).
3116
+ */
3117
+ private reportAssignments;
3118
+ /**
3119
+ * The memory keys of the sent locations whose campaign the micro did not
3120
+ * take up: every location when a campaign was sent and no answer carries
3121
+ * `assignment` (an older micro), or the ones answered `none` for a campaign
3122
+ * the bootstrap lists as active. They are remembered with the 1 h TTL.
3123
+ */
3124
+ private campaignNotTakenUp;
2451
3125
  private scheduleSlotDeclaration;
2452
3126
  private findSponsor;
2453
3127
  }
2454
3128
  declare const Vio: VioFacade;
2455
3129
 
3130
+ /**
3131
+ * The buyer reference — shopcart's `buyer_ref`: the keyed hash Commerce
3132
+ * computes from the buyer's email, so one person is one ref across orders,
3133
+ * devices and platforms, and nothing in it can be turned back into an email
3134
+ * without Commerce's secret. The SDK forwards it as analytics `buyer_id`
3135
+ * (EVENTS_CONTRACT `commerce.buyer_id`, ≤ 128 chars in the collector's
3136
+ * schema) and never puts anything else in its place: an email, a name, an
3137
+ * over-long value are dropped — not hashed client-side, not cut (a cut hash
3138
+ * is another identity).
3139
+ */
3140
+ declare const BUYER_REF_MAX_LENGTH = 128;
3141
+ /** The reference when `value` is one; `undefined` for anything else (never an email). */
3142
+ declare function normalizeBuyerRef(value: unknown): string | undefined;
3143
+
2456
3144
  /**
2457
3145
  * SDK version reported in analytics events (`sdk_version`) and available
2458
3146
  * to consumers. Kept as a constant (not a package.json import) so the
@@ -2460,7 +3148,7 @@ declare const Vio: VioFacade;
2460
3148
  *
2461
3149
  * RELEASE CHECKLIST: bump together with package.json (see CONTRIBUTING).
2462
3150
  */
2463
- declare const SDK_VERSION = "0.23.1";
3151
+ declare const SDK_VERSION = "0.25.0";
2464
3152
 
2465
3153
  /**
2466
3154
  * Vipps MobilePay's own button, the way the design guidelines ask for it.
@@ -2489,4 +3177,4 @@ declare function vippsButtonAttributes(verb?: 'buy' | 'pay' | 'express' | 'conti
2489
3177
  language?: string;
2490
3178
  }): Record<string, string>;
2491
3179
 
2492
- export { ADD_ITEM_MUTATION, type AddManualOptions, type AddProductOptions, type AnalyticsCommerce, type AnalyticsContext, type AnalyticsEventName, type AnalyticsItemInput, AnalyticsManager, type AnalyticsStartOptions, type ApplePayConfig, type ApplePayResult, type Attribution, type BootstrapCampaign, type BootstrapCampaignEntry, type BootstrapCampaignStatus, type BootstrapResponse, type BootstrapSlot, CREATE_CART_MUTATION, CREATE_CHECKOUT_MUTATION, CREATE_PAYMENT_STRIPE_MUTATION, CREATE_PAYMENT_VIPPS_MUTATION, type CartChangeDetail, type CartLineItem, type CartLineOrigin, CartManager, type CartOrigin, type CartQueryOptions, type CartSlice, type CheckoutAddress, type CheckoutChangeDetail, CheckoutManager, type CheckoutState, CommerceClient, Configuration, type ContentRef, type CreatePaymentVippsResponse, type CreatePaymentVippsVariables, DELETE_ITEM_MUTATION, type Environment, GET_AVAILABLE_PAYMENT_METHODS_QUERY, GET_CART_QUERY, GET_CHECKOUT_QUERY, GET_LINE_ITEMS_BY_SUPPLIER_QUERY, GET_VIPPS_STATUS_QUERY, type GetVippsStatusVariables, type ImageSize, type ManifestLocation, type ManifestRequest, type ManifestResult, type PaymentCompleteDetail, type PaymentMethod, type PaymentSelectDetail, type PaymentSuccessDetail, type PaymentSuccessResult, type PlacementComponent, type Product, type ProductCategory, type ProductImage, type ProductOption, type ProductPrice, type ProductVariant, type ResolvedConfig, SDK_VERSION, type SlotInput, type SlotKind, type Sponsor, type SponsorCartState, type SponsorCommerceBlock, type TrackOptions, UPDATE_CHECKOUT_MUTATION, UPDATE_ITEM_MUTATION, UPDATE_SHIPPINGS_BY_SUPPLIER_MUTATION, VIPPS_BUTTON_SCRIPT, VIPPS_BUTTON_TAG, Vio, VioApi, VioApiError, type VioConfig, type VioItem, type VioPlatform, type VippsPaymentState, type VippsStatusResult, addItem, autoSlotDisplayName, autoSlotId, cartSlicesFrom, checkApplePayAvailability, createCart, createCheckout, createCommerceClient, createPaymentStripe, createPaymentVipps, createVioApi, deleteItem, displayPrice, ensureVippsButton, executeCartGraphQL, formatPrice, getAvailablePaymentMethods, getCart, getCartGraphQLOptions, getCheckout, getCustomerSessionId, getGlobalCurrency, getLineItemsBySupplier, getVippsStatus, lineOrigins, normalizeOrigin, normalizeScope, primaryImageUrl, purchaseFromPaymentSuccess, resolveCampaignId, resolveContent, resolveSlotCampaign, sameOrigin, showApplePaySheet, updateCheckout, updateItem, updateShippingsBySupplier, vippsButtonAttributes };
3180
+ export { ADD_ITEM_MUTATION, type AddManualOptions, type AddProductOptions, type AnalyticsCommerce, type AnalyticsContext, type AnalyticsEventName, type AnalyticsItemInput, AnalyticsManager, type AnalyticsStartOptions, type ApplePayConfig, type ApplePayResult, type Attribution, BUYER_REF_MAX_LENGTH, type BootstrapCampaign, type BootstrapCampaignEntry, type BootstrapCampaignStatus, type BootstrapResponse, type BootstrapSlot, CHECKOUT_ATTRIBUTION_CAPS, CLIENT_LANDING_URL_MAX_LENGTH, CONTENT_URL_MAX_LENGTH, CREATE_CART_MUTATION, CREATE_CHECKOUT_MUTATION, CREATE_CHECKOUT_WITH_ATTRIBUTION_MUTATION, CREATE_PAYMENT_STRIPE_MUTATION, CREATE_PAYMENT_VIPPS_MUTATION, type CampaignHint, type CartChangeDetail, type CartLineItem, type CartLineOrigin, CartManager, type CartOrigin, type CartQueryOptions, type CartSlice, type CheckoutAddress, type CheckoutAttributionInput, type CheckoutAttributionWire, type CheckoutChangeDetail, CheckoutManager, type CheckoutManagerDeps, type CheckoutReference, type CheckoutState, type ClientContext, CommerceClient, Configuration, type ContentRef, type CreatePaymentVippsResponse, type CreatePaymentVippsVariables, DELETE_ITEM_MUTATION, type EntryContextWire, type Environment, GET_AVAILABLE_PAYMENT_METHODS_QUERY, GET_CART_QUERY, GET_CHECKOUT_QUERY, GET_LINE_ITEMS_BY_SUPPLIER_QUERY, GET_VIPPS_STATUS_QUERY, GRAPHQL_INT_MAX, type GatewayFeature, type GetVippsStatusVariables, type ImageSize, LINE_ORIGIN_CAPS, type Landing, type LineOriginWire, type LineOriginWireOptions, type ManifestLocation, type ManifestRequest, type ManifestResult, type OriginPage, type PaymentCompleteDetail, type PaymentMethod, type PaymentSelectDetail, type PaymentSuccessDetail, type PaymentSuccessResult, type PlacementComponent, type Product, type ProductCategory, type ProductImage, type ProductOption, type ProductPrice, type ProductVariant, type RegisterSlotOptions, type ResolvedConfig, SDK_VERSION, type SlotInput, type SlotKind, type Sponsor, type SponsorCartState, type SponsorCommerceBlock, type SurfacePrivacyMode, type SurfaceResponse, type TrackOptions, UPDATE_CHECKOUT_MUTATION, UPDATE_CHECKOUT_WITH_ATTRIBUTION_MUTATION, UPDATE_ITEM_MUTATION, UPDATE_ITEM_WITH_ORIGIN_MUTATION, UPDATE_SHIPPINGS_BY_SUPPLIER_MUTATION, VIPPS_BUTTON_SCRIPT, VIPPS_BUTTON_TAG, Vio, VioApi, VioApiError, type VioConfig, type VioItem, type VioPlatform, type VippsPaymentState, type VippsStatusResult, activeCampaignEntry, addItem, autoSlotDisplayName, autoSlotId, buyerRefOf, campaignCandidates, capContentUrl, cartSlicesFrom, checkApplePayAvailability, checkoutAttributionOf, componentKindOf, createCart, createCheckout, createCommerceClient, createPaymentStripe, createPaymentVipps, createVioApi, deleteItem, displayPrice, dominantCampaignOf, ensureVippsButton, entryContextOf, executeCartGraphQL, formatPrice, gatewayHas, getAvailablePaymentMethods, getCart, getCartGraphQLOptions, getCheckout, getCheckoutReference, getCustomerSessionId, getGlobalCurrency, getLineItemsBySupplier, getVippsStatus, isUnknownFeatureError, isUnknownTokenError, landingUrl, lineOriginWire, lineOrigins, normalizeBuyerRef, normalizeOrigin, normalizeScope, normalizeSlotKind, originAndPath, primaryImageUrl, purchaseFromPaymentSuccess, resetGatewayFeatures, resolveCampaignId, resolveClientContext, resolveContent, resolveLanding, resolveSlotCampaign, sameOrigin, showApplePaySheet, sponsorCampaignEntry, storedLanding, toCampaignId, updateCheckout, updateItem, updateShippingsBySupplier, vippsButtonAttributes, withGatewayFeature };