@vio-live/web-sdk 0.35.0 → 0.37.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.
- package/CHANGELOG.md +39 -0
- package/README.md +99 -0
- package/dist/chunk-6HBX7GBJ.js +3 -0
- package/dist/{chunk-3YFJFDSN.js.map → chunk-6HBX7GBJ.js.map} +1 -1
- package/dist/{chunk-QA5R4VYF.js → chunk-KVI56NGO.js} +156 -13
- package/dist/chunk-KVI56NGO.js.map +1 -0
- package/dist/{chunk-F7LE5AZY.js → chunk-LDA7RI43.js} +371 -98
- package/dist/chunk-LDA7RI43.js.map +1 -0
- package/dist/core/index.d.ts +122 -5
- package/dist/core/index.js +2 -2
- package/dist/{detail-layout-BI556w8p.d.ts → detail-layout-BfR20W_X.d.ts} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/react/index.d.ts +7 -3
- package/dist/react/index.js +11 -7
- package/dist/react/index.js.map +1 -1
- package/dist/{tokens-C-LsqKQH.d.ts → tokens-ChbmD8wb.d.ts} +50 -3
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-3YFJFDSN.js +0 -3
- package/dist/chunk-F7LE5AZY.js.map +0 -1
- package/dist/chunk-QA5R4VYF.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -14,6 +14,45 @@ How to keep this file: see [CONTRIBUTING → Changelog](CONTRIBUTING.md#changelo
|
|
|
14
14
|
The details of each feature live in the [README](README.md); this file says *what*
|
|
15
15
|
and *when*, and links there.
|
|
16
16
|
|
|
17
|
+
## 0.37.0 — 2026-10-29
|
|
18
|
+
|
|
19
|
+
> **Deploy the collector `89f2766` (vio-analytics#38) before using this version:** an older collector rejects
|
|
20
|
+
> `cta_click` (the rest of the batch is kept, those clicks are lost).
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- **Button tracking: `cta_click`** — which buttons shoppers use. Every tap on a button of
|
|
24
|
+
`<vio-product-detail>`, `<vio-cart>`, `<vio-product>` and `<vio-checkout>` sends one `cta_click`
|
|
25
|
+
(in `context`: `cta`, `cta_location`, `cta_label`, `option_value`, `product_id`,
|
|
26
|
+
`product_variant_id`, the detail's layout, and the usual attribution), on the tap, before the
|
|
27
|
+
action. Each tap also dispatches **`vio:cta-click`** (bubbles, composed; React `onCtaClick`).
|
|
28
|
+
**`Vio.trackCta({ cta, location, label, variant, … })`** sends the same event for a host's own
|
|
29
|
+
buttons (`location: 'host' | 'card' | 'block'`, `cta_variant` for the button option being
|
|
30
|
+
tested). Ids and fields: [README → Button tracking](README.md#button-tracking-cta_click-unreleased).
|
|
31
|
+
|
|
32
|
+
### ⚠️ Upgrade notes
|
|
33
|
+
- **The collector must know `cta_click`** (and its context fields) before this ships: an older
|
|
34
|
+
collector rejects the event — the rest of the batch is not affected.
|
|
35
|
+
- On `cta_click`, **`variant_id` is the layout's experiment variant** (as on `view_item`); the
|
|
36
|
+
product variant is **`product_variant_id`**.
|
|
37
|
+
- Hosts with `autoTrack: false` (Vev) get no `cta_click` from the SDK's buttons unless they forward
|
|
38
|
+
`vio:cta-click` themselves (`Vio.trackCta(e.detail)`).
|
|
39
|
+
- Nothing is sent before `Vio.analytics.start()`, `Vio.trackCta()` included.
|
|
40
|
+
|
|
41
|
+
## 0.36.0 — 2026-10-29
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
- **The cart says where shipping is chosen.** Under «Frakt» / «Totalt» a note: «Frakt velger du i Vipps eller i
|
|
45
|
+
neste steg.» (`part="cart-shipping-hint"`). While no rate is chosen and the brand offers several, the shipping and
|
|
46
|
+
the total read «fra …» (the cheapest).
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
- **The heading of the description fold is configurable**: `Vio.configureDetail({ descriptionLabel: 'Produktbeskrivelse' })`
|
|
50
|
+
for the page, or `description-label` on `<vio-product-detail>` (wins). Default «Beskrivelse». Feedback from Aller
|
|
51
|
+
(29/10): a folded «Produktbeskrivelse» right under the price — with the section order
|
|
52
|
+
`[..., 'price', 'description', 'options', 'purchase', ...]` and `detailDescriptionMode: 'folded'`.
|
|
53
|
+
- **The brand's promises in the cart** too, under the ways to pay (same strip as the product detail, from the
|
|
54
|
+
sponsor block's `highlights`). Hide them with `applyVioTheme({ cartHighlightsDisplay: 'none' })`.
|
|
55
|
+
|
|
17
56
|
## 0.35.0 — 2026-10-29
|
|
18
57
|
|
|
19
58
|
> 0.34.0 was never published on its own: its changes (section order of the product detail and layout tracking,
|
package/README.md
CHANGED
|
@@ -577,6 +577,103 @@ To **undo** it, open any page with **`?vio_internal=0`**. Things to know:
|
|
|
577
577
|
(`Vio.analytics.isInternal` reads it). `resolveInternal()` / `INTERNAL_KEY` are
|
|
578
578
|
exported from `/core`.
|
|
579
579
|
|
|
580
|
+
### Button tracking (`cta_click`) (unreleased)
|
|
581
|
+
|
|
582
|
+
Which buttons shoppers use. Every tap on a button of the SDK's elements sends **one
|
|
583
|
+
`cta_click`**, through the same pipeline as every other event (consent,
|
|
584
|
+
`privateContent`, internal traffic, batching, attribution). A host's own buttons
|
|
585
|
+
send the same event with **`Vio.trackCta()`**, so the dashboard compares them on
|
|
586
|
+
one scale.
|
|
587
|
+
|
|
588
|
+
**When.** On the tap, before the button's own action runs (before any navigation
|
|
589
|
+
to Vipps, Stripe…) — it never blocks or delays the action, and one tap is one
|
|
590
|
+
event. Only once `Vio.analytics.start()` ran (with `autoTrack`, the default);
|
|
591
|
+
before that nothing is queued. A host with `autoTrack: false` hears the DOM event
|
|
592
|
+
(below) and decides itself.
|
|
593
|
+
|
|
594
|
+
**The wire** — everything in `context`, next to `campaign_id` / `location_id` /
|
|
595
|
+
`content_*` / `sponsor_id` as every event carries them:
|
|
596
|
+
|
|
597
|
+
| field | what |
|
|
598
|
+
|---|---|
|
|
599
|
+
| `cta` | the button id, `[a-z0-9_.:-]`, 1–64 chars (lists below) |
|
|
600
|
+
| `cta_location` | `detail` · `cart` · `card` · `checkout` · `host` · `block` |
|
|
601
|
+
| `cta_label` | the visible text of the button, trimmed, ≤ 64 (`Kjøp nå med Vipps`, `Til kassen`) |
|
|
602
|
+
| `cta_variant` | the host's name of the button option it is testing, `[A-Za-z0-9._:-]`, ≤ 64 (`bar-kjop`, `outline-velg`). The SDK's own buttons send none |
|
|
603
|
+
| `option_value` | the option value chosen, ≤ 64 (`size`: `M`, `42`) |
|
|
604
|
+
| `product_id` | the product (string) |
|
|
605
|
+
| `product_variant_id` | the **product** variant, when known (every option chosen, or a single variant) |
|
|
606
|
+
| `layout_id` · `layout_revision` · `experiment_id` · `variant_id` | the `<vio-product-detail>` layout shown — only a non-default one, as on `view_item`. **`variant_id` is the layout's experiment variant**, never the product's: that one is `product_variant_id` |
|
|
607
|
+
| `component_template_id` | `product-detail` / `product-card` (or the carousel's) for the SDK's elements |
|
|
608
|
+
|
|
609
|
+
No PII: ids, the button's own text and the option value. With
|
|
610
|
+
`start({ privateContent: true })` `cta_label` and `option_value` stay on the device
|
|
611
|
+
too (they can name the product), with `content_url` / `content_title` /
|
|
612
|
+
`content_id`; `cta`, `cta_location`, `cta_variant` and the ids still go. Without
|
|
613
|
+
consent (`requireConsent`) the event goes with the visit's ephemeral ids, as every
|
|
614
|
+
event. A browser marked as internal sends `client.internal: true`.
|
|
615
|
+
|
|
616
|
+
**The SDK's buttons.**
|
|
617
|
+
|
|
618
|
+
| element (`cta_location`) | `cta` ids |
|
|
619
|
+
|---|---|
|
|
620
|
+
| `<vio-product-detail>` (`detail`) | `vipps` (Kjøp nå med Vipps) · `apple_pay` · `stripe` · `klarna` · `buy_now` (Kjøp nå) · `add_to_cart` (Legg i handlekurv) · `size` (any option value chosen, with `option_value`) · `quantity_plus` · `quantity_minus` · `description_open` («Beskrivelse» / the text / «Les mer», when the tap opens it) · `shipping_returns_open` («Frakt & retur», when it opens) · `terms_link` (Kjøpsvilkår) · `refund_link` (Angrerett og retur) · `checkout` («Til kassen» in the added-to-cart toast) · `close` (×, the backdrop, the handle) · `gallery_swipe` (the first change of photo per open product: a swipe, an arrow or a thumbnail) |
|
|
621
|
+
| `<vio-cart>` (`cart`) | `checkout` (Til kassen) · `vipps` · `apple_pay` · `stripe` · `klarna` · `remove` · `quantity_plus` · `quantity_minus` · `close` |
|
|
622
|
+
| `<vio-product>` card (`card`) | `open` (a tap — or Enter — on the card or its image) · `add` (the bag or bar button) |
|
|
623
|
+
| `<vio-checkout>` (`checkout`) | `select_<method>` (a method of the list: `select_vipps`, `select_stripe`, `select_klarna`, `select_apple_pay`, `select_kustom`, `select_qliro`, `select_walley`, `select_nexi`, `select_adyen`) · `pay_<method>` (the pay button of the chosen method: `pay_vipps`, `pay_stripe`, `pay_klarna`, `pay_apple_pay`, `pay_adyen`, `pay_kustom`…) · `pay_stripe_confirm` («Betal» under Stripe's own payment form) · `close` (×, the backdrop, the handle, «Lukk» / «Fortsett å handle» on the receipt) |
|
|
624
|
+
|
|
625
|
+
A detail's buttons carry the open product (`product_id`, `product_variant_id`), its
|
|
626
|
+
sponsor, slot, campaign and article; a cart line's carry its product, variant,
|
|
627
|
+
sponsor and where its units came from; the cart's and the checkout's footer
|
|
628
|
+
buttons carry the sponsor they pay.
|
|
629
|
+
|
|
630
|
+
**The DOM event.** Each SDK button tap also dispatches **`vio:cta-click`**
|
|
631
|
+
(`bubbles`, `composed`) from the element, so a host can mirror it to its own
|
|
632
|
+
analytics. `detail` is the `Vio.trackCta` shape: `{ cta, location, label?,
|
|
633
|
+
optionValue?, productId?, productVariantId?, sponsorId?, campaignId?, slot?,
|
|
634
|
+
contentId?, contentTitle?, componentTemplateId?, layout? }`. React: `onCtaClick` on
|
|
635
|
+
`VioProduct`, `VioProductDetail`, `VioCart` and `VioCheckout`.
|
|
636
|
+
|
|
637
|
+
```js
|
|
638
|
+
window.addEventListener('vio:cta-click', (e) => myAnalytics.track('button', e.detail))
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
**A host's own buttons** (Replit's cards and article blocks):
|
|
642
|
+
|
|
643
|
+
```js
|
|
644
|
+
Vio.trackCta({
|
|
645
|
+
cta: 'choose_size', // required: [a-z0-9_.:-], ≤ 64 — invalid → ignored, one console.warn
|
|
646
|
+
location: 'block', // 'host' (default) | 'card' | 'block' | … — unknown → 'host', warned
|
|
647
|
+
label: 'Velg størrelse', // the button's visible text
|
|
648
|
+
variant: 'outline-velg', // the button option you are testing — invalid → left out, warned
|
|
649
|
+
optionValue: undefined, // the value chosen, for `size`
|
|
650
|
+
productId: 408948,
|
|
651
|
+
productVariantId: undefined,
|
|
652
|
+
sponsorId: 4,
|
|
653
|
+
campaignId: 31, // else resolved from slot / sponsor, as every event
|
|
654
|
+
slot: 'article-12-block-1',
|
|
655
|
+
contentId: 'art-12',
|
|
656
|
+
layout: undefined, // { layoutId, layoutRevision, experimentId, variantId } when it is a detail layout
|
|
657
|
+
})
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
It sends nothing before `Vio.analytics.start()` and never throws. It does not
|
|
661
|
+
dispatch `vio:cta-click` (the host already knows its own tap). Ids to use in the
|
|
662
|
+
blocks — the same as the SDK's where the button does the same thing:
|
|
663
|
+
|
|
664
|
+
| block button | `cta` |
|
|
665
|
+
|---|---|
|
|
666
|
+
| a size chosen | `size` (with `optionValue`) |
|
|
667
|
+
| add to the cart | `add_to_cart` |
|
|
668
|
+
| «Velg størrelse» — opens the detail to choose | `choose_size` |
|
|
669
|
+
| «Produktbeskrivelse» / «Vis mer» | `description_open` |
|
|
670
|
+
| Vipps directly | `vipps` |
|
|
671
|
+
| the image or the title (opens the detail) | `open` |
|
|
672
|
+
|
|
673
|
+
Name the button option you are testing with `variant` (`bar-kjop` vs
|
|
674
|
+
`outline-velg`) and keep `cta` the same for buttons that do the same thing: the
|
|
675
|
+
dashboard groups by `cta` and splits by `cta_variant` / `cta_label`.
|
|
676
|
+
|
|
580
677
|
## Sponsor identity — name and logo
|
|
581
678
|
|
|
582
679
|
The elements say **who sells**: the sponsor's (brand's) display name and logo.
|
|
@@ -760,11 +857,13 @@ whole page through `applyVioTheme` (theme key → custom property). The element
|
|
|
760
857
|
|---|---|---|---|
|
|
761
858
|
| `gallery` | `detailGallery` | `thumbs` (default) · `carousel` | `carousel`: every photo in one swipeable row with a dot per photo, no thumbnails — less height. `detailCarouselPeek` (`--vio-detail-carousel-peek`) shows the edge of the next one |
|
|
762
859
|
| `description-mode` | `detailDescriptionMode` | `preview` (default) · `folded` · `open` | «Beskrivelse»: the first lines fading out + «Les mer» (`detailDescriptionPreviewLines`, `3`); only the heading until a tap; or all of it |
|
|
860
|
+
| `description-label` | — (`Vio.configureDetail({ descriptionLabel })`) | text, default `Beskrivelse` | Heading of the description fold, e.g. `Produktbeskrivelse` |
|
|
763
861
|
| `highlights` | — | `[{ icon, title, text }]` (JSON) | The brand's promises under the buy zone. By default the brand's own (dashboard Settings → Brand, sponsor block `highlights`); this list replaces them on the page. Icons: `plane heart shirt truck return leaf star shield mailbox home pin clock`, or an image URL. `detailHighlightsDisplay: 'none'` hides the strip |
|
|
764
862
|
| `delivery-time` | — | text, e.g. `2-5 virkedager` | «Leveringstid …» in «Frakt & retur» for a brand whose rates do not say it (each rate's own text in Commerce — «Leveringstid 1-5 dager» — wins) |
|
|
765
863
|
| `carrier-logos` | — | `{ "Bring": "https://…" }` (JSON) | Carrier logos by the name the rate starts with («Bring - Pakke i postkasse»), for rates without their own logo in Commerce (`logo_url`, which wins); otherwise a line icon by the kind of delivery |
|
|
766
864
|
| `vipps-cart-payment` | `vippsCartPayment` | `express` (default) · `checkout` | «Kjøp nå med Vipps» when the brand's cart already has lines: the product is added and the **whole cart** goes to Vipps Express, the line under the button saying «Betaler hele handlekurven · n varer · total»; or (`checkout`) the checkout opens first, Vipps preselected. Also on `<vio-cart>` (its Vipps button) |
|
|
767
865
|
| — | `detailShippingReturnsDisplay` | `block` (default) · `none` | «Frakt & retur»: one row per carrier (logo or icon, carrier, how it delivers, price), the delivery time, the right of withdrawal and the brand's pages |
|
|
866
|
+
| — | `cartHighlightsDisplay` | `grid` (default) · `none` | The brand's promises in the cart, under the ways to pay |
|
|
768
867
|
|
|
769
868
|
The sheet closes with a pull down from its top bar, or from anywhere while its content is at the top.
|
|
770
869
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-6HBX7GBJ.js"}
|
|
@@ -1181,6 +1181,20 @@ function setGlobalDetailLayout(layout) {
|
|
|
1181
1181
|
}
|
|
1182
1182
|
}
|
|
1183
1183
|
}
|
|
1184
|
+
function currentGlobalDescriptionLabel() {
|
|
1185
|
+
return store().descriptionLabel ?? null;
|
|
1186
|
+
}
|
|
1187
|
+
function setGlobalDescriptionLabel(label) {
|
|
1188
|
+
const s = store();
|
|
1189
|
+
const text3 = typeof label === "string" ? label.trim() : "";
|
|
1190
|
+
s.descriptionLabel = text3 && text3.length <= 40 ? text3 : null;
|
|
1191
|
+
for (const listener of [...s.listeners]) {
|
|
1192
|
+
try {
|
|
1193
|
+
listener();
|
|
1194
|
+
} catch {
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1184
1198
|
function onGlobalDetailLayoutChange(listener) {
|
|
1185
1199
|
const s = store();
|
|
1186
1200
|
s.listeners.add(listener);
|
|
@@ -3955,7 +3969,7 @@ async function prepareApplePay(config) {
|
|
|
3955
3969
|
}
|
|
3956
3970
|
|
|
3957
3971
|
// src/core/version.ts
|
|
3958
|
-
var SDK_VERSION = "0.
|
|
3972
|
+
var SDK_VERSION = "0.37.0";
|
|
3959
3973
|
|
|
3960
3974
|
// src/core/checkout/payments/stripe-embedded.ts
|
|
3961
3975
|
var CREATE_PAYMENT_INTENT_STRIPE_MUTATION = `
|
|
@@ -7894,6 +7908,91 @@ function localStorageOrNull() {
|
|
|
7894
7908
|
}
|
|
7895
7909
|
}
|
|
7896
7910
|
|
|
7911
|
+
// src/core/analytics/cta.ts
|
|
7912
|
+
var CTA_LOCATIONS = ["detail", "cart", "card", "checkout", "host", "block"];
|
|
7913
|
+
var CTA_ID_PATTERN = /^[a-z0-9_.:-]{1,64}$/;
|
|
7914
|
+
var CTA_VARIANT_PATTERN = /^[A-Za-z0-9._:-]{1,64}$/;
|
|
7915
|
+
var CTA_TEXT_MAX_LENGTH = 64;
|
|
7916
|
+
var ID_MAX_LENGTH = 128;
|
|
7917
|
+
function isCtaId(value) {
|
|
7918
|
+
return typeof value === "string" && CTA_ID_PATTERN.test(value);
|
|
7919
|
+
}
|
|
7920
|
+
function ctaText(value, max = CTA_TEXT_MAX_LENGTH) {
|
|
7921
|
+
if (typeof value !== "string" && typeof value !== "number") return void 0;
|
|
7922
|
+
const clean = String(value).replace(/[\u0000-\u001f\u007f-\u009f]/g, " ").replace(/\s+/g, " ").trim();
|
|
7923
|
+
if (!clean) return void 0;
|
|
7924
|
+
if (clean.length <= max) return clean;
|
|
7925
|
+
let cut4 = clean.slice(0, max);
|
|
7926
|
+
const last = cut4.charCodeAt(cut4.length - 1);
|
|
7927
|
+
if (last >= 55296 && last <= 56319) cut4 = cut4.slice(0, -1);
|
|
7928
|
+
return cut4.trimEnd() || void 0;
|
|
7929
|
+
}
|
|
7930
|
+
function idOf(value) {
|
|
7931
|
+
if (typeof value === "number") return Number.isFinite(value) ? String(value) : void 0;
|
|
7932
|
+
if (typeof value !== "string") return void 0;
|
|
7933
|
+
const v = value.trim();
|
|
7934
|
+
return v && v.length <= ID_MAX_LENGTH ? v : void 0;
|
|
7935
|
+
}
|
|
7936
|
+
function positive(value) {
|
|
7937
|
+
const n = toNumber(value);
|
|
7938
|
+
return n !== void 0 && Number.isInteger(n) && n > 0 ? n : void 0;
|
|
7939
|
+
}
|
|
7940
|
+
function warn(message) {
|
|
7941
|
+
try {
|
|
7942
|
+
console.warn(`[Vio.trackCta] ${message}`);
|
|
7943
|
+
} catch {
|
|
7944
|
+
}
|
|
7945
|
+
}
|
|
7946
|
+
function ctaContextOf(input) {
|
|
7947
|
+
const cta = input?.cta;
|
|
7948
|
+
if (!isCtaId(cta)) {
|
|
7949
|
+
warn(`ignored: cta must be 1\u201364 chars of [a-z0-9_.:-], got ${JSON.stringify(cta)}`);
|
|
7950
|
+
return null;
|
|
7951
|
+
}
|
|
7952
|
+
let location2 = "host";
|
|
7953
|
+
if (input.location !== void 0 && input.location !== null && input.location !== "") {
|
|
7954
|
+
if (CTA_LOCATIONS.includes(String(input.location))) {
|
|
7955
|
+
location2 = input.location;
|
|
7956
|
+
} else {
|
|
7957
|
+
warn(`unknown location ${JSON.stringify(input.location)} \u2014 sent as 'host' (${CTA_LOCATIONS.join(" | ")})`);
|
|
7958
|
+
}
|
|
7959
|
+
}
|
|
7960
|
+
let variant;
|
|
7961
|
+
if (input.variant !== void 0 && input.variant !== null && input.variant !== "") {
|
|
7962
|
+
if (typeof input.variant === "string" && CTA_VARIANT_PATTERN.test(input.variant)) variant = input.variant;
|
|
7963
|
+
else warn(`variant left out: 1\u201364 chars of [A-Za-z0-9._:-], got ${JSON.stringify(input.variant)}`);
|
|
7964
|
+
}
|
|
7965
|
+
const i = input;
|
|
7966
|
+
const layout = normalizeLayoutOrigin(i.layout);
|
|
7967
|
+
const contentId = typeof i.contentId === "number" ? Number.isFinite(i.contentId) ? i.contentId : void 0 : idOf(i.contentId);
|
|
7968
|
+
const slot = typeof i.slot === "string" && i.slot.trim() ? i.slot.trim() : void 0;
|
|
7969
|
+
const ctx = {
|
|
7970
|
+
cta,
|
|
7971
|
+
ctaLocation: location2,
|
|
7972
|
+
ctaLabel: ctaText(i.label),
|
|
7973
|
+
ctaVariant: variant,
|
|
7974
|
+
optionValue: ctaText(i.optionValue),
|
|
7975
|
+
productId: idOf(i.productId),
|
|
7976
|
+
productVariantId: idOf(i.productVariantId),
|
|
7977
|
+
sponsorId: positive(i.sponsorId),
|
|
7978
|
+
campaignId: positive(i.campaignId),
|
|
7979
|
+
slot,
|
|
7980
|
+
contentId,
|
|
7981
|
+
contentTitle: typeof i.contentTitle === "string" && i.contentTitle.trim() ? i.contentTitle.trim() : void 0,
|
|
7982
|
+
componentTemplateId: idOf(i.componentTemplateId),
|
|
7983
|
+
...layout.layoutId ? {
|
|
7984
|
+
layoutId: layout.layoutId,
|
|
7985
|
+
layoutRevision: layout.layoutRevision ?? "",
|
|
7986
|
+
experimentId: layout.experimentId,
|
|
7987
|
+
variantId: layout.variantId
|
|
7988
|
+
} : {}
|
|
7989
|
+
};
|
|
7990
|
+
for (const key of Object.keys(ctx)) {
|
|
7991
|
+
if (ctx[key] === void 0) delete ctx[key];
|
|
7992
|
+
}
|
|
7993
|
+
return ctx;
|
|
7994
|
+
}
|
|
7995
|
+
|
|
7897
7996
|
// src/core/cart/slices.ts
|
|
7898
7997
|
function cartSlicesFrom(lines, resolveCampaign, fallbackCurrency) {
|
|
7899
7998
|
if (!Array.isArray(lines) || lines.length === 0) return [];
|
|
@@ -8208,6 +8307,20 @@ var AnalyticsManager = class extends EventTarget {
|
|
|
8208
8307
|
if (this.queue.length > MAX_QUEUE) this.queue.splice(0, this.queue.length - MAX_QUEUE);
|
|
8209
8308
|
if (this.queue.length >= FLUSH_AT_COUNT) void this.flush();
|
|
8210
8309
|
}
|
|
8310
|
+
/**
|
|
8311
|
+
* One `cta_click` — a tap on a button (README «Button tracking»). What
|
|
8312
|
+
* `Vio.trackCta()` calls for a host's own buttons; the SDK's elements reach
|
|
8313
|
+
* it through `vio:cta-click`. Only once `start()` ran — like the funnel
|
|
8314
|
+
* events of the elements, never queued before. An invalid `cta` is ignored
|
|
8315
|
+
* with one `console.warn`; consent, `privateContent`, internal traffic,
|
|
8316
|
+
* batching and attribution are those of every event.
|
|
8317
|
+
*/
|
|
8318
|
+
trackCta(input) {
|
|
8319
|
+
if (!hasDom() || !this.started) return;
|
|
8320
|
+
const context = ctaContextOf(input);
|
|
8321
|
+
if (!context) return;
|
|
8322
|
+
this.track("cta_click", { context });
|
|
8323
|
+
}
|
|
8211
8324
|
/**
|
|
8212
8325
|
* Impression helper: observes an element and tracks ONE
|
|
8213
8326
|
* `component_impression` per (session, campaignComponentId) when the
|
|
@@ -8330,7 +8443,16 @@ var AnalyticsManager = class extends EventTarget {
|
|
|
8330
8443
|
layout_id: ctx.layoutId,
|
|
8331
8444
|
layout_revision: ctx.layoutRevision,
|
|
8332
8445
|
experiment_id: ctx.experimentId,
|
|
8333
|
-
variant_id: ctx.variantId
|
|
8446
|
+
variant_id: ctx.variantId,
|
|
8447
|
+
// `cta_click` (./cta.ts). Con `privateContent` el texto del botón y el
|
|
8448
|
+
// valor elegido no salen del dispositivo: pueden nombrar el producto.
|
|
8449
|
+
cta: ctx.cta,
|
|
8450
|
+
cta_location: ctx.ctaLocation,
|
|
8451
|
+
cta_label: this.options.privateContent ? void 0 : ctx.ctaLabel,
|
|
8452
|
+
cta_variant: ctx.ctaVariant,
|
|
8453
|
+
option_value: this.options.privateContent ? void 0 : ctx.optionValue,
|
|
8454
|
+
product_id: ctx.productId,
|
|
8455
|
+
product_variant_id: ctx.productVariantId
|
|
8334
8456
|
});
|
|
8335
8457
|
const com = opts.commerce;
|
|
8336
8458
|
const commerce = com ? compact({
|
|
@@ -8567,6 +8689,10 @@ var AnalyticsManager = class extends EventTarget {
|
|
|
8567
8689
|
}
|
|
8568
8690
|
});
|
|
8569
8691
|
});
|
|
8692
|
+
on("vio:cta-click", (ev) => {
|
|
8693
|
+
const d = ev.detail;
|
|
8694
|
+
if (d) this.trackCta(d);
|
|
8695
|
+
});
|
|
8570
8696
|
on("vio:open-cart", () => {
|
|
8571
8697
|
const snap = this.cartCommerce();
|
|
8572
8698
|
this.track("view_cart", snap ? { commerce: snap } : {});
|
|
@@ -9326,6 +9452,7 @@ var VioFacade = class {
|
|
|
9326
9452
|
*/
|
|
9327
9453
|
configureDetail(options = {}) {
|
|
9328
9454
|
if (options && typeof options === "object" && "layout" in options) setGlobalDetailLayout(options.layout ?? null);
|
|
9455
|
+
if (options && typeof options === "object" && "descriptionLabel" in options) setGlobalDescriptionLabel(options.descriptionLabel ?? null);
|
|
9329
9456
|
}
|
|
9330
9457
|
/**
|
|
9331
9458
|
* The layout a `<vio-product-detail>` without its own `layout` applies now:
|
|
@@ -9335,6 +9462,22 @@ var VioFacade = class {
|
|
|
9335
9462
|
detailLayout() {
|
|
9336
9463
|
return copyAppliedLayout(resolveDetailLayout(null));
|
|
9337
9464
|
}
|
|
9465
|
+
/**
|
|
9466
|
+
* Report a tap on one of the host's own buttons (its cards, its article
|
|
9467
|
+
* blocks) as `cta_click`, the event the SDK's own buttons send — so the
|
|
9468
|
+
* dashboard compares them on one scale. `{ cta, location?, label?,
|
|
9469
|
+
* variant?, optionValue?, productId?, productVariantId?, sponsorId?,
|
|
9470
|
+
* campaignId?, slot?, contentId?, layout? }`; `location` is `host` by
|
|
9471
|
+
* default (`card` / `block` for the host's cards and article blocks). An
|
|
9472
|
+
* invalid `cta` is ignored with one `console.warn`. Nothing is sent before
|
|
9473
|
+
* `Vio.analytics.start()`. Never throws. See README «Button tracking».
|
|
9474
|
+
*/
|
|
9475
|
+
trackCta(input) {
|
|
9476
|
+
try {
|
|
9477
|
+
this.analytics.trackCta(input);
|
|
9478
|
+
} catch {
|
|
9479
|
+
}
|
|
9480
|
+
}
|
|
9338
9481
|
get isInitialized() {
|
|
9339
9482
|
return Configuration.isInitialized;
|
|
9340
9483
|
}
|
|
@@ -9662,7 +9805,7 @@ var VioFacade = class {
|
|
|
9662
9805
|
const all = normalizeSlotLocations(slots);
|
|
9663
9806
|
if (all.length === 0) return null;
|
|
9664
9807
|
if (!Configuration.isInitialized) {
|
|
9665
|
-
|
|
9808
|
+
warn2("declareSlots() before Vio.init() \u2014 nothing declared");
|
|
9666
9809
|
return null;
|
|
9667
9810
|
}
|
|
9668
9811
|
const cfg = Configuration.get();
|
|
@@ -9680,7 +9823,7 @@ var VioFacade = class {
|
|
|
9680
9823
|
if (locations.length > MAX_LOCATIONS_PER_DECLARATION) {
|
|
9681
9824
|
if (!this.warnedLocationCap) {
|
|
9682
9825
|
this.warnedLocationCap = true;
|
|
9683
|
-
|
|
9826
|
+
warn2(
|
|
9684
9827
|
`declareSlots(): ${locations.length} slots on one page \u2014 only the first ${MAX_LOCATIONS_PER_DECLARATION} are declared`
|
|
9685
9828
|
);
|
|
9686
9829
|
}
|
|
@@ -9690,7 +9833,7 @@ var VioFacade = class {
|
|
|
9690
9833
|
if (!opts.force && this.declarationsThisLoad >= MAX_DECLARATIONS_PER_LOAD) {
|
|
9691
9834
|
if (!this.warnedDeclarationCap) {
|
|
9692
9835
|
this.warnedDeclarationCap = true;
|
|
9693
|
-
|
|
9836
|
+
warn2(
|
|
9694
9837
|
`declareSlots(): already ${MAX_DECLARATIONS_PER_LOAD} manifests this page load \u2014 further ones are skipped (force: true to override)`
|
|
9695
9838
|
);
|
|
9696
9839
|
}
|
|
@@ -9712,7 +9855,7 @@ var VioFacade = class {
|
|
|
9712
9855
|
writeSlotDeclaration(storageKey, next);
|
|
9713
9856
|
} else {
|
|
9714
9857
|
writeSlotDeclaration(storageKey, rememberSlotKeys(memory2, keys, failedAt(now)));
|
|
9715
|
-
|
|
9858
|
+
warn2(
|
|
9716
9859
|
"slots declared but the server ignored mode=merge (old server); not caching, will retry next load"
|
|
9717
9860
|
);
|
|
9718
9861
|
}
|
|
@@ -9721,7 +9864,7 @@ var VioFacade = class {
|
|
|
9721
9864
|
if (storageKey && keys.length > 0) {
|
|
9722
9865
|
writeSlotDeclaration(storageKey, rememberSlotKeys(readSlotDeclaration(storageKey), keys, failedAt(now)));
|
|
9723
9866
|
}
|
|
9724
|
-
|
|
9867
|
+
warn2("declareSlots() failed \u2014", err);
|
|
9725
9868
|
return null;
|
|
9726
9869
|
}
|
|
9727
9870
|
}
|
|
@@ -10083,11 +10226,11 @@ var VioFacade = class {
|
|
|
10083
10226
|
if (sentCampaign === void 0) continue;
|
|
10084
10227
|
if (l.assignment === "dashboard" && !this.warnedDashboardSlots.has(l.locationId)) {
|
|
10085
10228
|
this.warnedDashboardSlots.add(l.locationId);
|
|
10086
|
-
|
|
10229
|
+
warn2(`slot ${l.locationId} is assigned from the dashboard; the page's campaign is ignored there`);
|
|
10087
10230
|
}
|
|
10088
10231
|
if (l.assignment === "replaced" && !this.warnedReplacedSlots.has(l.locationId)) {
|
|
10089
10232
|
this.warnedReplacedSlots.add(l.locationId);
|
|
10090
|
-
|
|
10233
|
+
warn2(`slot ${l.locationId} moved to campaign ${sentCampaign} by this page (it replaced an earlier page assignment)`);
|
|
10091
10234
|
}
|
|
10092
10235
|
}
|
|
10093
10236
|
}
|
|
@@ -10159,7 +10302,7 @@ function documentCampaignHints() {
|
|
|
10159
10302
|
return [];
|
|
10160
10303
|
}
|
|
10161
10304
|
}
|
|
10162
|
-
function
|
|
10305
|
+
function warn2(...args) {
|
|
10163
10306
|
if (typeof console !== "undefined") console.warn("[Vio]", ...args);
|
|
10164
10307
|
}
|
|
10165
10308
|
function failedAt(now) {
|
|
@@ -10217,6 +10360,6 @@ function vippsButtonAttributes(verb = "buy", opts = {}) {
|
|
|
10217
10360
|
};
|
|
10218
10361
|
}
|
|
10219
10362
|
|
|
10220
|
-
export { ADD_ITEM_MUTATION, ADYEN_RETURN_METHOD, ADYEN_RETURN_QUERY_KEYS, AdyenOriginError, AnalyticsManager, BUYER_REF_MAX_LENGTH, CHECKOUT_ATTRIBUTION_CAPS, CHECKOUT_SPONSOR_STORAGE_KEY, 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, CartManager, CheckoutManager, CommerceClient, Configuration, DELETE_ITEM_MUTATION, DETAIL_SECTION_IDS, ESSENTIAL_DETAIL_SECTIONS, GET_AVAILABLE_PAYMENT_METHODS_QUERY, GET_CART_QUERY, GET_CHECKOUT_QUERY, GET_LINE_ITEMS_BY_SUPPLIER_QUERY, GET_VIPPS_STATUS_QUERY, GRAPHQL_INT_MAX, INTERNAL_KEY, INTERNAL_PARAM, KUSTOM_RETURN_QUERY_KEYS, LINE_ORIGIN_CAPS, SDK_VERSION, 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, __decorateClass, activeCampaignEntry, addItem, adyenReturnOutcome, adyenReturnParams, autoSlotDisplayName, autoSlotId, buyerRefOf, campaignCandidates, capContentUrl, cartSlicesFrom, checkApplePayAvailability, checkoutAttributionOf, checkoutSponsorOf, componentKindOf, copyAppliedLayout, createCart, createCheckout, createCommerceClient, createPaymentStripe, createPaymentVipps, createVioApi, defaultDetailLayout, deleteItem, displayPrice, dominantCampaignOf, effectiveDetailSections, ensureVippsButton, entryContextOf, executeCartGraphQL, formatPrice, gatewayHas, gatewayHasBuyerRef, getAvailablePaymentMethods, getCart, getCartGraphQLOptions, getCheckout, getCheckoutReference, getCustomerSessionId, getGlobalCountryCode, getGlobalCurrency, getLineItemsBySupplier, getVippsStatus, isUnknownFeatureError, isUnknownTokenError, isValidPhone, kustomReturnOutcome, landingUrl, layoutOriginOf, layoutSignature, lineOriginWire, lineOrigins, nexiReturnPaymentId, normalizeBuyerRef, normalizeDetailLayout, normalizeOrigin, normalizeScope, normalizeSlotId, normalizeSlotKind, onGlobalDetailLayoutChange, originAndPath, primaryImageUrl, purchaseFromPaymentSuccess, purchaseIdsOf, readInternal, readNexiPending, rememberedCheckoutSponsor, resetGatewayFeatures, resolveCampaignId, resolveClientContext, resolveContent, resolveDetailLayout, resolveInternal, resolveLanding, resolveSlotCampaign, sameOrigin, shippingDescriptionOf, showApplePaySheet, sponsorCampaignEntry, sponsorIdentityFrom, storageGet, storedLanding, toCampaignId, updateCheckout, updateItem, updateShippingsBySupplier, vippsButtonAttributes, withGatewayFeature, writeInternal };
|
|
10221
|
-
//# sourceMappingURL=chunk-
|
|
10222
|
-
//# sourceMappingURL=chunk-
|
|
10363
|
+
export { ADD_ITEM_MUTATION, ADYEN_RETURN_METHOD, ADYEN_RETURN_QUERY_KEYS, AdyenOriginError, AnalyticsManager, BUYER_REF_MAX_LENGTH, CHECKOUT_ATTRIBUTION_CAPS, CHECKOUT_SPONSOR_STORAGE_KEY, 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, CTA_ID_PATTERN, CTA_LOCATIONS, CTA_TEXT_MAX_LENGTH, CTA_VARIANT_PATTERN, CartManager, CheckoutManager, CommerceClient, Configuration, DELETE_ITEM_MUTATION, DETAIL_SECTION_IDS, ESSENTIAL_DETAIL_SECTIONS, GET_AVAILABLE_PAYMENT_METHODS_QUERY, GET_CART_QUERY, GET_CHECKOUT_QUERY, GET_LINE_ITEMS_BY_SUPPLIER_QUERY, GET_VIPPS_STATUS_QUERY, GRAPHQL_INT_MAX, INTERNAL_KEY, INTERNAL_PARAM, KUSTOM_RETURN_QUERY_KEYS, LINE_ORIGIN_CAPS, SDK_VERSION, 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, __decorateClass, activeCampaignEntry, addItem, adyenReturnOutcome, adyenReturnParams, autoSlotDisplayName, autoSlotId, buyerRefOf, campaignCandidates, capContentUrl, cartSlicesFrom, checkApplePayAvailability, checkoutAttributionOf, checkoutSponsorOf, componentKindOf, copyAppliedLayout, createCart, createCheckout, createCommerceClient, createPaymentStripe, createPaymentVipps, createVioApi, ctaContextOf, ctaText, currentGlobalDescriptionLabel, defaultDetailLayout, deleteItem, displayPrice, dominantCampaignOf, effectiveDetailSections, ensureVippsButton, entryContextOf, executeCartGraphQL, formatPrice, gatewayHas, gatewayHasBuyerRef, getAvailablePaymentMethods, getCart, getCartGraphQLOptions, getCheckout, getCheckoutReference, getCustomerSessionId, getGlobalCountryCode, getGlobalCurrency, getLineItemsBySupplier, getVippsStatus, isCtaId, isUnknownFeatureError, isUnknownTokenError, isValidPhone, kustomReturnOutcome, landingUrl, layoutOriginOf, layoutSignature, lineOriginWire, lineOrigins, nexiReturnPaymentId, normalizeBuyerRef, normalizeDetailLayout, normalizeOrigin, normalizeScope, normalizeSlotId, normalizeSlotKind, onGlobalDetailLayoutChange, originAndPath, primaryImageUrl, purchaseFromPaymentSuccess, purchaseIdsOf, readInternal, readNexiPending, rememberedCheckoutSponsor, resetGatewayFeatures, resolveCampaignId, resolveClientContext, resolveContent, resolveDetailLayout, resolveInternal, resolveLanding, resolveSlotCampaign, sameOrigin, shippingDescriptionOf, showApplePaySheet, sponsorCampaignEntry, sponsorIdentityFrom, storageGet, storedLanding, toCampaignId, updateCheckout, updateItem, updateShippingsBySupplier, vippsButtonAttributes, withGatewayFeature, writeInternal };
|
|
10364
|
+
//# sourceMappingURL=chunk-KVI56NGO.js.map
|
|
10365
|
+
//# sourceMappingURL=chunk-KVI56NGO.js.map
|