@vio-live/web-sdk 0.36.0 → 0.37.1

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, Configuration, rememberedCheckoutSponsor, checkoutSponsorOf, AdyenOriginError, normalizeSlotId, autoSlotDisplayName, autoSlotId, sponsorIdentityFrom, normalizeScope, campaignCandidates, ctaText } from './chunk-GUXBD7KR.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
  /**
@@ -6999,7 +7205,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
6999
7205
  this.returningFrom = "kustom";
7000
7206
  this.setOrderSponsor(sponsorId, kustomReturn.checkoutId);
7001
7207
  if (!this.checkoutState) {
7002
- const spIdToUse = sponsorId || [...Vio.cart.getAllCarts().keys()][0] || 0;
7208
+ const spIdToUse = this.returnSponsorOf(sponsorId, kustomReturn.checkoutId);
7003
7209
  if (spIdToUse) {
7004
7210
  try {
7005
7211
  Vio.checkout.open(spIdToUse);
@@ -7017,7 +7223,8 @@ var _VioCheckout = class _VioCheckout extends LitElement {
7017
7223
  try {
7018
7224
  const order = await Vio.checkout.getKustomOrder(
7019
7225
  kustomOrderId,
7020
- this.checkoutState?.sponsorId
7226
+ this.checkoutState?.sponsorId,
7227
+ kustomReturn.checkoutId
7021
7228
  );
7022
7229
  this.verifyingReturn = null;
7023
7230
  if (order?.status === "checkout_complete" && order.html_snippet) {
@@ -7043,7 +7250,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
7043
7250
  this.returningFrom = "qliro";
7044
7251
  this.setOrderSponsor(sponsorId, checkoutId);
7045
7252
  if (!this.checkoutState) {
7046
- const spIdToUse = sponsorId || [...Vio.cart.getAllCarts().keys()][0] || 0;
7253
+ const spIdToUse = this.returnSponsorOf(sponsorId, checkoutId);
7047
7254
  if (spIdToUse) {
7048
7255
  try {
7049
7256
  Vio.checkout.open(spIdToUse);
@@ -7098,7 +7305,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
7098
7305
  this.returningFrom = "walley";
7099
7306
  this.setOrderSponsor(sponsorId, checkoutId);
7100
7307
  if (!this.checkoutState) {
7101
- const spIdToUse = sponsorId || [...Vio.cart.getAllCarts().keys()][0] || 0;
7308
+ const spIdToUse = this.returnSponsorOf(sponsorId, checkoutId);
7102
7309
  if (spIdToUse) {
7103
7310
  try {
7104
7311
  Vio.checkout.open(spIdToUse);
@@ -7157,7 +7364,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
7157
7364
  this.adyenSettled = true;
7158
7365
  this.autoSelectAttempted = true;
7159
7366
  if (!this.checkoutState) {
7160
- const spIdToUse = sponsorId || [...Vio.cart.getAllCarts().keys()][0] || 0;
7367
+ const spIdToUse = this.returnSponsorOf(sponsorId, checkoutId);
7161
7368
  if (spIdToUse) {
7162
7369
  try {
7163
7370
  Vio.checkout.open(spIdToUse);
@@ -7201,7 +7408,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
7201
7408
  }
7202
7409
  if (vioMethod === "vipps" && checkoutId) {
7203
7410
  if (!this.checkoutState) {
7204
- const spIdToUse = sponsorId || [...Vio.cart.getAllCarts().keys()][0] || 0;
7411
+ const spIdToUse = this.returnSponsorOf(sponsorId, checkoutId);
7205
7412
  if (spIdToUse) {
7206
7413
  try {
7207
7414
  Vio.checkout.open(spIdToUse);
@@ -7210,10 +7417,12 @@ var _VioCheckout = class _VioCheckout extends LitElement {
7210
7417
  }
7211
7418
  }
7212
7419
  }
7420
+ const reopening = this.checkoutState ? null : this.reopenOnceInitialized(sponsorId, checkoutId, "vipps");
7213
7421
  this.setOrderSponsor(sponsorId, checkoutId);
7214
7422
  this.open = true;
7215
7423
  this.verifyingReturn = "Bekrefter betalingen med Vipps\u2026";
7216
7424
  const { outcome, sawStatus } = await this.pollVippsStatus(checkoutId, sponsorId);
7425
+ if (reopening) await reopening;
7217
7426
  this.verifyingReturn = null;
7218
7427
  this.applyReturnOutcome(outcome, sawStatus, vioMethod, sponsorId, checkoutId);
7219
7428
  this.cleanReturnQueryParams(["vio_payment", "vio_method", "vio_sponsor", "checkout_id"]);
@@ -7288,6 +7497,8 @@ var _VioCheckout = class _VioCheckout extends LitElement {
7288
7497
  }
7289
7498
  }
7290
7499
  disconnectedCallback() {
7500
+ this.stopCtaClicks?.();
7501
+ this.stopCtaClicks = null;
7291
7502
  Vio.checkout.removeEventListener("change", this.boundOnCheckoutChange);
7292
7503
  Vio.checkout.removeEventListener("payment-complete", this.boundOnPaymentComplete);
7293
7504
  Vio.checkout.removeEventListener("payment-error", this.boundOnPaymentError);
@@ -8108,7 +8319,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
8108
8319
  }
8109
8320
  render() {
8110
8321
  return html`
8111
- <div class="backdrop" @click=${this.close}></div>
8322
+ <div class="backdrop" data-vio-cta="close" data-vio-cta-label="" @click=${this.close}></div>
8112
8323
  <div
8113
8324
  class="modal ${this.express ? "as-side" : this.orderConfirmed ? "as-confirm" : ""}"
8114
8325
  role="dialog"
@@ -8116,13 +8327,13 @@ var _VioCheckout = class _VioCheckout extends LitElement {
8116
8327
  aria-label=${this.heading}
8117
8328
  tabindex="-1"
8118
8329
  >
8119
- <div class="handle" @click=${this.close} aria-hidden="true"></div>
8330
+ <div class="handle" data-vio-cta="close" data-vio-cta-label="" @click=${this.close} aria-hidden="true"></div>
8120
8331
  <div class="topbar">
8121
8332
  <div class="topbar-title">
8122
8333
  <h2 class="heading">${this.orderConfirmed ? "Takk!" : this.heading}</h2>
8123
8334
  ${this.renderTopbarSponsor()}
8124
8335
  </div>
8125
- <button class="close" @click=${this.close} aria-label="Lukk">×</button>
8336
+ <button class="close" data-vio-cta="close" @click=${this.close} aria-label="Lukk">×</button>
8126
8337
  </div>
8127
8338
 
8128
8339
  <div class="body">
@@ -8131,14 +8342,55 @@ var _VioCheckout = class _VioCheckout extends LitElement {
8131
8342
  </div>
8132
8343
  `;
8133
8344
  }
8345
+ static {
8346
+ /**
8347
+ * Remember whose order this is and how it is named right now, before the
8348
+ * cart that names it is cleared. Whose: the sponsor this tab remembered for
8349
+ * the checkout when it was created (exact for that checkout id), else the
8350
+ * one given (the return URL's `vio_sponsor`, the state it was paid in),
8351
+ * else the open state's — a return without `vio_sponsor` (Qliro, Walley)
8352
+ * re-opens the state with whichever cart comes first, which is a guess.
8353
+ */
8354
+ /**
8355
+ * The sponsor to reopen the checkout with on a provider's return: the one
8356
+ * the URL names, else the one this tab remembered for that checkout (a
8357
+ * return URL need not name it — Kustom's never does), else the first cart.
8358
+ * The first cart alone is a guess: with two brands' carts on the page it is
8359
+ * the wrong one, and with the cart already completed by the order there is
8360
+ * none — every read after it then goes out with the wrong key.
8361
+ */
8362
+ /** How long a return waits for `Vio.init()` to reopen the checkout on its cart. */
8363
+ this.RETURN_INIT_WAIT_MS = 1e4;
8364
+ }
8134
8365
  /**
8135
- * Remember whose order this is and how it is named right now, before the
8136
- * cart that names it is cleared. Whose: the sponsor this tab remembered for
8137
- * the checkout when it was created (exact for that checkout id), else the
8138
- * one given (the return URL's `vio_sponsor`, the state it was paid in),
8139
- * else the open state's — a return without `vio_sponsor` (Qliro, Walley)
8140
- * re-opens the state with whichever cart comes first, which is a guess.
8366
+ * Reopen the checkout of a provider's return once `Vio.init()` is there.
8367
+ * A page may mount the checkout before it calls `Vio.init()` — Vev does:
8368
+ * the overlay renders with the page, the key comes from its config block a
8369
+ * moment later — and then the checkout reads the return first. Each
8370
+ * connection keeps its own carts (0.33), so before the init the cart is not
8371
+ * there: `open()` throws, the checkout has no state, and nothing asks for
8372
+ * the payment methods. A Vipps payment cancelled on Alan's Vev page
8373
+ * (2026-10-29) came back to «Betalingen ble avbrutt…» over a
8374
+ * «Henter betalingsmåter…» that never ended, with no cart to pay again.
8375
+ * Never throws; does nothing when a state is already there.
8141
8376
  */
