@vio-live/web-sdk 0.36.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.
@@ -1,4 +1,4 @@
1
- import { Vio, __decorateClass, primaryImageUrl, displayPrice, resolveDetailLayout, toCampaignId, getGlobalCurrency, copyAppliedLayout, onGlobalDetailLayoutChange, layoutSignature, layoutOriginOf, ensureVippsButton, formatPrice, currentGlobalDescriptionLabel, shippingDescriptionOf, buyerRefOf, nexiReturnPaymentId, readNexiPending, kustomReturnOutcome, KUSTOM_RETURN_QUERY_KEYS, storageGet, ADYEN_RETURN_METHOD, adyenReturnParams, ADYEN_RETURN_QUERY_KEYS, adyenReturnOutcome, getGlobalCountryCode, isValidPhone, gatewayHasBuyerRef, rememberedCheckoutSponsor, checkoutSponsorOf, AdyenOriginError, normalizeSlotId, autoSlotDisplayName, autoSlotId, sponsorIdentityFrom, Configuration, normalizeScope, campaignCandidates } from './chunk-6PQFXUOW.js';
1
+ import { Vio, __decorateClass, primaryImageUrl, displayPrice, resolveDetailLayout, toCampaignId, getGlobalCurrency, layoutOriginOf, copyAppliedLayout, onGlobalDetailLayoutChange, layoutSignature, ensureVippsButton, formatPrice, currentGlobalDescriptionLabel, shippingDescriptionOf, lineOrigins, buyerRefOf, nexiReturnPaymentId, readNexiPending, kustomReturnOutcome, KUSTOM_RETURN_QUERY_KEYS, storageGet, ADYEN_RETURN_METHOD, adyenReturnParams, ADYEN_RETURN_QUERY_KEYS, adyenReturnOutcome, getGlobalCountryCode, isValidPhone, gatewayHasBuyerRef, rememberedCheckoutSponsor, checkoutSponsorOf, AdyenOriginError, normalizeSlotId, autoSlotDisplayName, autoSlotId, sponsorIdentityFrom, Configuration, normalizeScope, campaignCandidates, ctaText } from './chunk-KVI56NGO.js';
2
2
  import { LitElement, css, html, nothing } from 'lit';
3
3
  import { property, state, query } from 'lit/decorators.js';
4
4
 
@@ -373,6 +373,61 @@ function closestAcrossShadow(start, selector) {
373
373
  return null;
374
374
  }
375
375
 
376
+ // src/ui/cta.ts
377
+ function labelOf(button) {
378
+ if (button.hasAttribute("data-vio-cta-label")) return ctaText(button.getAttribute("data-vio-cta-label"));
379
+ return ctaText(button.getAttribute("aria-label")) ?? ctaText(button.textContent);
380
+ }
381
+ function emitCta(host, location, cta, contextOf, extra = {}, button = null) {
382
+ try {
383
+ const context = contextOf(cta, button);
384
+ if (context === null) return;
385
+ const detail = { ...context, ...stripUndefined(extra), cta, location };
386
+ host.dispatchEvent(new CustomEvent("vio:cta-click", { bubbles: true, composed: true, detail }));
387
+ } catch {
388
+ }
389
+ }
390
+ function stripUndefined(obj) {
391
+ const out = {};
392
+ for (const [k, v] of Object.entries(obj)) if (v !== void 0) out[k] = v;
393
+ return out;
394
+ }
395
+ function trackCtaClicks(host, location, contextOf) {
396
+ const root = host.renderRoot ?? host.shadowRoot;
397
+ if (!root || typeof root.addEventListener !== "function") return () => {
398
+ };
399
+ const onClick = (ev) => {
400
+ try {
401
+ const button = markedButton(ev, root);
402
+ if (!button) return;
403
+ const cta = button.getAttribute("data-vio-cta") ?? "";
404
+ if (button.tagName === "SUMMARY" && button.parentElement?.open) return;
405
+ const option = button.getAttribute("data-vio-cta-option");
406
+ emitCta(
407
+ host,
408
+ location,
409
+ cta,
410
+ contextOf,
411
+ { label: labelOf(button), ...option !== null ? { optionValue: option } : {} },
412
+ button
413
+ );
414
+ } catch {
415
+ }
416
+ };
417
+ root.addEventListener("click", onClick, { capture: true });
418
+ return () => root.removeEventListener("click", onClick, { capture: true });
419
+ }
420
+ function markedButton(ev, root) {
421
+ const path = typeof ev.composedPath === "function" ? ev.composedPath() : [];
422
+ for (const node of path) {
423
+ if (node === root) break;
424
+ if (!(node instanceof Element)) continue;
425
+ if (node.getRootNode() !== root) continue;
426
+ if (node.hasAttribute("data-vio-cta")) return node;
427
+ }
428
+ return null;
429
+ }
430
+
376
431
  // src/ui/components/vio-product.ts
