@mparticle/web-sdk 3.24.0 → 3.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mparticle.js CHANGED
@@ -204,7 +204,7 @@ var mParticle = (function () {
204
204
  Base64: Base64$1
205
205
  };
206
206
 
207
- var version = "3.24.0";
207
+ var version = "3.26.0";
208
208
 
209
209
  var Constants = {
210
210
  sdkVersion: version,
@@ -379,7 +379,8 @@ var mParticle = (function () {
379
379
  CaptureIntegrationSpecificIdsV2: 'captureIntegrationSpecificIds.V2',
380
380
  AstBackgroundEvents: 'astBackgroundEvents',
381
381
  AutoLogPageView: 'autoLogPageView',
382
- AutoButtonTracking: 'autoButtonTracking'
382
+ AutoButtonTracking: 'autoButtonTracking',
383
+ AutoLinkTracking: 'autoLinkTracking'
383
384
  },
384
385
  DefaultInstance: 'default_instance',
385
386
  CCPAPurpose: 'data_sale_opt_out',
@@ -5349,9 +5350,13 @@ var mParticle = (function () {
5349
5350
  if (requiresConsent && mpidIsNotInCookies) {
5350
5351
  return;
5351
5352
  }
5352
- // For Rokt, block cookie sync when noTargeting privacy flag is true
5353
- if (moduleId === PARTNER_MODULE_IDS.Rokt && mpInstance._CookieConsentManager.getNoTargeting()) {
5354
- return;
5353
+ // For Rokt, block cookie sync under the noTargeting or doNotShareOrSell privacy flag,
5354
+ // or when the browser sends Global Privacy Control
5355
+ if (moduleId === PARTNER_MODULE_IDS.Rokt) {
5356
+ var nav = typeof navigator === 'undefined' ? undefined : navigator;
5357
+ if (mpInstance._CookieConsentManager.getNoTargeting() || mpInstance._CookieConsentManager.getDoNotShareOrSell() || !!nav && nav.globalPrivacyControl === true) {
5358
+ return;
5359
+ }
5355
5360
  }
5356
5361
  var isEnabledForUserConsent = mpInstance._Consent.isEnabledForUserConsent;
5357
5362
  if (!isEnabledForUserConsent(filteringConsentRuleValues, mpInstance.Identity.getCurrentUser())) {
@@ -6545,7 +6550,8 @@ var mParticle = (function () {
6545
6550
  CaptureIntegrationSpecificIdsV2 = _a.CaptureIntegrationSpecificIdsV2,
6546
6551
  AstBackgroundEvents = _a.AstBackgroundEvents,
6547
6552
  AutoLogPageView = _a.AutoLogPageView,
6548
- AutoButtonTracking = _a.AutoButtonTracking;
6553
+ AutoButtonTracking = _a.AutoButtonTracking,
6554
+ AutoLinkTracking = _a.AutoLinkTracking;
6549
6555
  if (!config.flags) {
6550
6556
  return {};
6551
6557
  }
@@ -6563,6 +6569,7 @@ var mParticle = (function () {
6563
6569
  flags[AstBackgroundEvents] = config.flags[AstBackgroundEvents] === 'True';
6564
6570
  flags[AutoLogPageView] = config.flags[AutoLogPageView] === 'True';
6565
6571
  flags[AutoButtonTracking] = config.flags[AutoButtonTracking] === 'True';
6572
+ flags[AutoLinkTracking] = config.flags[AutoLinkTracking] === 'True';
6566
6573
  return flags;
6567
6574
  }
6568
6575
  function processBaseUrls(config, flags, apiKey) {
@@ -10874,8 +10881,9 @@ var mParticle = (function () {
10874
10881
  }
10875
10882
 
10876
10883
  var PASSBACK_CONVERSION_TRACKING_ID = 'passbackconversiontrackingid';
10877
- // One signal per kind (commit, wallet, checkout_step, frame and cart), so a new kind never evicts another.
10878
- var CHECKOUT_INTENT_BUFFER_LIMIT = 5;
10884
+ // One signal per kind (commit, wallet, checkout_step, frame and cart), with an
10885
+ // add-to-cart click apart from a cart open, so a new one never evicts another.
10886
+ var CHECKOUT_INTENT_BUFFER_LIMIT = 6;
10879
10887
  var CHECKOUT_INTENT_MAX_AGE_MS = 30000;
10880
10888
  var ON_SHOPPABLE_ADS_READY_METHOD = 'onShoppableAdsReady';
10881
10889
  // The purpose of this class is to create a link between the Core mParticle SDK and the
@@ -11035,21 +11043,27 @@ var mParticle = (function () {
11035
11043
  RoktManager.prototype.setAutoButtonClicksForwarded = function (forwarded) {
11036
11044
  this.autoButtonClicksForwarded = forwarded;
11037
11045
  };
11046
+ // noTargeting (which noDeviceId implies), doNotShareOrSell or Global Privacy
11047
+ // Control. Unlike noFunctional, these also stop auto button and link clicks
11048
+ // from being logged.
11049
+ RoktManager.prototype.hasTargetingOptOut = function () {
11050
+ var options = this.launcherOptions || {};
11051
+ if (options.noTargeting || options.doNotShareOrSell) {
11052
+ return true;
11053
+ }
11054
+ var nav = typeof navigator === 'undefined' ? undefined : navigator;
11055
+ return !!nav && nav.globalPrivacyControl === true;
11056
+ };
11038
11057
  // Checkout intent is off unless the flag is on, and under opt-out, any Rokt
11039
11058
  // privacy launcher option, Global Privacy Control, or a Rokt connection that
11040
11059
  // does not receive auto button clicks.
11041
11060
  RoktManager.prototype.isCheckoutIntentSuppressed = function () {
11042
- var _a, _b;
11061
+ var _a, _b, _c;
11043
11062
  var flags = (_b = (_a = this.store) === null || _a === void 0 ? void 0 : _a.SDKConfig) === null || _b === void 0 ? void 0 : _b.flags;
11044
11063
  if (!flags || flags[Constants.FeatureFlags.AutoButtonTracking] !== true || !this.store.isEnabled || !this.autoButtonClicksForwarded) {
11045
11064
  return true;
11046
11065
  }
11047
- var options = this.launcherOptions || {};
11048
- if (options.noFunctional || options.noTargeting || options.doNotShareOrSell) {
11049
- return true;
11050
- }
11051
- var nav = typeof navigator === 'undefined' ? undefined : navigator;
11052
- return !!nav && nav.globalPrivacyControl === true;
11066
+ return !!((_c = this.launcherOptions) === null || _c === void 0 ? void 0 : _c.noFunctional) || this.hasTargetingOptOut();
11053
11067
  };
11054
11068
  // True when the kit can wait for the shopper's confirm click: signals are not
11055
11069
  // suppressed and the browser exposes the composed path the detector reads.
@@ -11072,8 +11086,10 @@ var mParticle = (function () {
11072
11086
  }
11073
11087
  var kit = this.kit;
11074
11088
  if (!kit) {
11089
+ // One per kind, with an add-to-cart click kept apart from a
11090
+ // click that opens the cart.
11075
11091
  this.pendingCheckoutIntents = this.pendingCheckoutIntents.filter(function (pending) {
11076
- return pending.signal.kind !== signal.kind;
11092
+ return pending.signal.kind !== signal.kind || !!pending.signal.adds !== !!signal.adds;
11077
11093
  }).concat({
11078
11094
  signal: signal,
11079
11095
  pathname: pathname
@@ -11091,6 +11107,23 @@ var mParticle = (function () {
11091
11107
  RoktManager.prototype.discardCheckoutIntents = function () {
11092
11108
  this.pendingCheckoutIntents = [];
11093
11109
  };
11110
+ // Under the same gates as checkout intent. A pick made before a kit
11111
+ // attaches is not kept: the shopper is still choosing, and the next pick
11112
+ // replaces it.
11113
+ RoktManager.prototype.notifyPaymentPick = function (signal) {
11114
+ var _a;
11115
+ if (this.isCheckoutIntentSuppressed()) {
11116
+ return;
11117
+ }
11118
+ var kit = this.kit;
11119
+ try {
11120
+ if (kit && isFunction(kit.onPaymentPick)) {
11121
+ kit.onPaymentPick(signal);
11122
+ }
11123
+ } catch (e) {
11124
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.error("RoktManager: Error in onPaymentPick: ".concat(getErrorMessage(e)));
11125
+ }
11126
+ };
11094
11127
  // Replays recent buffered signals raised on the current page, oldest first.
11095
11128
  RoktManager.prototype.flushCheckoutIntents = function () {
11096
11129
  var _this = this;
@@ -11646,12 +11679,12 @@ var mParticle = (function () {
11646
11679
  }();
11647
11680
 
11648
11681
  /**
11649
- * CookieConsentManager handles storage and access of consent flags (noFunctional, noTargeting)
11650
- * that are passed via launcherOptions during SDK initialization.
11682
+ * CookieConsentManager handles storage and access of consent flags (noFunctional, noTargeting,
11683
+ * doNotShareOrSell) that are passed via launcherOptions during SDK initialization.
11651
11684
  *
11652
11685
  * These flags allow Rokt integration to respect user privacy choices.
11653
11686
  *
11654
- * Default behavior: Both flags default to false, meaning all features are allowed
11687
+ * Default behavior: All flags default to false, meaning all features are allowed
11655
11688
  * unless explicitly opted out by the user.
11656
11689
  */
11657
11690
  var CookieConsentManager = /** @class */function () {
@@ -11659,7 +11692,8 @@ var mParticle = (function () {
11659
11692
  this.flags = flags;
11660
11693
  this.flags = {
11661
11694
  noFunctional: flags.noFunctional === true,
11662
- noTargeting: flags.noTargeting === true
11695
+ noTargeting: flags.noTargeting === true,
11696
+ doNotShareOrSell: flags.doNotShareOrSell === true
11663
11697
  };
11664
11698
  }
11665
11699
  /**
@@ -11676,6 +11710,13 @@ var mParticle = (function () {
11676
11710
  CookieConsentManager.prototype.getNoFunctional = function () {
11677
11711
  return this.flags.noFunctional;
11678
11712
  };
11713
+ /**
11714
+ * Returns true if the user has opted out of the sale or sharing of their data.
11715
+ * Sharing is allowed when doNotShareOrSell is false (default).
11716
+ */
11717
+ CookieConsentManager.prototype.getDoNotShareOrSell = function () {
11718
+ return this.flags.doNotShareOrSell;
11719
+ };
11679
11720
  CookieConsentManager.prototype.syncNoTargetingAttribute = function (user) {
11680
11721
  if (!user) return;
11681
11722
  if (this.flags.noTargeting) {
@@ -11733,19 +11774,20 @@ var mParticle = (function () {
11733
11774
  var AUTO_BUTTON_ATTRIBUTE = 'is_auto_button_click';
11734
11775
  // Specific enough not to merge with a customer's own 'Button Click' event.
11735
11776
  var BUTTON_CLICK_EVENT_NAME = 'Auto Button Click';
11736
- // One custom event per click, logged like logLink() with the auto marker and the
11737
- // page fields that auto page views carry. No intent: classifying clicks is left
11738
- // to whoever reads the data.
11739
- var buildButtonClickEvent = function buildButtonClickEvent(click, pathname) {
11740
- var _a;
11741
- var data = (_a = {
11777
+ // Marks an automatically logged click on a link that leaves the page.
11778
+ var AUTO_LINK_ATTRIBUTE = 'is_auto_link_click';
11779
+ var LINK_CLICK_EVENT_NAME = 'Auto Link Click';
11780
+ // The attributes both click events carry, with the page fields that auto page
11781
+ // views carry. No intent: classifying clicks is left to whoever reads the data.
11782
+ var clickAttributes = function clickAttributes(click, pathname) {
11783
+ var data = {
11742
11784
  label_source: click.labelSource,
11743
11785
  element: click.element,
11744
11786
  type: click.type,
11745
11787
  path: pathname,
11746
11788
  hostname: window.location.hostname
11747
- }, _a[AUTO_BUTTON_ATTRIBUTE] = true, _a);
11748
- // Optional fields are left out when the button has no safe value for them.
11789
+ };
11790
+ // Optional fields are left out when the control has no safe value for them.
11749
11791
  var optional = {
11750
11792
  label: click.label,
11751
11793
  aria_label: click.ariaLabel,
@@ -11759,8 +11801,8 @@ var mParticle = (function () {
11759
11801
  link_domain: click.linkDomain,
11760
11802
  file_extension: click.fileExtension
11761
11803
  };
11762
- for (var _i = 0, _b = Object.keys(optional); _i < _b.length; _i++) {
11763
- var key = _b[_i];
11804
+ for (var _i = 0, _a = Object.keys(optional); _i < _a.length; _i++) {
11805
+ var key = _a[_i];
11764
11806
  if (optional[key]) {
11765
11807
  data[key] = optional[key];
11766
11808
  }
@@ -11768,6 +11810,12 @@ var mParticle = (function () {
11768
11810
  if (click.checked !== undefined) {
11769
11811
  data.checked = click.checked;
11770
11812
  }
11813
+ return data;
11814
+ };
11815
+ // One custom event per button click, logged like logLink() with the auto marker.
11816
+ var buildButtonClickEvent = function buildButtonClickEvent(click, pathname) {
11817
+ var data = clickAttributes(click, pathname);
11818
+ data[AUTO_BUTTON_ATTRIBUTE] = true;
11771
11819
  return {
11772
11820
  messageType: MessageType$1.PageEvent,
11773
11821
  name: BUTTON_CLICK_EVENT_NAME,
@@ -11775,28 +11823,52 @@ var mParticle = (function () {
11775
11823
  eventType: EventType.Other
11776
11824
  };
11777
11825
  };
11826
+ // One custom event per click on a link that leaves the page. Typed Other, not
11827
+ // Navigation, so no kit reads it as a page change. A plain link to another page
11828
+ // of the site goes without its text, which can name the shopper ("Hi, Jane");
11829
+ // a button or wallet acting as a link keeps its name.
11830
+ var buildLinkClickEvent = function buildLinkClickEvent(click, pathname) {
11831
+ var data = clickAttributes(click.linkType === 'internal' && click.element === 'link' ? __assign(__assign({}, click), {
11832
+ label: undefined,
11833
+ labelSource: 'none',
11834
+ ariaLabel: undefined
11835
+ }) : click, pathname);
11836
+ data[AUTO_LINK_ATTRIBUTE] = true;
11837
+ return {
11838
+ messageType: MessageType$1.PageEvent,
11839
+ name: LINK_CLICK_EVENT_NAME,
11840
+ data: data,
11841
+ eventType: EventType.Other
11842
+ };
11843
+ };
11778
11844
  // Every attribute buildButtonClickEvent can set apart from the marker and the
11779
11845
  // hostname, which is the same on every click on this page. A spec checks the
11780
11846
  // two stay in step.
11781
11847
  var CLICK_ATTRIBUTES = ['label_source', 'element', 'type', 'path', 'label', 'aria_label', 'icon', 'element_id', 'element_name', 'test_id', 'controls', 'form', 'link_type', 'link_domain', 'file_extension', 'checked'];
11782
- // Which check keeps some or all auto button clicks from a kit, or undefined
11783
- // when the kit receives every one. A forwarding rule on an attribute whose
11784
- // value differs between clicks lets some through and not others. Each other
11785
- // check goes through isEventForwarded on its own, so together they decide as
11786
- // it does for each click.
11787
- var getButtonClickBlocker = function getButtonClickBlocker(forwarder, kitBlocker) {
11788
- var _a;
11848
+ // Which check keeps some or all auto button clicks, or auto link clicks with
11849
+ // `link`, from a kit, or undefined when the kit receives every one. A forwarding
11850
+ // rule on an attribute whose value differs between clicks lets some through and
11851
+ // not others. Each other check goes through isEventForwarded on its own, so
11852
+ // together they decide as it does for each click.
11853
+ var getButtonClickBlocker = function getButtonClickBlocker(forwarder, kitBlocker, link) {
11854
+ if (link === void 0) {
11855
+ link = false;
11856
+ }
11789
11857
  var rule = forwarder.filteringEventAttributeValue;
11790
11858
  if (rule && rule.eventAttributeValue && CLICK_ATTRIBUTES.some(function (name) {
11791
11859
  return KitFilterHelper.hashAttributeConditionalForwarding(name) === rule.eventAttributeName;
11792
11860
  })) {
11793
11861
  return 'forwarding rule';
11794
11862
  }
11863
+ var attributes = {
11864
+ hostname: window.location.hostname
11865
+ };
11866
+ attributes[link ? AUTO_LINK_ATTRIBUTE : AUTO_BUTTON_ATTRIBUTE] = true;
11795
11867
  var click = {
11796
- EventName: BUTTON_CLICK_EVENT_NAME,
11868
+ EventName: link ? LINK_CLICK_EVENT_NAME : BUTTON_CLICK_EVENT_NAME,
11797
11869
  EventCategory: EventType.Other,
11798
11870
  EventDataType: MessageType$1.PageEvent,
11799
- EventAttributes: (_a = {}, _a[AUTO_BUTTON_ATTRIBUTE] = true, _a.hostname = window.location.hostname, _a)
11871
+ EventAttributes: attributes
11800
11872
  };
11801
11873
  var checks = [['data plan', {}], ['forwarding rule', {
11802
11874
  filteringEventAttributeValue: rule
@@ -12020,9 +12092,13 @@ var mParticle = (function () {
12020
12092
  return control;
12021
12093
  }
12022
12094
  // Text that may hold what a shopper typed or what the page opted out: form
12023
- // fields, editable regions, and anything under data-mp-no-track.
12024
- function isUnsafeTextSource(element) {
12025
- return element.matches('input, select, textarea, option, optgroup, datalist, ' + EDITABLE) || !!element.querySelector('input, select, textarea, [data-mp-no-track], ' + EDITABLE) || hasComposedAncestor(element, 'select, datalist, textarea, [data-mp-no-track], ' + EDITABLE);
12095
+ // fields, editable regions, and anything under data-mp-no-track. `own` is a
12096
+ // box the element labels, which holds no typing of its own.
12097
+ function isUnsafeTextSource(element, own) {
12098
+ var inside = 'input, select, textarea, [data-mp-no-track], ' + EDITABLE;
12099
+ return element.matches('input, select, textarea, option, optgroup, datalist, ' + EDITABLE) || (own ? Array.from(element.querySelectorAll(inside)).some(function (found) {
12100
+ return found !== own;
12101
+ }) : !!element.querySelector(inside)) || hasComposedAncestor(element, 'select, datalist, textarea, [data-mp-no-track], ' + EDITABLE);
12026
12102
  }
12027
12103
 
12028
12104
  // Masks a button label before it is logged. Button text can carry personal data,
@@ -12363,8 +12439,8 @@ var mParticle = (function () {
12363
12439
  return tag === 'button' || tag === 'input' ? control.type : 'button';
12364
12440
  }
12365
12441
  // Reads the link's own resolved URL parts, never its full href: only the hostname of
12366
- // a link that leaves the site and the extension of a file it downloads travel. Navigation
12367
- // within the site is left to page views, and mailto:, tel: and other schemes are skipped.
12442
+ // a link that leaves the site and the extension of a file it downloads travel.
12443
+ // mailto:, tel: and other schemes give undefined.
12368
12444
  function describeLink(link) {
12369
12445
  var href = (link.getAttribute('href') || '').trim();
12370
12446
  if (!href || href.charAt(0) === '#') {
@@ -12401,7 +12477,14 @@ var mParticle = (function () {
12401
12477
  }
12402
12478
  return link.pathname === window.location.pathname && link.search === window.location.search ? {
12403
12479
  type: 'same_page'
12404
- } : undefined;
12480
+ } : {
12481
+ type: 'internal'
12482
+ };
12483
+ }
12484
+ // Whether a described click is on a link that leaves the page, logged as a link
12485
+ // click rather than a button click.
12486
+ function isLinkClick(click) {
12487
+ return !!click.linkType && click.linkType !== 'same_page';
12405
12488
  }
12406
12489
  // Checkboxes and radios, and the roles that act as them. A role can list
12407
12490
  // fallbacks, so any of its tokens counts.
@@ -12411,6 +12494,9 @@ var mParticle = (function () {
12411
12494
  var box = element instanceof HTMLLabelElement ? element.control : element;
12412
12495
  return box && box.matches(CHOICE) ? box : null;
12413
12496
  }
12497
+ function isRadio(choice) {
12498
+ return choice instanceof HTMLInputElement ? choice.type === 'radio' : !!choice && choice.matches(RADIO_ROLE);
12499
+ }
12414
12500
  // The box a click on this control picks. One the click passed through below
12415
12501
  // the control comes first: querySelector can't reach a slotted box, a box in a
12416
12502
  // shadow root or the box of a label inside the control, and a row can hold
@@ -12429,8 +12515,9 @@ var mParticle = (function () {
12429
12515
  }
12430
12516
  return boxOf(control) || control.querySelector(CHOICE);
12431
12517
  }
12432
- // Describes a clicked control for auto button tracking. A link counts only when page
12433
- // views can't see the click, and carries its link type.
12518
+ // Describes a clicked control for auto button and link tracking. A link carries its
12519
+ // link type, and one to another scheme is skipped. A role="button" anchor carries one
12520
+ // only when it leaves the page; otherwise it stays a plain button.
12434
12521
  function describeButtonClick(control, path) {
12435
12522
  if (path === void 0) {
12436
12523
  path = [];
@@ -12441,6 +12528,11 @@ var mParticle = (function () {
12441
12528
  if (!link) {
12442
12529
  return undefined;
12443
12530
  }
12531
+ } else if (control.matches('a[href]')) {
12532
+ link = describeLink(control);
12533
+ if (link && link.type === 'same_page') {
12534
+ link = undefined;
12535
+ }
12444
12536
  }
12445
12537
  var element = elementKind(control);
12446
12538
  var box = control instanceof HTMLInputElement && (control.type === 'checkbox' || control.type === 'radio') ? control : undefined;
@@ -12454,7 +12546,7 @@ var mParticle = (function () {
12454
12546
  // radio's id, test id and the panel it opens name the option picked, so
12455
12547
  // only the name of its input, the question, goes with it. A wrapper's own
12456
12548
  // name, or a role radio's, can name the option instead.
12457
- var radio = choice instanceof HTMLInputElement ? choice.type === 'radio' : !!choice && choice.matches(RADIO_ROLE);
12549
+ var radio = isRadio(choice);
12458
12550
  var named = !radio ? control : choice instanceof HTMLInputElement ? choice : null;
12459
12551
  var name = choice ? undefined : accessibleName(control);
12460
12552
  var label = name ? maskLabel(name.raw) : undefined;
@@ -12480,6 +12572,54 @@ var mParticle = (function () {
12480
12572
  checked: box ? box.checked : undefined
12481
12573
  };
12482
12574
  }
12575
+ // A question about payment, read from the names its author gave it, so
12576
+ // "checkout[payment_gateway]", "paymentMethod" and "tender_type" all count and
12577
+ // "payee" does not. A radio's input name is its question; its group or
12578
+ // fieldset speaks only for a radio with no name, as a role radio usually is.
12579
+ var PAYMENT_QUESTION = /(?:^| )(?:pay|payment\w*|tenders?|gateways?)(?: |$)/;
12580
+ var QUESTION_GROUP = '[role="radiogroup"], fieldset';
12581
+ function isPaymentQuestion(radio) {
12582
+ var name = radio.getAttribute('name');
12583
+ var group = name ? null : radio.closest(QUESTION_GROUP);
12584
+ var question = group ? [group.getAttribute('id'), group.getAttribute('name'), group.getAttribute('aria-label')] : [name];
12585
+ return question.some(function (words) {
12586
+ return PAYMENT_QUESTION.test(nameWords(words));
12587
+ });
12588
+ }
12589
+ // What names a payment option: the radio's accessible name, the text and
12590
+ // image of each label, and its hand-written ids, text masked like a label.
12591
+ function optionNames(radio) {
12592
+ var names = [maskLabel(accessibleName(radio).raw)];
12593
+ var labels = radio instanceof HTMLInputElement && radio.labels ? Array.from(radio.labels).slice(0, 2) : [];
12594
+ labels.forEach(function (label) {
12595
+ if (isShown(label) && !isUnsafeTextSource(label, radio)) {
12596
+ names.push(maskLabel(renderedText(label)));
12597
+ names.push(maskLabel(shownImageAlt(label)));
12598
+ }
12599
+ });
12600
+ names.push(stableIdentifier(radio.getAttribute('id')), firstIdentifier(radio, TEST_ID_ATTRIBUTES));
12601
+ return names.filter(function (name, index) {
12602
+ return !!name && names.indexOf(name) === index;
12603
+ });
12604
+ }
12605
+ function describePaymentChoice(control, path) {
12606
+ if (path === void 0) {
12607
+ path = [];
12608
+ }
12609
+ var choice = choiceOf(control, path);
12610
+ if (!isRadio(choice) || hasComposedAncestor(choice, '[data-mp-no-track]') || !isPaymentQuestion(choice)) {
12611
+ return undefined;
12612
+ }
12613
+ var names = optionNames(choice);
12614
+ return names.length ? {
12615
+ radio: choice,
12616
+ names: names
12617
+ } : undefined;
12618
+ }
12619
+ // Read once the page has handled the click, which may have cancelled it.
12620
+ function isPicked(radio) {
12621
+ return radio instanceof HTMLInputElement ? radio.checked : radio.getAttribute('aria-checked') === 'true';
12622
+ }
12483
12623
 
12484
12624
  var checkoutPath = /(?:^|\/)(?:checkouts?|payment|order|kasse|paiement|commander?|pago)(?:\/|$)/i;
12485
12625
  // English look-alikes are whole words; the other languages stay substring
@@ -12495,9 +12635,11 @@ var mParticle = (function () {
12495
12635
  var routeGatedCommits = new RegExp('^(?:buy now|purchase|jetzt kaufen|kaufen|commander|(?:passer|valider) (?:la |ma )?commande|finalizar (?:la |mi )?compra|' + 'comprar ahora|acquista ora|nu kopen|\u4ECA\u3059\u3050\u8CFC\u5165|\u8CFC\u5165\u3059\u308B|\u3053\u306E\u5185\u5BB9\u3067\u7533\u3057\u8FBC\u3080)$');
12496
12636
  var steps = new RegExp('^(?:' + ["(?:let's |lets |go to |proceed to |secure )?(?:check ?out|checkout)(?: now| securely| as guest)?", '(?:continue|proceed) to (?:payment|review|billing|shipping|delivery|order review)|review (?:my |your )?order', 'guest checkout|(?:pay|continue|check ?out) (?:with|by) (?:card|credit card|debit card|credit or debit card)', 'zur kasse|zur kasse gehen|auschecken|weiter zur zahlung', 'passer \u00E0 la caisse|continuer vers le paiement|proc\u00E9der au paiement', 'ir a caja|continuar al pago|tramitar pedido', "procedi al checkout|procedi all'acquisto|procedi al pagamento|vai alla cassa", 'afrekenen|verder naar betalen|doorgaan naar betalen', '\u30EC\u30B8\u306B\u9032\u3080|\u3054?(?:\u8CFC\u5165|\u6CE8\u6587)\u624B\u7D9A\u304D(?:\u3078|\u306B)(?:\u9032\u3080)?|\u304A?\u652F\u6255\u3044(?:\u3078|\u306B)\u9032\u3080|(?:\u3054\u6CE8\u6587\u5185\u5BB9\u306E)?\u78BA\u8A8D\u753B\u9762\u3078(?:\u9032\u3080)?'].join('|') + ')$');
12497
12637
  var CART_NOUN = '(?:(?:my|your|the) )?(?:shopping )?(?:cart|bag|basket)';
12498
- // "Add to bag", "View cart", "Shopping bag", "Bag", and a count badge such as
12499
- // "1 item in bag", which reads "item in bag" once digits are stripped.
12500
- var cartLabels = new RegExp('^(?:add(?: [^ ]+){0,5} to ' + CART_NOUN + '|(?:(?:view|open|go to) )?' + CART_NOUN + '(?: items?)?' + '|items? in ' + CART_NOUN + ')$');
12638
+ // "Add to bag" and "Add 2 to cart": a click that puts something in the cart.
12639
+ var addToCartLabels = new RegExp('^add(?: [^ ]+){0,5} to ' + CART_NOUN + '$');
12640
+ // "View cart", "Shopping bag", "Bag", and a count badge such as "1 item in bag",
12641
+ // which reads "item in bag" once digits are stripped: a click that opens the cart.
12642
+ var openCartLabels = new RegExp('^(?:(?:(?:view|open|go to) )?' + CART_NOUN + '(?: items?)?' + '|items? in ' + CART_NOUN + ')$');
12501
12643
  var WALLET_NAMES = 'apple pay|google pay|paypal|venmo|amazon pay|shop pay|klarna|afterpay|clearpay|cash app(?: pay)?|affirm|sezzle|samsung pay';
12502
12644
  var WALLET_VERBS = 'pay|buy|purchase|order|book|donate|subscribe|check ?out|checkout|express checkout|continue|proceed|' + 'complete purchase|place (?:my |your )?order';
12503
12645
  // "Pay with Klarna", "Buy with GPay", "Continue to PayPal".
@@ -12505,14 +12647,27 @@ var mParticle = (function () {
12505
12647
  // A wallet's own name on a button: "PayPal", "Klarna checkout", "Apple Pay logo".
12506
12648
  var walletBrands = new RegExp('^(?:' + WALLET_NAMES + ')(?: (?:checkout|check out|express(?: checkout)?|express pay|buy now|pay now|pay|now)' + '| (?:logo|icon|mark|button)(?: (?:logo|icon|mark|button))*)?$');
12507
12649
  // Exact HTTPS hosts of hosted wallet button frames.
12508
- var walletFrameHosts = new Set(['pay.google.com', 'applepay.cdn-apple.com', 'payments.amazon.com', 'pay.shopify.com']);
12650
+ var walletFrameFamilies = {
12651
+ 'pay.google.com': 'google_pay',
12652
+ 'applepay.cdn-apple.com': 'apple_pay',
12653
+ 'payments.amazon.com': 'amazon_pay',
12654
+ 'pay.shopify.com': 'shop_pay'
12655
+ };
12509
12656
  // PayPal serves its buttons and its card fields and pay-later messages from
12510
12657
  // the same hosts; only the button frames are wallet taps.
12511
12658
  var paypalFrameHosts = new Set(['www.paypal.com', 'www.sandbox.paypal.com']);
12512
12659
  var PAYPAL_BUTTON_FRAME = /^\/smart\/(?:buttons|menu)(?:\/|$)/;
12660
+ var PAYPAL_CARD_FRAME = /^\/smart\/card-fields?(?:\/|$)/;
12661
+ // PayPal's JS SDK, used directly or wrapped by a processor, leaves its frames
12662
+ // without a src and names them __zoid__paypal_<component>__ instead.
12663
+ var PAYPAL_SDK_FRAME = /^__zoid__paypal_/;
12664
+ var PAYPAL_SDK_BUTTON_FRAME = /^__zoid__paypal_(?:buttons|menu)__/;
12513
12665
  // Stripe's quick-pay button frames; its other frames are card and form fields.
12514
12666
  var STRIPE_WALLET_FRAME = /\/elements-inner-(?:payment-request|express-checkout)-/;
12667
+ var STRIPE_CARD_FRAME = /\/elements-inner-card\b/;
12515
12668
  // Hosted card-entry and fingerprint frames: focus there is typing card details.
12669
+ // Some of these hosts also serve gift card and bank account fields, so none
12670
+ // names a family.
12516
12671
  var CARD_FRAME_DOMAINS = ['adyen.com', 'braintreegateway.com', 'cybersource.com', 'squarecdn.com', 'checkout.com'];
12517
12672
  // Keep these classes ASCII-only in source bytes to avoid mojibake parse failures
12518
12673
  // when a host page forces non-UTF-8 decoding before JavaScript parse.
@@ -12574,12 +12729,20 @@ var mParticle = (function () {
12574
12729
  });
12575
12730
  }
12576
12731
  // A cart button is often a bare icon, so its title names it when nothing else
12577
- // does. Only the cart rule reads the title.
12578
- function isCartControl(control, cores) {
12732
+ // does. Only the cart rule reads the title. Opening the cart counts only for a
12733
+ // control that opens it on the page, such as a flyout: one that leads to the cart
12734
+ // page unloads before a call made on the click can return.
12735
+ function cartControlAction(control, cores) {
12579
12736
  var title = cores.length ? undefined : normalize(control.getAttribute('title'));
12580
- return (title ? [coreLabel(title)] : cores).some(function (text) {
12581
- return cartLabels.test(text);
12582
- });
12737
+ var texts = title ? [coreLabel(title)] : cores;
12738
+ if (texts.some(function (text) {
12739
+ return addToCartLabels.test(text);
12740
+ })) {
12741
+ return 'add';
12742
+ }
12743
+ return (control.hasAttribute('aria-expanded') || control.hasAttribute('aria-haspopup')) && texts.some(function (text) {
12744
+ return openCartLabels.test(text);
12745
+ }) ? 'open' : undefined;
12583
12746
  }
12584
12747
  // "Buy now" and "Purchase" count only on a checkout route, and never on a plain
12585
12748
  // link, which is navigation.
@@ -12593,8 +12756,8 @@ var mParticle = (function () {
12593
12756
  // pickers, toggles and pay-later messages never count; a vendor's own wallet
12594
12757
  // button counts before any label rule; a confirm label on any source counts
12595
12758
  // before the look-alike exclusions veto; then a wallet-named control, wallet
12596
- // phrases and steps. A cart label, links included, counts only where none of
12597
- // those do.
12759
+ // phrases and steps. An add-to-cart label, links included, or a control that
12760
+ // opens the cart on the page counts only where none of those do.
12598
12761
  function classifyIntent(control, pathname) {
12599
12762
  var vendor = vendorButtonKind(control);
12600
12763
  if (vendor === 'none') {
@@ -12608,10 +12771,20 @@ var mParticle = (function () {
12608
12771
  }
12609
12772
  var texts = labels(control);
12610
12773
  var cores = texts.map(coreLabel);
12611
- var cart = isCartControl(control, cores) ? {
12612
- kind: 'cart',
12613
- source: 'label'
12614
- } : undefined;
12774
+ var cartAction = cartControlAction(control, cores);
12775
+ var cart;
12776
+ if (cartAction === 'add') {
12777
+ cart = {
12778
+ kind: 'cart',
12779
+ source: 'label',
12780
+ adds: true
12781
+ };
12782
+ } else if (cartAction === 'open') {
12783
+ cart = {
12784
+ kind: 'cart',
12785
+ source: 'label'
12786
+ };
12787
+ }
12615
12788
  if (isQuietIntentControl(control, false, !!cart)) {
12616
12789
  return undefined;
12617
12790
  }
@@ -12668,30 +12841,66 @@ var mParticle = (function () {
12668
12841
  return host === domain || host.length > domain.length && host.slice(host.length - domain.length - 1) === '.' + domain;
12669
12842
  }
12670
12843
  // Focus moving into a visible hosted wallet button counts as a wallet click;
12671
- // focus into hosted card fields or messages is only a frame.
12672
- function classifyIntentFrame(target, win) {
12844
+ // focus into hosted card fields or messages is only a frame. A family comes
12845
+ // only from a frame that can draw no other method: PayPal's button frame also
12846
+ // draws Pay Later, Venmo and its card form, Stripe's quick-pay frame draws
12847
+ // Apple Pay or Google Pay by browser, and its payment form holds several.
12848
+ function classifyPaymentFrame(target, win) {
12673
12849
  if (win.document.visibilityState !== 'visible' || !(target instanceof HTMLIFrameElement)) {
12674
12850
  return undefined;
12675
12851
  }
12676
12852
  if (isRoktElement(target) || hasComposedAncestor(target, '[data-mp-no-track]')) {
12677
12853
  return undefined;
12678
12854
  }
12855
+ // A frame that has its own src is judged by that address, never by its name.
12856
+ if ((!target.src || target.src === 'about:blank') && PAYPAL_SDK_FRAME.test(target.name)) {
12857
+ return PAYPAL_SDK_BUTTON_FRAME.test(target.name) ? {
12858
+ kind: 'wallet'
12859
+ } : {
12860
+ kind: 'frame'
12861
+ };
12862
+ }
12679
12863
  try {
12680
12864
  var url = new URL(target.src);
12681
12865
  var host_1 = url.protocol === 'https:' ? url.hostname : '';
12682
12866
  if (paypalFrameHosts.has(host_1)) {
12683
- return PAYPAL_BUTTON_FRAME.test(url.pathname) ? 'wallet' : 'frame';
12867
+ if (PAYPAL_BUTTON_FRAME.test(url.pathname)) {
12868
+ return {
12869
+ kind: 'wallet'
12870
+ };
12871
+ }
12872
+ return PAYPAL_CARD_FRAME.test(url.pathname) ? {
12873
+ kind: 'frame',
12874
+ family: 'card'
12875
+ } : {
12876
+ kind: 'frame'
12877
+ };
12684
12878
  }
12685
- if (walletFrameHosts.has(host_1)) {
12686
- return 'wallet';
12879
+ if (Object.prototype.hasOwnProperty.call(walletFrameFamilies, host_1)) {
12880
+ return {
12881
+ kind: 'wallet',
12882
+ family: walletFrameFamilies[host_1]
12883
+ };
12687
12884
  }
12688
12885
  if (host_1 === 'js.stripe.com') {
12689
- return STRIPE_WALLET_FRAME.test(url.pathname) ? 'wallet' : 'frame';
12886
+ if (STRIPE_WALLET_FRAME.test(url.pathname)) {
12887
+ return {
12888
+ kind: 'wallet'
12889
+ };
12890
+ }
12891
+ return STRIPE_CARD_FRAME.test(url.pathname) ? {
12892
+ kind: 'frame',
12893
+ family: 'card'
12894
+ } : {
12895
+ kind: 'frame'
12896
+ };
12690
12897
  }
12691
12898
  if (CARD_FRAME_DOMAINS.some(function (domain) {
12692
12899
  return isOnDomain(host_1, domain);
12693
12900
  })) {
12694
- return 'frame';
12901
+ return {
12902
+ kind: 'frame'
12903
+ };
12695
12904
  }
12696
12905
  } catch (e) {
12697
12906
  // An unparseable frame src is not a wallet frame.
@@ -12808,13 +13017,17 @@ var mParticle = (function () {
12808
13017
  var PASSIVE = {
12809
13018
  passive: true
12810
13019
  };
12811
- // Logs every button click as an mParticle event, and hands checkout intent to the
12812
- // Rokt kit as a frozen {kind, t, source, pathname}. Submits and wallet frame focus feed the kit only.
13020
+ // Logs button clicks and clicks on links that leave the page as mParticle events, and hands checkout
13021
+ // intent to the Rokt kit as a frozen {kind, t, source, pathname}, with adds on an add-to-cart click.
13022
+ // Submits and wallet frame focus feed the kit only, and so do payment picks: a payment radio's option
13023
+ // names, or the payment family of a focused frame.
12813
13024
  var ButtonTracker = /** @class */function () {
12814
13025
  function ButtonTracker(mpInstance) {
12815
13026
  var _this = this;
12816
13027
  this.active = false;
12817
13028
  this.hasRoktKit = false;
13029
+ this.logButtons = false;
13030
+ this.logLinks = false;
12818
13031
  // Bumped on reset so classification queued before it is dropped.
12819
13032
  this.generation = 0;
12820
13033
  this.lastCommitClick = -Infinity;
@@ -12888,7 +13101,9 @@ var mParticle = (function () {
12888
13101
  this.teardown();
12889
13102
  }
12890
13103
  this.hasRoktKit = options.hasRoktKit;
12891
- if (!this.eventsEnabled() && this.isKitSuppressed()) {
13104
+ this.logButtons = options.logButtons;
13105
+ this.logLinks = options.logLinks;
13106
+ if ((!(this.logButtons || this.logLinks) || !this.eventsEnabled()) && this.isKitSuppressed()) {
12892
13107
  this.log('opted out, not starting');
12893
13108
  return;
12894
13109
  }
@@ -12989,7 +13204,7 @@ var mParticle = (function () {
12989
13204
  return;
12990
13205
  }
12991
13206
  var layer = event.type;
12992
- var logsEvents = layer === 'click' && this.eventsEnabled();
13207
+ var logsEvents = layer === 'click' && (this.logButtons || this.logLinks) && this.eventsEnabled() && !this.hasTargetingOptOut();
12993
13208
  var signalsKit = !this.isKitSuppressed();
12994
13209
  if (!logsEvents && !signalsKit) {
12995
13210
  return;
@@ -13001,9 +13216,13 @@ var mParticle = (function () {
13001
13216
  // button that disables or relabels itself is seen as it was clicked.
13002
13217
  // Logging and the kit hand-off wait for the next paint.
13003
13218
  var click;
13219
+ var asLink = false;
13004
13220
  var box;
13005
13221
  var kind;
13006
13222
  var source;
13223
+ var adds;
13224
+ var choice;
13225
+ var family;
13007
13226
  var unconfirmedCommit = false;
13008
13227
  if (layer === 'click') {
13009
13228
  // The composed path is only populated during dispatch.
@@ -13011,7 +13230,18 @@ var mParticle = (function () {
13011
13230
  var excluded = isExcludedPath(path);
13012
13231
  var control = excluded ? undefined : findControl(path, true);
13013
13232
  if (control) {
13014
- click = logsEvents ? describeButtonClick(control, path) : undefined;
13233
+ // With links alone, only an anchor can be logged.
13234
+ click = logsEvents && (this.logButtons || control.matches('a[href]')) ? describeButtonClick(control, path) : undefined;
13235
+ if (click) {
13236
+ asLink = this.logLinks && isLinkClick(click);
13237
+ // Without link tracking, a link that leaves the page stays a
13238
+ // button click, except a plain link to another page of the
13239
+ // site, which button tracking never logged.
13240
+ var asButton = this.logButtons && !asLink && !(click.linkType === 'internal' && control.matches('a[href]:not([role="button"])'));
13241
+ if (!asLink && !asButton) {
13242
+ click = undefined;
13243
+ }
13244
+ }
13015
13245
  if (click && click.checked !== undefined) {
13016
13246
  box = control;
13017
13247
  }
@@ -13019,6 +13249,8 @@ var mParticle = (function () {
13019
13249
  var intent = signalsKit ? classifyIntent(control, pathname) : undefined;
13020
13250
  kind = intent ? intent.kind : undefined;
13021
13251
  source = intent ? intent.source : undefined;
13252
+ adds = intent ? intent.adds : undefined;
13253
+ choice = signalsKit ? describePaymentChoice(control, path) : undefined;
13022
13254
  }
13023
13255
  this.lastClick = {
13024
13256
  t: t,
@@ -13038,6 +13270,7 @@ var mParticle = (function () {
13038
13270
  var intent = classifyIntent(control, pathname);
13039
13271
  kind = intent ? intent.kind : undefined;
13040
13272
  source = intent ? intent.source : undefined;
13273
+ adds = intent ? intent.adds : undefined;
13041
13274
  }
13042
13275
  unconfirmedCommit = !submitter;
13043
13276
  }
@@ -13050,7 +13283,9 @@ var mParticle = (function () {
13050
13283
  if (layer === 'blur') {
13051
13284
  // Read after the blur settles: some browsers have not moved
13052
13285
  // focus into the frame yet when the window blurs.
13053
- kind = classifyIntentFrame(document.activeElement, window);
13286
+ var frame = classifyPaymentFrame(document.activeElement, window);
13287
+ kind = frame ? frame.kind : undefined;
13288
+ family = frame ? frame.family : undefined;
13054
13289
  source = 'frame';
13055
13290
  } else if (unconfirmedCommit && t - _this.lastCommitClick > SUBMIT_AFTER_COMMIT_CLICK_MS) {
13056
13291
  kind = undefined;
@@ -13064,10 +13299,17 @@ var mParticle = (function () {
13064
13299
  if (box && event.defaultPrevented) {
13065
13300
  click.checked = box.type === 'checkbox' ? !click.checked : box.checked;
13066
13301
  }
13067
- _this.logClick(click, pathname);
13302
+ _this.logClick(click, pathname, asLink);
13303
+ }
13304
+ // Ahead of the intent, so a pre-selection it fires goes out
13305
+ // with this pick.
13306
+ if (choice && isPicked(choice.radio)) {
13307
+ _this.pickPayment(t, pathname, choice.names);
13308
+ } else if (family) {
13309
+ _this.pickPayment(t, pathname, undefined, family);
13068
13310
  }
13069
13311
  if (kind) {
13070
- _this.emit(kind, source, layer, t, pathname);
13312
+ _this.emit(kind, source, layer, t, pathname, adds);
13071
13313
  }
13072
13314
  } catch (e) {
13073
13315
  _this.log('[error] delivery threw: ' + e);
@@ -13075,8 +13317,8 @@ var mParticle = (function () {
13075
13317
  });
13076
13318
  };
13077
13319
  // Every real click is one event, repeats included, up to a ceiling per page.
13078
- ButtonTracker.prototype.logClick = function (click, pathname) {
13079
- if (!this.eventsEnabled()) {
13320
+ ButtonTracker.prototype.logClick = function (click, pathname, asLink) {
13321
+ if (!this.eventsEnabled() || this.hasTargetingOptOut()) {
13080
13322
  return;
13081
13323
  }
13082
13324
  if (pathname !== this.pagePath) {
@@ -13090,7 +13332,7 @@ var mParticle = (function () {
13090
13332
  // Restarts an expired session, as public logEvent() and page views do.
13091
13333
  this.mpInstance._SessionManager.resetSessionTimer();
13092
13334
  var queued = this.queuedForUpload();
13093
- this.mpInstance._Events.logEvent(buildButtonClickEvent(click, pathname));
13335
+ this.mpInstance._Events.logEvent(asLink ? buildLinkClickEvent(click, pathname) : buildButtonClickEvent(click, pathname));
13094
13336
  // Only a click waiting for the batch interval is sent early: a held
13095
13337
  // one goes out when released, and with batching off it already has.
13096
13338
  // A checkbox or radio waits for the batch, since choosing an option
@@ -13130,33 +13372,60 @@ var mParticle = (function () {
13130
13372
  }
13131
13373
  this.uploadHeld = false;
13132
13374
  };
13133
- ButtonTracker.prototype.emit = function (kind, source, layer, t, pathname) {
13375
+ ButtonTracker.prototype.emit = function (kind, source, layer, t, pathname, adds) {
13134
13376
  if (this.isKitSuppressed()) {
13135
13377
  return;
13136
13378
  }
13137
13379
  if (kind === 'commit' && layer === 'click') {
13138
13380
  this.lastCommitClick = t;
13139
13381
  }
13140
- var last = this.lastSent[kind];
13382
+ // An add-to-cart click throttles apart from a click that opens the
13383
+ // cart, so opening the cart first never drops the add.
13384
+ var key = adds ? kind + ':adds' : kind;
13385
+ var last = this.lastSent[key];
13141
13386
  if (last && last.pathname === pathname && t - last.t < THROTTLE_MS) {
13142
13387
  return;
13143
13388
  }
13144
- this.lastSent[kind] = {
13389
+ this.lastSent[key] = {
13145
13390
  t: t,
13146
13391
  pathname: pathname
13147
13392
  };
13148
- this.mpInstance._RoktManager.notifyCheckoutIntent(Object.freeze({
13393
+ this.mpInstance._RoktManager.notifyCheckoutIntent(Object.freeze(adds ? {
13394
+ kind: kind,
13395
+ t: t,
13396
+ source: source,
13397
+ pathname: pathname,
13398
+ adds: adds
13399
+ } : {
13149
13400
  kind: kind,
13150
13401
  t: t,
13151
13402
  source: source,
13152
13403
  pathname: pathname
13153
13404
  }), pathname);
13154
13405
  };
13406
+ ButtonTracker.prototype.pickPayment = function (t, pathname, names, family) {
13407
+ if (this.isKitSuppressed()) {
13408
+ return;
13409
+ }
13410
+ this.mpInstance._RoktManager.notifyPaymentPick(Object.freeze({
13411
+ t: t,
13412
+ pathname: pathname,
13413
+ names: names ? Object.freeze(names.slice()) : undefined,
13414
+ family: family
13415
+ }));
13416
+ };
13155
13417
  // Events follow the SDK's opt-out like any other event.
13156
13418
  ButtonTracker.prototype.eventsEnabled = function () {
13157
13419
  var store = this.mpInstance._Store;
13158
13420
  return !!store && store.isEnabled;
13159
13421
  };
13422
+ // Read per click, since the launcher options can arrive after the tracker
13423
+ // starts. Only where this init configures a Rokt kit, so Global Privacy
13424
+ // Control alone doesn't stop click logging elsewhere.
13425
+ ButtonTracker.prototype.hasTargetingOptOut = function () {
13426
+ var roktManager = this.mpInstance._RoktManager;
13427
+ return this.hasRoktKit && !!roktManager && roktManager.hasTargetingOptOut();
13428
+ };
13160
13429
  // The Rokt manager owns the kit's privacy gates: flag, opt-out, launcher
13161
13430
  // options and Global Privacy Control.
13162
13431
  ButtonTracker.prototype.isKitSuppressed = function () {
@@ -14101,7 +14370,8 @@ var mParticle = (function () {
14101
14370
  var getFeatureFlag = mpInstance._Helpers.getFeatureFlag;
14102
14371
  var _e = Constants.FeatureFlags,
14103
14372
  AutoLogPageView = _e.AutoLogPageView,
14104
- AutoButtonTracking = _e.AutoButtonTracking;
14373
+ AutoButtonTracking = _e.AutoButtonTracking,
14374
+ AutoLinkTracking = _e.AutoLinkTracking;
14105
14375
  // Destroy previous batch uploader to prevent leaked timers and event listeners
14106
14376
  if ((_a = mpInstance._APIClient) === null || _a === void 0 ? void 0 : _a.uploader) {
14107
14377
  mpInstance._APIClient.uploader.destroy();
@@ -14168,11 +14438,16 @@ var mParticle = (function () {
14168
14438
  // Rokt kit only when that kit receives them. Set before
14169
14439
  // processForwarders: the kit can read it during this init, from its own
14170
14440
  // init or from a returning shopper's landing page view.
14441
+ var logButtons = !!getFeatureFlag(AutoButtonTracking);
14442
+ var logLinks = !!getFeatureFlag(AutoLinkTracking);
14443
+ // Links feed intent too, so with link tracking on the kit must also
14444
+ // receive Auto Link Click events.
14171
14445
  var buttonClickBlocker = roktConfig_1 ? getButtonClickBlocker(roktConfig_1, kitBlocker) : undefined;
14172
- if (buttonClickBlocker && getFeatureFlag(AutoButtonTracking)) {
14173
- mpInstance.Logger.warning("Checkout intent is off: the ".concat(buttonClickBlocker, " keeps some or all Auto Button Click events from the Rokt kit."));
14446
+ var linkClickBlocker = roktConfig_1 && logLinks ? getButtonClickBlocker(roktConfig_1, kitBlocker, true) : undefined;
14447
+ if (logButtons && (buttonClickBlocker || linkClickBlocker)) {
14448
+ mpInstance.Logger.warning(buttonClickBlocker ? "Checkout intent is off: the ".concat(buttonClickBlocker, " keeps some or all Auto Button Click events from the Rokt kit.") : "Checkout intent is off: the ".concat(linkClickBlocker, " keeps some or all Auto Link Click events from the Rokt kit."));
14174
14449
  }
14175
- mpInstance._RoktManager.setAutoButtonClicksForwarded(!!roktConfig_1 && !buttonClickBlocker);
14450
+ mpInstance._RoktManager.setAutoButtonClicksForwarded(!!roktConfig_1 && !buttonClickBlocker && !linkClickBlocker);
14176
14451
  mpInstance._Forwarders.processForwarders(config, mpInstance._APIClient.prepareForwardingStats);
14177
14452
  mpInstance._Forwarders.processPixelConfigs(config);
14178
14453
  // Checks if session is created, resumed, or needs to be ended
@@ -14207,12 +14482,14 @@ var mParticle = (function () {
14207
14482
  // so it stops listening. Re-created if the flag is re-enabled later.
14208
14483
  mpInstance._PageViewTracker.teardown();
14209
14484
  }
14210
- if (getFeatureFlag(AutoButtonTracking)) {
14485
+ if (logButtons || logLinks) {
14211
14486
  if (!mpInstance._ButtonTracker) {
14212
14487
  mpInstance._ButtonTracker = new ButtonTracker(mpInstance);
14213
14488
  }
14214
14489
  mpInstance._ButtonTracker.init({
14215
- hasRoktKit: !!roktConfig_1
14490
+ hasRoktKit: !!roktConfig_1,
14491
+ logButtons: logButtons,
14492
+ logLinks: logLinks
14216
14493
  });
14217
14494
  } else {
14218
14495
  // Also retires a tracker left by an earlier bundle load. Like APV,
@@ -14318,10 +14595,12 @@ var mParticle = (function () {
14318
14595
  // Initialize CookieConsentManager with privacy flags from launcherOptions
14319
14596
  var _a = normalizeRoktLauncherOptions(config === null || config === void 0 ? void 0 : config.launcherOptions),
14320
14597
  noFunctional = _a.noFunctional,
14321
- noTargeting = _a.noTargeting;
14598
+ noTargeting = _a.noTargeting,
14599
+ doNotShareOrSell = _a.doNotShareOrSell;
14322
14600
  mpInstance._CookieConsentManager = new CookieConsentManager({
14323
14601
  noFunctional: noFunctional,
14324
- noTargeting: noTargeting
14602
+ noTargeting: noTargeting,
14603
+ doNotShareOrSell: doNotShareOrSell
14325
14604
  });
14326
14605
  // Check to see if localStorage is available before main configuration runs
14327
14606
  // since we will need this for the current implementation of user persistence