8377
+ async reopenOnceInitialized(sponsorId, checkoutId, method) {
8378
+ try {
8379
+ if (!Configuration.isInitialized && !await Configuration.whenReady(_VioCheckout.RETURN_INIT_WAIT_MS)) return;
8380
+ if (this.checkoutState) return;
8381
+ const spId = this.returnSponsorOf(sponsorId, checkoutId);
8382
+ if (!spId) return;
8383
+ Vio.checkout.open(spId);
8384
+ Vio.checkout.selectPaymentMethod(method);
8385
+ } catch {
8386
+ }
8387
+ }
8388
+ returnSponsorOf(sponsorId, checkoutId) {
8389
+ if (sponsorId > 0) return sponsorId;
8390
+ const remembered = rememberedCheckoutSponsor(checkoutId || void 0)?.sponsorId;
8391
+ if (remembered) return remembered;
8392
+ return [...Vio.cart.getAllCarts().keys()][0] || 0;
8393
+ }
8142
8394
  setOrderSponsor(sponsorId, checkoutId) {
8143
8395
  try {
8144
8396
  const checkout = checkoutId || void 0;
@@ -8219,7 +8471,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
8219
8471
  return html`
8220
8472
  <section class="section provider-receipt">
8221
8473
  <slot name=${slot}></slot>
8222
- <button class="confirm-close" @click=${this.close}>Lukk</button>
8474
+ <button class="confirm-close" data-vio-cta="close" @click=${this.close}>Lukk</button>
8223
8475
  </section>
8224
8476
  `;
8225
8477
  }
@@ -8315,7 +8567,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
8315
8567
  </div>
8316
8568
  </div>
8317
8569
  ` : ""}
8318
- <button class="confirm-close" @click=${this.close}>Fortsett å handle</button>
8570
+ <button class="confirm-close" data-vio-cta="close" @click=${this.close}>Fortsett å handle</button>
8319
8571
  </section>
8320
8572
  `;
8321
8573
  }