377
432
  var VioProduct = class extends LitElement {
378
433
  constructor() {
@@ -405,6 +460,21 @@ var VioProduct = class extends LitElement {
405
460
  this.cartQty = 0;
406
461
  this.justAdded = false;
407
462
  this.boundCartChange = () => this.updateInCart();
463
+ /** Stops reporting the taps on the buttons (`vio:cta-click`). */
464
+ this.stopCtaClicks = null;
465
+ /** What a tap on the card says (`vio:cta-click`): its product, sponsor and attribution. */
466
+ this.ctaContext = () => {
467
+ const a = this.attribution();
468
+ return {
469
+ productId: this.productId || void 0,
470
+ sponsorId: this.sponsorId || this.sponsorFromAttribution(),
471
+ campaignId: a.campaignId,
472
+ slot: a.slot,
473
+ contentId: a.contentId,
474
+ contentTitle: a.contentTitle,
475
+ componentTemplateId: a.componentTemplateId
476
+ };
477
+ };
408
478
  }
409
479
  /** The slot id in effect: `vio-slot`, else the auto id (`card-N`). Read-only. */
410
480
  get effectiveSlot() {
@@ -609,8 +679,12 @@ var VioProduct = class extends LitElement {
609
679
  this.updateInCart();
610
680
  this.slotRegistration.connect(this.slotAttributes());
611
681
  Vio.cart.addEventListener("change", this.boundCartChange);
682
+ this.stopCtaClicks?.();
683
+ this.stopCtaClicks = trackCtaClicks(this, "card", this.ctaContext);
612
684
  }
613
685
  disconnectedCallback() {
686
+ this.stopCtaClicks?.();
687
+ this.stopCtaClicks = null;
614
688
  Vio.cart.removeEventListener("change", this.boundCartChange);
615
689
  this.slotRegistration.clear();
616
690
  super.disconnectedCallback();
@@ -660,6 +734,7 @@ var VioProduct = class extends LitElement {
660
734
  onKeydown(e) {
661
735
  if (e.key === "Enter" || e.key === " ") {
662
736
  e.preventDefault();
737
+ if (e.target === e.currentTarget) emitCta(this, "card", "open", this.ctaContext);
663
738
  this.onClick();
664
739
  }
665
740
  }
@@ -710,6 +785,8 @@ var VioProduct = class extends LitElement {
710
785
  return html`
711
786
  <div
712
787
  class="card"
788
+ data-vio-cta="open"
789
+ data-vio-cta-label=""
713
790
  @click=${this.onClick}
714
791
  @keydown=${this.onKeydown}
715
792
  role="button"
@@ -720,6 +797,8 @@ var VioProduct = class extends LitElement {
720
797
  ${this.imageUrl ? html`<img src=${this.imageUrl} alt=${this.name || this.brand} loading="lazy" />` : ""}
721
798
  ${this.buttonStyle === "icon" ? html`<button
722
799
  class="add-btn ${this.inCart ? "in-cart" : ""} ${this.justAdded ? "pop" : ""}"
800
+ data-vio-cta="add"
801
+ data-vio-cta-label="Legg i kurv"
723
802
  @click=${this.onAdd}
724
803
  aria-label=${this.inCart ? "I handlekurven \u2013 legg til en til" : "Legg i kurv"}
725
804
  title=${this.inCart ? "I handlekurven" : "Legg i kurv"}
@@ -740,7 +819,7 @@ var VioProduct = class extends LitElement {
740
819
  ${this.showDescription && this.description ? html`<p class="description">${this.description}</p>` : ""}
741
820
  ${this.price ? html`<div class="price">${this.price}</div>` : ""}
742
821
  ${this.retailer ? html`<div class="retailer">${this.retailer}</div>` : ""}
743
- ${this.buttonStyle === "bar" ? html`<button class="bar-btn ${this.justAdded ? "pop" : ""}" @click=${this.onAdd}>
822
+ ${this.buttonStyle === "bar" ? html`<button class="bar-btn ${this.justAdded ? "pop" : ""}" data-vio-cta="add" data-vio-cta-label=${this.buttonLabel} @click=${this.onAdd}>
744
823
  ${this.inCart ? `${this.buttonLabel} \xB7 ${this.cartQty}` : this.buttonLabel}
745
824
  </button>` : ""}
746
825
  </div>`}
@@ -2265,12 +2344,54 @@ var VioProductDetail = class extends LitElement {
2265
2344
  this.show();
2266
2345
  void this.fetchProduct();
2267
2346
  };
2347
+ /** Stops reporting the taps on the buttons (`vio:cta-click`). */
2348
+ this.stopCtaClicks = null;
2349
+ /** The product open when the shopper last changed photo: `gallery_swipe` once per open. */
2350
+ this.gallerySwipedFor = null;
2351
+ /** A finger, a pen or a wheel is on the carousel: its scroll is the shopper's swipe, not the SDK's. */
2352
+ this.galleryGesture = false;
2353
+ /**
2354
+ * What a tap on a button of the detail says (`vio:cta-click`, README
2355
+ * «Button tracking»): the open product and the variant chosen (when every
2356
+ * option is), its sponsor and attribution, and the layout shown (only a
2357
+ * non-default one). `gallery_swipe` only once per open product.
2358
+ */
2359
+ this.ctaContext = (cta) => {
2360
+ const product = this.product;
2361
+ if (cta === "gallery_swipe") {
2362
+ if (!product || this.gallerySwipedFor === product) return null;
2363
+ this.gallerySwipedFor = product;
2364
+ }
2365
+ const a = this.attribution();
2366
+ const variants = Array.isArray(product?.variants) ? product.variants : [];
2367
+ const variant = product && (variants.length === 1 || !this.missingOption()) ? this.selectedVariant() : null;
2368
+ const layout = layoutOriginOf(this.layoutNow);
2369
+ return {
2370
+ productId: product?.id ?? (this.productId || void 0),
2371
+ productVariantId: variant?.id,
2372
+ sponsorId: this.sponsorId > 0 ? this.sponsorId : void 0,
2373
+ campaignId: a.campaignId,
2374
+ slot: a.slot,
2375
+ contentId: a.contentId,
2376
+ contentTitle: a.contentTitle,
2377
+ componentTemplateId: a.componentTemplateId,
2378
+ layout: layout.layoutId ? layout : null
2379
+ };
2380
+ };
2381
+ /** The carousel scrolled under the shopper's finger: their first swipe of this product. */
2382
+ this.onGalleryGesture = () => {
2383
+ this.galleryGesture = true;
2384
+ };
2268
2385
  /** The cart changed (another tab, the drawer): the line under Vipps counts it again. */
2269
2386
  this.boundCartChange = () => {
2270
2387
  if (this.open) this.requestUpdate();
2271
2388
  };
2272
2389
  /** The photo in view is the active one (dots, Apple Pay sheet, events). */
2273
2390
  this.onCarouselScroll = () => {
2391
+ if (this.galleryGesture) {
2392
+ this.galleryGesture = false;
2393
+ emitCta(this, "detail", "gallery_swipe", this.ctaContext);
2394
+ }
2274
2395
  const track = this.carouselTrack();
2275
2396
  const step = this.carouselStep(track);
2276
2397
  if (!track || !step) return;
@@ -3286,12 +3407,16 @@ var VioProductDetail = class extends LitElement {
3286
3407
  this.slotRegistration.connect(this.slotAttributes());
3287
3408
  void this.loadVippsButton();
3288
3409
  document.addEventListener("vio:product-click", this.boundProductClick);
3410
+ this.stopCtaClicks?.();
3411
+ this.stopCtaClicks = trackCtaClicks(this, "detail", this.ctaContext);
3289
3412
  }
3290
3413
  disconnectedCallback() {
3291
3414
  if (this.addedToastTimer) clearTimeout(this.addedToastTimer);
3292
3415
  this.addedToastTimer = null;
3293
3416
  document.removeEventListener("vio:product-click", this.boundProductClick);
3294
3417
  Vio.cart.removeEventListener("change", this.boundCartChange);
3418
+ this.stopCtaClicks?.();
3419
+ this.stopCtaClicks = null;
3295
3420
  this.slotRegistration.clear();
3296
3421
  this.bottomSheet.disconnect();
3297
3422
  this.unsubscribeLayout?.();
@@ -3961,7 +4086,7 @@ var VioProductDetail = class extends LitElement {
3961
4086
  <div class="added-toast" part="added-toast" role="status" aria-live="polite">
3962
4087
  <div class="added-toast-text">Lagt i handlekurven</div>
3963
4088
  <div class="added-toast-actions">
3964
- <button class="added-toast-checkout" part="added-toast-checkout" @click=${this.toastToCheckout}>Til kassen</button>
4089
+ <button class="added-toast-checkout" part="added-toast-checkout" data-vio-cta="checkout" @click=${this.toastToCheckout}>Til kassen</button>
3965
4090
  <button class="added-toast-continue" part="added-toast-continue" @click=${this.hideAddedToast}>Fortsett å handle</button>
3966
4091
  </div>
3967
4092
  </div>
@@ -4224,7 +4349,14 @@ var VioProductDetail = class extends LitElement {
4224
4349
  const current2 = Math.min(this.activeImageIndex, Math.max(0, count - 1));
4225
4350
  return html`
4226
4351
  <div class="gallery carousel" part="gallery">
4227
- <div class="carousel-track" part="image" @scroll=${this.onCarouselScroll}>
4352
+ <div
4353
+ class="carousel-track"
4354
+ part="image"
4355
+ @scroll=${this.onCarouselScroll}
4356
+ @pointerdown=${this.onGalleryGesture}
4357
+ @touchstart=${this.onGalleryGesture}
4358
+ @wheel=${this.onGalleryGesture}
4359
+ >
4228
4360
  ${images.map(
4229
4361
  (img, idx) => html`
4230
4362
  <div class="carousel-slide" part="slide" aria-label=${`Bilde ${idx + 1} av ${count}`}>
@@ -4238,6 +4370,7 @@ var VioProductDetail = class extends LitElement {
4238
4370
  class="carousel-arrow prev"
4239
4371
  part="carousel-arrow"
4240
4372
  aria-label="Forrige bilde"
4373
+ data-vio-cta="gallery_swipe"
4241
4374
  ?disabled=${current2 === 0}
4242
4375
  @click=${() => this.stepCarousel(-1)}
4243
4376
  >‹</button>
@@ -4245,6 +4378,7 @@ var VioProductDetail = class extends LitElement {
4245
4378
  class="carousel-arrow next"
4246
4379
  part="carousel-arrow"
4247
4380
  aria-label="Neste bilde"
4381
+ data-vio-cta="gallery_swipe"
4248
4382
  ?disabled=${current2 === count - 1}
4249
4383
  @click=${() => this.stepCarousel(1)}
4250
4384
  >›</button>
@@ -4278,10 +4412,16 @@ var VioProductDetail = class extends LitElement {
4278
4412
  const toggle = () => {
4279
4413
  if (foldable) this.descriptionOpen = !this.descriptionOpen;
4280
4414
  };
4415
+ const opens = foldable && !open ? "description_open" : nothing;
4281
4416
  return html`<div class="description-block description-preview ${open ? "open" : ""} ${foldable ? "clipped" : ""} ${mode}" part="description">
4282
- <button class="desc-head" type="button" aria-expanded=${open ? "true" : "false"} @click=${toggle}>${this.descriptionHeading()}</button>
4283
- ${mode === "folded" && !open ? nothing : html`<div class="description ${open ? "" : "collapsed"}" @click=${() => !this.descriptionOpen && toggle()}>${text}</div>`}
4284
- ${mode === "preview" && this.descriptionClipped ? html`<button class="desc-more" type="button" @click=${toggle}>${this.descriptionOpen ? "Vis mindre" : "Les mer"}</button>` : nothing}
4417
+ <button class="desc-head" type="button" aria-expanded=${open ? "true" : "false"} data-vio-cta=${opens} @click=${toggle}>${this.descriptionHeading()}</button>
4418
+ ${mode === "folded" && !open ? nothing : html`<div
4419
+ class="description ${open ? "" : "collapsed"}"
4420
+ data-vio-cta=${opens}
4421
+ data-vio-cta-label=${opens === nothing ? nothing : this.descriptionHeading()}
4422
+ @click=${() => !this.descriptionOpen && toggle()}
4423
+ >${text}</div>`}
4424
+ ${mode === "preview" && this.descriptionClipped ? html`<button class="desc-more" type="button" data-vio-cta=${opens} @click=${toggle}>${this.descriptionOpen ? "Vis mindre" : "Les mer"}</button>` : nothing}
4285
4425
  </div>`;
4286
4426
  }
4287
4427
  /** Is the preview hiding part of the text? Measured with the preview applied. */
@@ -4315,11 +4455,11 @@ var VioProductDetail = class extends LitElement {
4315
4455
  const perRateTime = times.length > 1;
4316
4456
  const sharedTime = times.length === 1 ? times[0] : times.length === 0 && this.deliveryTime.trim() ? `Leveringstid: ${this.deliveryTime.trim()}` : "";
4317
4457
  const links = [
4318
- identity?.refundPolicyUrl ? html`<a href=${identity.refundPolicyUrl} target="_blank" rel="noopener noreferrer">Angrerett og retur</a>` : null,
4319
- identity?.termsUrl ? html`<a href=${identity.termsUrl} target="_blank" rel="noopener noreferrer">Kjøpsvilkår</a>` : null
4458
+ identity?.refundPolicyUrl ? html`<a href=${identity.refundPolicyUrl} target="_blank" rel="noopener noreferrer" data-vio-cta="refund_link">Angrerett og retur</a>` : null,
4459
+ identity?.termsUrl ? html`<a href=${identity.termsUrl} target="_blank" rel="noopener noreferrer" data-vio-cta="terms_link">Kjøpsvilkår</a>` : null
4320
4460
  ].filter(Boolean);
4321
4461
  return html`<details class="description-block shipping-returns" part="shipping-returns">
4322
- <summary>Frakt &amp; retur</summary>
4462
+ <summary data-vio-cta="shipping_returns_open">Frakt &amp; retur</summary>
4323
4463
  <div class="description shipping-returns-body">
4324
4464
  <div class="sr-title">Frakt</div>
4325
4465
  ${rates.length ? html`<ul class="sr-rates">
@@ -4402,8 +4542,8 @@ var VioProductDetail = class extends LitElement {
4402
4542
  const name = identity?.name || this.headerName();
4403
4543
  if (!name) return nothing;
4404
4544
  const links = [
4405
- identity?.termsUrl ? html`<a href=${identity.termsUrl} target="_blank" rel="noopener noreferrer" part="seller-terms">Kjøpsvilkår</a>` : null,
4406
- identity?.refundPolicyUrl ? html`<a href=${identity.refundPolicyUrl} target="_blank" rel="noopener noreferrer" part="seller-refund">Angrerett og retur</a>` : null
4545
+ identity?.termsUrl ? html`<a href=${identity.termsUrl} target="_blank" rel="noopener noreferrer" part="seller-terms" data-vio-cta="terms_link">Kjøpsvilkår</a>` : null,
4546
+ identity?.refundPolicyUrl ? html`<a href=${identity.refundPolicyUrl} target="_blank" rel="noopener noreferrer" part="seller-refund" data-vio-cta="refund_link">Angrerett og retur</a>` : null
4407
4547
  ].filter(Boolean);
4408
4548
  return html`<p class="seller-note" part="seller-note">
4409
4549
  Du handler direkte hos <strong>${name}</strong>.${links.length ? html`<span class="seller-links">${links}</span>` : nothing}
@@ -4427,12 +4567,12 @@ var VioProductDetail = class extends LitElement {
4427
4567
  }
4428
4568
  render() {
4429
4569
  return html`
4430
- <div class="backdrop" @click=${this.close}></div>
4570
+ <div class="backdrop" data-vio-cta="close" data-vio-cta-label="" @click=${this.close}></div>
4431
4571
  <div class="modal" role="dialog" aria-modal="true" aria-label="Produkt" tabindex="-1">
4432
- <div class="handle" @click=${this.close} aria-hidden="true"></div>
4572
+ <div class="handle" data-vio-cta="close" data-vio-cta-label="" @click=${this.close} aria-hidden="true"></div>
4433
4573
  <div class="topbar" part="topbar">
4434
4574
  <div class="topbar-sponsor ${this.logoSquare ? "is-square" : ""}" part="sponsor">${this.renderTopbarSponsor()}</div>
4435
- <button class="close" part="close" @click=${this.close} aria-label="Lukk">×</button>
4575
+ <button class="close" part="close" data-vio-cta="close" @click=${this.close} aria-label="Lukk">×</button>
4436
4576
  </div>
4437
4577
 
4438
4578
  ${this.renderBody()}
@@ -4482,6 +4622,7 @@ var VioProductDetail = class extends LitElement {
4482
4622
  class="gallery-thumb ${idx === this.activeImageIndex ? "active" : ""}"
4483
4623
  part=${idx === this.activeImageIndex ? "thumb thumb-active" : "thumb"}
4484
4624
  @click=${() => this.activeImageIndex = idx}
4625
+ data-vio-cta=${idx === this.activeImageIndex ? nothing : "gallery_swipe"}
4485
4626
  aria-label=${`Bilde ${idx + 1}`}
4486
4627
  aria-current=${idx === this.activeImageIndex ? "true" : "false"}
4487
4628
  >
@@ -4620,12 +4761,14 @@ var VioProductDetail = class extends LitElement {
4620
4761
  stretched="true"
4621
4762
  role="button"
4622
4763
  aria-label="Kjøp nå med Vipps"
4764
+ data-vio-cta="vipps"
4623
4765
  @click=${this.buyWithVipps}
4624
4766
  ></vipps-mobilepay-button>
4625
4767
  ` : html`
4626
4768
  <button
4627
4769
  class="buy-vipps"
4628
4770
  part="buy-vipps"
4771
+ data-vio-cta="vipps"
4629
4772
  @click=${this.buyWithVipps}
4630
4773
  ?disabled=${this.adding}
4631
4774
  aria-label="Kjøp nå med Vipps"
@@ -4640,6 +4783,7 @@ var VioProductDetail = class extends LitElement {
4640
4783
  <div class="qty-stepper">
4641
4784
  <button
4642
4785
  class="qty-btn"
4786
+ data-vio-cta="quantity_minus"
4643
4787
  @click=${() => this.quantity = Math.max(1, this.quantity - 1)}
4644
4788
  aria-label="Reduser antall"
4645
4789
  >
@@ -4648,6 +4792,7 @@ var VioProductDetail = class extends LitElement {
4648
4792
  <span class="qty-value">${this.quantity}</span>
4649
4793
  <button
4650
4794
  class="qty-btn"
4795
+ data-vio-cta="quantity_plus"
4651
4796
  @click=${() => this.quantity = Math.min(this.availableQuantity, this.quantity + 1)}
4652
4797
  aria-label="Øk antall"
4653
4798
  ?disabled=${this.quantity >= this.availableQuantity}
@@ -4658,6 +4803,7 @@ var VioProductDetail = class extends LitElement {
4658
4803
  <button
4659
4804
  class="add-to-cart"
4660
4805
  part="add-to-cart"
4806
+ data-vio-cta="add_to_cart"
4661
4807
  @click=${this.addToCart}
4662
4808
  ?disabled=${this.availableQuantity <= 0 || this.adding}
4663
4809
  >
@@ -4668,6 +4814,7 @@ var VioProductDetail = class extends LitElement {
4668
4814
  ${this.availableQuantity > 0 && this.methodEnabled(...NO_EXPRESS_BUTTON_METHODS) ? html`
4669
4815
  <button
4670
4816
  class="buy-now"
4817
+ data-vio-cta="buy_now"
4671
4818
  @click=${this.buyNow}
4672
4819
  ?disabled=${this.adding}
4673
4820
  aria-label="Kjøp nå"
@@ -4679,6 +4826,7 @@ var VioProductDetail = class extends LitElement {
4679
4826
  ${this.availableQuantity > 0 && this.hasPrice && this.applePayOk && this.methodEnabled("apple-pay", "applepay") ? html`
4680
4827
  <button
4681
4828
  class="buy-applepay"
4829
+ data-vio-cta="apple_pay"
4682
4830
  @click=${this.buyWithApplePay}
4683
4831
  ?disabled=${this.adding}
4684
4832
  aria-label="Kjøp nå med Apple Pay"
@@ -4691,6 +4839,7 @@ var VioProductDetail = class extends LitElement {
4691
4839
  ${this.availableQuantity > 0 && this.methodEnabled("stripe") ? html`
4692
4840
  <button
4693
4841
  class="buy-stripe"
4842
+ data-vio-cta="stripe"
4694
4843
  @click=${this.buyWithStripe}
4695
4844
  ?disabled=${this.adding}
4696
4845
  aria-label="Kjøp nå med Stripe"
@@ -4707,6 +4856,8 @@ var VioProductDetail = class extends LitElement {
4707
4856
  ${this.availableQuantity > 0 && this.methodEnabled("klarna") ? html`
4708
4857
  <button
4709
4858
  class="buy-klarna"
4859
+ data-vio-cta="klarna"
4860
+ data-vio-cta-label="Kjøp nå med Klarna"
4710
4861
  @click=${this.buyWithKlarna}
4711
4862
  ?disabled=${this.adding}
4712
4863
  >
@@ -4749,6 +4900,8 @@ var VioProductDetail = class extends LitElement {
4749
4900
  <button
4750
4901
  class="option-pill ${available ? "" : "unavailable"}"
4751
4902
  part=${isSelected ? "option option-selected" : "option"}
4903
+ data-vio-cta="size"
4904
+ data-vio-cta-option=${val}
4752
4905
  @click=${() => this.selectOption(opt.name, val)}
4753
4906
  aria-pressed=${isSelected}
4754
4907
  ?disabled=${!available}
@@ -5005,6 +5158,35 @@ var VioCart = class extends LitElement {
5005
5158
  void this.loadAvailablePaymentMethods();
5006
5159
  }
5007
5160
  };
5161
+ /** Stops reporting the taps on the buttons (`vio:cta-click`). */
5162
+ this.stopCtaClicks = null;
5163
+ /**
5164
+ * What a tap on a button of the cart says (`vio:cta-click`): a line's
5165
+ * buttons name its product, variant and sponsor, and where its most recent
5166
+ * units came from (campaign, slot, article); the footer's buttons name the
5167
+ * sponsor they pay (Vipps: the one it pays; the others: the first).
5168
+ */
5169
+ this.ctaContext = (_cta, button) => {
5170
+ const lineId = button?.getAttribute("data-vio-cta-line");
5171
+ if (lineId) {
5172
+ for (const cart of this.carts.values()) {
5173
+ const item = cart.items.find((i) => i.id === lineId);
5174
+ if (!item) continue;
5175
+ const origin = [...lineOrigins(item)].reverse().find((o) => o.campaignId !== void 0 || o.slot || o.contentId);
5176
+ return {
5177
+ productId: item.productId,
5178
+ productVariantId: item.variantId,
5179
+ sponsorId: item.sponsorId,
5180
+ campaignId: origin?.campaignId,
5181
+ slot: origin?.slot,
5182
+ contentId: origin?.contentId
5183
+ };
5184
+ }
5185
+ return {};
5186
+ }
5187
+ const sponsorId = _cta === "vipps" ? this.vippsSponsorId() : [...this.carts.keys()][0];
5188
+ return { sponsorId };
5189
+ };
5008
5190
  }
5009
5191
  static {
5010
5192
  this.styles = [
@@ -5401,8 +5583,12 @@ var VioCart = class extends LitElement {
5401
5583
  this.itemCount = Vio.cart.itemCount;
5402
5584
  Vio.cart.addEventListener("change", this.boundOnCartChange);
5403
5585
  void this.loadAvailablePaymentMethods();
5586
+ this.stopCtaClicks?.();
5587
+ this.stopCtaClicks = trackCtaClicks(this, "cart", this.ctaContext);
5404
5588
  }
5405
5589
  disconnectedCallback() {
5590
+ this.stopCtaClicks?.();
5591
+ this.stopCtaClicks = null;
5406
5592
  Vio.cart.removeEventListener("change", this.boundOnCartChange);
5407
5593
  this.bottomSheet.disconnect();
5408
5594
  super.disconnectedCallback();
@@ -5717,12 +5903,12 @@ var VioCart = class extends LitElement {
5717
5903
  const isEmpty = this.itemCount === 0;
5718
5904
  const sponsorCarts = [...this.carts.values()].filter((c) => c.items.length > 0);
5719
5905
  return html`
5720
- <div class="backdrop" @click=${this.close}></div>
5906
+ <div class="backdrop" data-vio-cta="close" data-vio-cta-label="" @click=${this.close}></div>
5721
5907
  <aside class="drawer" role="dialog" aria-modal="true" aria-label=${this.heading} tabindex="-1">
5722
- <div class="handle" @click=${this.close} aria-hidden="true"></div>
5908
+ <div class="handle" data-vio-cta="close" data-vio-cta-label="" @click=${this.close} aria-hidden="true"></div>
5723
5909
  <div class="header">
5724
5910
  <h2 class="heading">${this.confirmedOrder ? "Takk!" : this.heading}</h2>
5725
- <button class="close" @click=${this.close} aria-label="Lukk">×</button>
5911
+ <button class="close" data-vio-cta="close" @click=${this.close} aria-label="Lukk">×</button>
5726
5912
  </div>
5727
5913
 
5728
5914
  ${this.confirmedOrder ? this.renderConfirmation() : isEmpty ? html`<div class="empty">${this.emptyLabel}</div>` : html`
@@ -5744,6 +5930,8 @@ var VioCart = class extends LitElement {
5744
5930
  <span class="item-qty">
5745
5931
  <button
5746
5932
  class="qty-btn"
5933
+ data-vio-cta="quantity_minus"
5934
+ data-vio-cta-line=${item.id}
5747
5935
  @click=${() => this.onDecrement(item)}
5748
5936
  aria-label="Reduser"
5749
5937
  >
@@ -5752,6 +5940,8 @@ var VioCart = class extends LitElement {
5752
5940
  ${item.quantity}
5753
5941
  <button
5754
5942
  class="qty-btn"
5943
+ data-vio-cta="quantity_plus"
5944
+ data-vio-cta-line=${item.id}
5755
5945
  @click=${() => this.onIncrement(item)}
5756
5946
  aria-label="Øk"
5757
5947
  >
@@ -5759,6 +5949,8 @@ var VioCart = class extends LitElement {
5759
5949
  </button>
5760
5950
  <button
5761
5951
  class="qty-btn"
5952
+ data-vio-cta="remove"
5953
+ data-vio-cta-line=${item.id}
5762
5954
  @click=${() => this.onRemove(item)}
5763
5955
  aria-label="Fjern"
5764
5956
  style="margin-left: 8px;"
@@ -5791,6 +5983,7 @@ var VioCart = class extends LitElement {
5791
5983
  ${this.renderShippingRows()}
5792
5984
  <button
5793
5985
  class="checkout-btn"
5986
+ data-vio-cta="checkout"
5794
5987
  @click=${this.onCheckout}
5795
5988
  ?disabled=${!this.payable}
5796
5989
  aria-label="Til kassen"
@@ -5801,6 +5994,7 @@ var VioCart = class extends LitElement {
5801
5994
  ${this.methodEnabled("apple-pay") && this.applePayAvailable ? html`
5802
5995
  <button
5803
5996
  class="applepay-btn"
5997
+ data-vio-cta="apple_pay"
5804
5998
  @click=${this.onApplePay}
5805
5999
  aria-label="Betal med Apple Pay"
5806
6000
  >
@@ -5811,6 +6005,7 @@ var VioCart = class extends LitElement {
5811
6005
  ${this.methodEnabled("stripe") ? html`
5812
6006
  <button
5813
6007
  class="stripe-btn"
6008
+ data-vio-cta="stripe"
5814
6009
  @click=${this.onStripe}
5815
6010
  aria-label="Betal med Stripe"
5816
6011
  >
@@ -5820,6 +6015,7 @@ var VioCart = class extends LitElement {
5820
6015
  ${this.methodEnabled("klarna") ? html`
5821
6016
  <button
5822
6017
  class="klarna-btn"
6018
+ data-vio-cta="klarna"
5823
6019
  @click=${this.onKlarnaExpress}
5824
6020
  aria-label="Betal med Klarna"
5825
6021
  >
@@ -5842,11 +6038,13 @@ var VioCart = class extends LitElement {
5842
6038
  stretched="true"
5843
6039
  role="button"
5844
6040
  aria-label="Betal med Vipps"
6041
+ data-vio-cta="vipps"
5845
6042
  @click=${this.onVipps}
5846
6043
  ></vipps-mobilepay-button>
5847
6044
  ` : html`
5848
6045
  <button
5849
6046
  class="vipps-btn"
6047
+ data-vio-cta="vipps"
5850
6048
  @click=${this.onVipps}
5851
6049
  aria-label="Betal med Vipps"
5852
6050
  >
@@ -5910,7 +6108,7 @@ var VioCart = class extends LitElement {
5910
6108
  <span>${formatPrice(o.total, o.currency)}</span>
5911
6109
  </div>
5912
6110
  </div>
5913
- <button class="confirm-close" @click=${this.closeConfirmation}>Lukk</button>
6111
+ <button class="confirm-close" data-vio-cta="close" @click=${this.closeConfirmation}>Lukk</button>
5914
6112
  </div>
5915
6113
  `;
5916
6114
  }
@@ -6205,6 +6403,12 @@ var _VioCheckout = class _VioCheckout extends LitElement {
6205
6403
  this.paymentError = detail.method === "klarna" ? `Klarna-betalingen kunne ikke fullf\xF8res: ${detail.error}` : friendlyPaymentError(detail.error, detail.method);
6206
6404
  this.open = true;
6207
6405
  };
6406
+ /** Stops reporting the taps on the buttons (`vio:cta-click`). */
6407
+ this.stopCtaClicks = null;
6408
+ /** What a tap on a button of the checkout says (`vio:cta-click`): the sponsor whose cart it pays. */
6409
+ this.ctaContext = () => ({
6410
+ sponsorId: this.checkoutState?.sponsorId ?? this.orderSponsor?.sponsorId
6411
+ });
6208
6412
  /** Payment events still waiting for their buyer reference: settled early (without it) when the page hides or the element leaves. */
6209
6413
  this.pendingSuccessEmits = /* @__PURE__ */ new Set();
6210
6414
  }
@@ -6836,6 +7040,8 @@ var _VioCheckout = class _VioCheckout extends LitElement {
6836
7040
  void Vio.checkout.resumeKlarnaReturn();
6837
7041
  void this.checkReturnPaymentStatus();
6838
7042
  this.requestUpdate();
7043
+ this.stopCtaClicks?.();
7044
+ this.stopCtaClicks = trackCtaClicks(this, "checkout", this.ctaContext);
6839
7045
  }
6840
7046
  static {
6841
7047
  /**
@@ -7288,6 +7494,8 @@ var _VioCheckout = class _VioCheckout extends LitElement {
7288
7494
  }
7289
7495
  }
7290
7496
  disconnectedCallback() {
7497
+ this.stopCtaClicks?.();
7498
+ this.stopCtaClicks = null;
7291
7499
  Vio.checkout.removeEventListener("change", this.boundOnCheckoutChange);
7292
7500
  Vio.checkout.removeEventListener("payment-complete", this.boundOnPaymentComplete);
7293
7501
  Vio.checkout.removeEventListener("payment-error", this.boundOnPaymentError);
@@ -8108,7 +8316,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
8108
8316
  }
8109
8317
  render() {
8110
8318
  return html`
8111
- <div class="backdrop" @click=${this.close}></div>
8319
+ <div class="backdrop" data-vio-cta="close" data-vio-cta-label="" @click=${this.close}></div>
8112
8320
  <div
8113
8321
  class="modal ${this.express ? "as-side" : this.orderConfirmed ? "as-confirm" : ""}"
8114
8322
  role="dialog"
@@ -8116,13 +8324,13 @@ var _VioCheckout = class _VioCheckout extends LitElement {
8116
8324
  aria-label=${this.heading}
8117
8325
  tabindex="-1"
8118
8326
  >
8119
- <div class="handle" @click=${this.close} aria-hidden="true"></div>
8327
+ <div class="handle" data-vio-cta="close" data-vio-cta-label="" @click=${this.close} aria-hidden="true"></div>
8120
8328
  <div class="topbar">
8121
8329
  <div class="topbar-title">
8122
8330
  <h2 class="heading">${this.orderConfirmed ? "Takk!" : this.heading}</h2>
8123
8331
  ${this.renderTopbarSponsor()}
8124
8332
  </div>
8125
- <button class="close" @click=${this.close} aria-label="Lukk">×</button>
8333
+ <button class="close" data-vio-cta="close" @click=${this.close} aria-label="Lukk">×</button>
8126
8334
  </div>
8127
8335
 
8128
8336
  <div class="body">
@@ -8219,7 +8427,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
8219
8427
  return html`
8220
8428
  <section class="section provider-receipt">
8221
8429
  <slot name=${slot}></slot>
8222
- <button class="confirm-close" @click=${this.close}>Lukk</button>
8430
+ <button class="confirm-close" data-vio-cta="close" @click=${this.close}>Lukk</button>
8223
8431
  </section>
8224
8432
  `;
8225
8433
  }
@@ -8315,7 +8523,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
8315
8523
  </div>
8316
8524
  </div>
8317
8525
  ` : ""}
8318
- <button class="confirm-close" @click=${this.close}>Fortsett å handle</button>
8526
+ <button class="confirm-close" data-vio-cta="close" @click=${this.close}>Fortsett å handle</button>
8319
8527
  </section>
8320
8528
  `;
8321
8529
  }
@@ -8901,6 +9109,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
8901
9109
  class="payment-btn primary complete-cta"
8902
9110
  ?disabled=${!ready}
8903
9111
  title=${!this.isAddressValid ? "Vennligst fyll ut leveringsadresse" : !this.hasSelectedShipping ? "Vennligst velg en fraktmetode" : ""}
9112
+ data-vio-cta="pay_adyen"
8904
9113
  @click=${() => {
8905
9114
  this.adyenRequested = true;
8906
9115
  }}
@@ -9071,6 +9280,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9071
9280
  class="payment-btn primary complete-cta"
9072
9281
  ?disabled=${!ready}
9073
9282
  title=${!this.isAddressValid ? "Vennligst fyll ut leveringsadresse" : !this.hasSelectedShipping ? "Vennligst velg en fraktmetode" : ""}
9283
+ data-vio-cta="pay_stripe"
9074
9284
  @click=${() => {
9075
9285
  this.stripeRequested = true;
9076
9286
  }}
@@ -9083,6 +9293,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9083
9293
  <button
9084
9294
  class="payment-btn primary complete-cta"
9085
9295
  ?disabled=${this.stripePaying || !this.stripeReady}
9296
+ data-vio-cta="pay_stripe_confirm"
9086
9297
  @click=${() => void this.onStripePay()}
9087
9298
  >
9088
9299
  ${this.stripePaying ? "Betaler\u2026" : `Betal ${this.payTotalLabel()}`}
@@ -9149,6 +9360,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9149
9360
  <div class="klarna-widget" id="vio-klarna-payments-container"></div>
9150
9361
  <button
9151
9362
  class="payment-btn primary complete-cta"
9363
+ data-vio-cta="pay_klarna"
9152
9364
  @click=${() => void this.onKlarnaAuthorize()}
9153
9365
  ?disabled=${this.klarnaAuthorizing || !this.klarnaHandle || this.klarnaMounting || !this.express && (!this.isAddressValid || !this.hasSelectedShipping)}
9154
9366
  >
@@ -9365,6 +9577,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9365
9577
  ${method === "stripe" && this.stripeMode !== "native" ? html`
9366
9578
  <button
9367
9579
  class="payment-btn primary complete-cta"
9580
+ data-vio-cta="pay_stripe"
9368
9581
  @click=${() => void this.onPay("stripe")}
9369
9582
  ?disabled=${this.stripeLoading || !this.cartPayable || !this.isAddressValid || !this.hasSelectedShipping}
9370
9583
  title=${!this.isAddressValid ? "Vennligst fyll ut leveringsadresse" : !this.hasSelectedShipping ? "Vennligst velg en fraktmetode" : ""}
@@ -9375,6 +9588,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9375
9588
  ${method === "vipps" ? html`
9376
9589
  <button
9377
9590
  class="payment-btn primary complete-cta"
9591
+ data-vio-cta="pay_vipps"
9378
9592
  @click=${() => void this.onPay("vipps")}
9379
9593
  ?disabled=${this.vippsLoading || !this.cartPayable || !this.isAddressValid || !this.hasSelectedShipping}
9380
9594
  title=${!this.isAddressValid ? "Vennligst fyll ut leveringsadresse" : !this.hasSelectedShipping ? "Vennligst velg en fraktmetode" : ""}
@@ -9385,6 +9599,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9385
9599
  ${method === "apple-pay" ? html`
9386
9600
  <button
9387
9601
  class="payment-btn primary complete-cta"
9602
+ data-vio-cta="pay_apple_pay"
9388
9603
  @click=${() => void this.onPay("apple-pay")}
9389
9604
  ?disabled=${this.applePayInProgress || !this.cartPayable || !this.isAddressValid || !this.hasSelectedShipping}
9390
9605
  title=${!this.isAddressValid ? "Vennligst fyll ut leveringsadresse" : !this.hasSelectedShipping ? "Vennligst velg en fraktmetode" : ""}
@@ -9395,6 +9610,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9395
9610
  ${showCompleteCta && method !== "stripe" && method !== "vipps" ? html`
9396
9611
  <button
9397
9612
  class="payment-btn primary complete-cta"
9613
+ data-vio-cta=${`pay_${ctaMethod(method)}`}
9398
9614
  @click=${this.onCompleteOrder}
9399
9615
  ?disabled=${!this.cartPayable || !this.isAddressValid || !this.hasSelectedShipping}
9400
9616
  title=${!this.isAddressValid ? "Vennligst fyll ut leveringsadresse" : !this.hasSelectedShipping ? "Vennligst velg en fraktmetode" : ""}
@@ -9423,6 +9639,8 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9423
9639
  ${this.methodEnabled("apple-pay") && this.applePayAvailable && !this.stripeOwnsWallets() ? html`
9424
9640
  <button
9425
9641
  class="payment-btn primary"
9642
+ data-vio-cta="select_apple_pay"
9643
+ data-vio-cta-label="Apple Pay"
9426
9644
  @click=${() => this.onPay("apple-pay")}
9427
9645
  ?disabled=${this.applePayInProgress}
9428
9646
  >
@@ -9432,6 +9650,8 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9432
9650
  ${this.methodEnabled("stripe") ? html`
9433
9651
  <button
9434
9652
  class="payment-btn"
9653
+ data-vio-cta="select_stripe"
9654
+ data-vio-cta-label="Stripe"
9435
9655
  @click=${() => this.onPay("stripe")}
9436
9656
  ?disabled=${this.stripeLoading}
9437
9657
  >
@@ -9439,37 +9659,37 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9439
9659
  </button>
9440
9660
  ` : ""}
9441
9661
  ${this.methodEnabled("klarna") && this.klarnaAvailable ? html`
9442
- <button class="payment-btn" @click=${() => this.onPay("klarna")}>
9662
+ <button class="payment-btn" data-vio-cta="select_klarna" data-vio-cta-label="Klarna" @click=${() => this.onPay("klarna")}>
9443
9663
  Klarna
9444
9664
  </button>
9445
9665
  ` : ""}
9446
9666
  ${this.methodEnabled("kustom") ? html`
9447
- <button class="payment-btn" @click=${() => this.onPay("kustom")}>
9667
+ <button class="payment-btn" data-vio-cta="select_kustom" data-vio-cta-label="Kustom" @click=${() => this.onPay("kustom")}>
9448
9668
  <span style="font-weight:800;font-size:16px;letter-spacing:-0.01em">Kustom</span>
9449
9669
  </button>
9450
9670
  ` : ""}
9451
9671
  ${this.methodEnabled("qliro") ? html`
9452
- <button class="payment-btn" @click=${() => this.onPay("qliro")}>
9672
+ <button class="payment-btn" data-vio-cta="select_qliro" data-vio-cta-label="Qliro" @click=${() => this.onPay("qliro")}>
9453
9673
  <span style="font-weight:800;font-size:16px;letter-spacing:-0.01em">Qliro</span>
9454
9674
  </button>
9455
9675
  ` : ""}
9456
9676
  ${this.methodEnabled("walley") ? html`
9457
- <button class="payment-btn" @click=${() => this.onPay("walley")}>
9677
+ <button class="payment-btn" data-vio-cta="select_walley" data-vio-cta-label="Walley" @click=${() => this.onPay("walley")}>
9458
9678
  <span style="font-weight:800;font-size:16px;letter-spacing:-0.01em">Walley</span>
9459
9679
  </button>
9460
9680
  ` : ""}
9461
9681
  ${this.methodEnabled("nexi") ? html`
9462
- <button class="payment-btn" @click=${() => this.onPay("nexi")}>
9682
+ <button class="payment-btn" data-vio-cta="select_nexi" data-vio-cta-label="Nexi" @click=${() => this.onPay("nexi")}>
9463
9683
  <span style="font-weight:800;font-size:16px;letter-spacing:-0.01em">Nexi</span>
9464
9684
  </button>
9465
9685
  ` : ""}
9466
9686
  ${this.methodEnabled("adyen") ? html`
9467
- <button class="payment-btn" @click=${() => this.onPay("adyen")}>
9687
+ <button class="payment-btn" data-vio-cta="select_adyen" @click=${() => this.onPay("adyen")}>
9468
9688
  <span style="font-weight:700;font-size:15px;letter-spacing:-0.01em">${this.methodLabel("adyen")}</span>
9469
9689
  </button>
9470
9690
  ` : ""}
9471
9691
  ${this.methodEnabled("vipps") ? html`
9472
- <button class="payment-btn" @click=${() => this.onPay("vipps")} aria-label="Vipps">
9692
+ <button class="payment-btn" data-vio-cta="select_vipps" @click=${() => this.onPay("vipps")} aria-label="Vipps">
9473
9693
  ${this.vippsOfficial ? html`<vipps-mobilepay-button
9474
9694
  brand="vipps"
9475
9695
  variant="primary"
@@ -9687,6 +9907,9 @@ __decorateClass([
9687
9907
  state()
9688
9908
  ], _VioCheckout.prototype, "shippingsReadyFor", 2);
9689
9909
  var VioCheckout = _VioCheckout;
9910
+ function ctaMethod(method) {
9911
+ return String(method ?? "unknown").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "") || "unknown";
9912
+ }
9690
9913
 
9691
9914
  // src/ui/elements.ts
9692
9915
  function registerVioElements() {
@@ -9705,5 +9928,5 @@ function registerVioElements() {
9705
9928
  }
9706
9929
 
9707
9930
  export { VioCart, VioCheckout, VioProduct, VioProductCarousel, VioProductDetail, VioTokens, applyVioTheme, registerVioElements };
9708
- //# sourceMappingURL=chunk-DEREQRCM.js.map
9709
- //# sourceMappingURL=chunk-DEREQRCM.js.map
9931
+ //# sourceMappingURL=chunk-LDA7RI43.js.map
9932
+ //# sourceMappingURL=chunk-LDA7RI43.js.map