@@ -8901,6 +9153,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
8901
9153
  class="payment-btn primary complete-cta"
8902
9154
  ?disabled=${!ready}
8903
9155
  title=${!this.isAddressValid ? "Vennligst fyll ut leveringsadresse" : !this.hasSelectedShipping ? "Vennligst velg en fraktmetode" : ""}
9156
+ data-vio-cta="pay_adyen"
8904
9157
  @click=${() => {
8905
9158
  this.adyenRequested = true;
8906
9159
  }}
@@ -9071,6 +9324,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9071
9324
  class="payment-btn primary complete-cta"
9072
9325
  ?disabled=${!ready}
9073
9326
  title=${!this.isAddressValid ? "Vennligst fyll ut leveringsadresse" : !this.hasSelectedShipping ? "Vennligst velg en fraktmetode" : ""}
9327
+ data-vio-cta="pay_stripe"
9074
9328
  @click=${() => {
9075
9329
  this.stripeRequested = true;
9076
9330
  }}
@@ -9083,6 +9337,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9083
9337
  <button
9084
9338
  class="payment-btn primary complete-cta"
9085
9339
  ?disabled=${this.stripePaying || !this.stripeReady}
9340
+ data-vio-cta="pay_stripe_confirm"
9086
9341
  @click=${() => void this.onStripePay()}
9087
9342
  >
9088
9343
  ${this.stripePaying ? "Betaler\u2026" : `Betal ${this.payTotalLabel()}`}
@@ -9149,6 +9404,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9149
9404
  <div class="klarna-widget" id="vio-klarna-payments-container"></div>
9150
9405
  <button
9151
9406
  class="payment-btn primary complete-cta"
9407
+ data-vio-cta="pay_klarna"
9152
9408
  @click=${() => void this.onKlarnaAuthorize()}
9153
9409
  ?disabled=${this.klarnaAuthorizing || !this.klarnaHandle || this.klarnaMounting || !this.express && (!this.isAddressValid || !this.hasSelectedShipping)}
9154
9410
  >
@@ -9365,6 +9621,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9365
9621
  ${method === "stripe" && this.stripeMode !== "native" ? html`
9366
9622
  <button
9367
9623
  class="payment-btn primary complete-cta"
9624
+ data-vio-cta="pay_stripe"
9368
9625
  @click=${() => void this.onPay("stripe")}
9369
9626
  ?disabled=${this.stripeLoading || !this.cartPayable || !this.isAddressValid || !this.hasSelectedShipping}
9370
9627
  title=${!this.isAddressValid ? "Vennligst fyll ut leveringsadresse" : !this.hasSelectedShipping ? "Vennligst velg en fraktmetode" : ""}
@@ -9375,6 +9632,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9375
9632
  ${method === "vipps" ? html`
9376
9633
  <button
9377
9634
  class="payment-btn primary complete-cta"
9635
+ data-vio-cta="pay_vipps"
9378
9636
  @click=${() => void this.onPay("vipps")}
9379
9637
  ?disabled=${this.vippsLoading || !this.cartPayable || !this.isAddressValid || !this.hasSelectedShipping}
9380
9638
  title=${!this.isAddressValid ? "Vennligst fyll ut leveringsadresse" : !this.hasSelectedShipping ? "Vennligst velg en fraktmetode" : ""}
@@ -9385,6 +9643,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9385
9643
  ${method === "apple-pay" ? html`
9386
9644
  <button
9387
9645
  class="payment-btn primary complete-cta"
9646
+ data-vio-cta="pay_apple_pay"
9388
9647
  @click=${() => void this.onPay("apple-pay")}
9389
9648
  ?disabled=${this.applePayInProgress || !this.cartPayable || !this.isAddressValid || !this.hasSelectedShipping}
9390
9649
  title=${!this.isAddressValid ? "Vennligst fyll ut leveringsadresse" : !this.hasSelectedShipping ? "Vennligst velg en fraktmetode" : ""}
@@ -9395,6 +9654,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9395
9654
  ${showCompleteCta && method !== "stripe" && method !== "vipps" ? html`
9396
9655
  <button
9397
9656
  class="payment-btn primary complete-cta"
9657
+ data-vio-cta=${`pay_${ctaMethod(method)}`}
9398
9658
  @click=${this.onCompleteOrder}
9399
9659
  ?disabled=${!this.cartPayable || !this.isAddressValid || !this.hasSelectedShipping}
9400
9660
  title=${!this.isAddressValid ? "Vennligst fyll ut leveringsadresse" : !this.hasSelectedShipping ? "Vennligst velg en fraktmetode" : ""}
@@ -9411,7 +9671,14 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9411
9671
  Vennligst velg en fraktmetode for å fullføre betalingen
9412
9672
  </div>
9413
9673
  ` : ""}
9414
- ` : !this.paymentMethodsResolved ? html`
9674
+ ` : !this.checkoutState ? (
9675
+ // Nothing to ask the methods for (loadAvailablePaymentMethods
9676
+ // needs a checkout): the spinner would never end.
9677
+ html`
9678
+ <h3 class="section-heading">Velg betalingsmåte</h3>
9679
+ <p class="payment-loading">${EMPTY_CART_MESSAGE2}</p>
9680
+ `
9681
+ ) : !this.paymentMethodsResolved ? html`
9415
9682
  <h3 class="section-heading">Velg betalingsmåte</h3>
9416
9683
  <div class="payment-loading">
9417
9684
  <span class="payment-spinner" aria-hidden="true"></span>
@@ -9423,6 +9690,8 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9423
9690
  ${this.methodEnabled("apple-pay") && this.applePayAvailable && !this.stripeOwnsWallets() ? html`
9424
9691
  <button
9425
9692
  class="payment-btn primary"
9693
+ data-vio-cta="select_apple_pay"
9694
+ data-vio-cta-label="Apple Pay"
9426
9695
  @click=${() => this.onPay("apple-pay")}
9427
9696
  ?disabled=${this.applePayInProgress}
9428
9697
  >
@@ -9432,6 +9701,8 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9432
9701
  ${this.methodEnabled("stripe") ? html`
9433
9702
  <button
9434
9703
  class="payment-btn"
9704
+ data-vio-cta="select_stripe"
9705
+ data-vio-cta-label="Stripe"
9435
9706
  @click=${() => this.onPay("stripe")}
9436
9707
  ?disabled=${this.stripeLoading}
9437
9708
  >
@@ -9439,37 +9710,37 @@ var _VioCheckout = class _VioCheckout extends LitElement {
9439
9710
  </button>
9440
9711
  ` : ""}
9441
9712
  ${this.methodEnabled("klarna") && this.klarnaAvailable ? html`
9442
- <button class="payment-btn" @click=${() => this.onPay("klarna")}>
9713
+ <button class="payment-btn" data-vio-cta="select_klarna" data-vio-cta-label="Klarna" @click=${() => this.onPay("klarna")}>
9443
9714
  Klarna
9444
9715
  </button>
9445
9716
  ` : ""}
9446
9717
  ${this.methodEnabled("kustom") ? html`
9447
- <button class="payment-btn" @click=${() => this.onPay("kustom")}>
9718
+ <button class="payment-btn" data-vio-cta="select_kustom" data-vio-cta-label="Kustom" @click=${() => this.onPay("kustom")}>
9448
9719
  <span style="font-weight:800;font-size:16px;letter-spacing:-0.01em">Kustom</span>
9449
9720
  </button>
9450
9721
  ` : ""}
9451
9722
  ${this.methodEnabled("qliro") ? html`
9452
- <button class="payment-btn" @click=${() => this.onPay("qliro")}>
9723
+ <button class="payment-btn" data-vio-cta="select_qliro" data-vio-cta-label="Qliro" @click=${() => this.onPay("qliro")}>
9453
9724
  <span style="font-weight:800;font-size:16px;letter-spacing:-0.01em">Qliro</span>
9454
9725
  </button>
9455
9726
  ` : ""}
9456
9727
  ${this.methodEnabled("walley") ? html`
9457
- <button class="payment-btn" @click=${() => this.onPay("walley")}>
9728
+ <button class="payment-btn" data-vio-cta="select_walley" data-vio-cta-label="Walley" @click=${() => this.onPay("walley")}>
9458
9729
  <span style="font-weight:800;font-size:16px;letter-spacing:-0.01em">Walley</span>
9459
9730
  </button>
9460
9731
  ` : ""}
9461
9732
  ${this.methodEnabled("nexi") ? html`
9462
- <button class="payment-btn" @click=${() => this.onPay("nexi")}>
9733
+ <button class="payment-btn" data-vio-cta="select_nexi" data-vio-cta-label="Nexi" @click=${() => this.onPay("nexi")}>
9463
9734
  <span style="font-weight:800;font-size:16px;letter-spacing:-0.01em">Nexi</span>
9464
9735
  </button>
9465
9736
  ` : ""}
9466
9737
  ${this.methodEnabled("adyen") ? html`
9467
- <button class="payment-btn" @click=${() => this.onPay("adyen")}>
9738
+ <button class="payment-btn" data-vio-cta="select_adyen" @click=${() => this.onPay("adyen")}>
9468
9739
  <span style="font-weight:700;font-size:15px;letter-spacing:-0.01em">${this.methodLabel("adyen")}</span>
9469
9740
  </button>
9470
9741
  ` : ""}
9471
9742
  ${this.methodEnabled("vipps") ? html`
9472
- <button class="payment-btn" @click=${() => this.onPay("vipps")} aria-label="Vipps">
9743
+ <button class="payment-btn" data-vio-cta="select_vipps" @click=${() => this.onPay("vipps")} aria-label="Vipps">
9473
9744
  ${this.vippsOfficial ? html`<vipps-mobilepay-button
9474
9745
  brand="vipps"
9475
9746
  variant="primary"
@@ -9687,6 +9958,9 @@ __decorateClass([
9687
9958
  state()
9688
9959
  ], _VioCheckout.prototype, "shippingsReadyFor", 2);
9689
9960
  var VioCheckout = _VioCheckout;
9961
+ function ctaMethod(method) {
9962
+ return String(method ?? "unknown").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "") || "unknown";
9963
+ }
9690
9964
 
9691
9965
  // src/ui/elements.ts
9692
9966
  function registerVioElements() {
@@ -9705,5 +9979,5 @@ function registerVioElements() {
9705
9979
  }
9706
9980
 
9707
9981
  export { VioCart, VioCheckout, VioProduct, VioProductCarousel, VioProductDetail, VioTokens, applyVioTheme, registerVioElements };
9708
- //# sourceMappingURL=chunk-DEREQRCM.js.map
9709
- //# sourceMappingURL=chunk-DEREQRCM.js.map
9982
+ //# sourceMappingURL=chunk-2OHYZI3P.js.map
9983
+ //# sourceMappingURL=chunk-2OHYZI3P.js.map