@mparticle/web-sdk 3.28.0 → 3.29.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.
- package/README.md +65 -34
- package/dist/mparticle.common.js +1 -1
- package/dist/mparticle.esm.js +1 -1
- package/dist/mparticle.js +324 -55
- package/dist/types/src/buttonTracking/buttonDescription.d.ts +2 -0
- package/dist/types/src/buttonTracking/buttonTracker.d.ts +1 -0
- package/dist/types/src/buttonTracking/checkoutIntent.d.ts +2 -0
- package/dist/types/src/roktManager.d.ts +3 -0
- package/package.json +1 -1
- package/src/buttonTracking/buttonDescription.ts +397 -61
- package/src/buttonTracking/buttonTracker.ts +49 -7
- package/src/buttonTracking/checkoutIntent.ts +36 -0
- package/src/mp-instance.ts +8 -4
- package/src/roktManager.ts +13 -0
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.
|
|
207
|
+
var version = "3.29.1";
|
|
208
208
|
|
|
209
209
|
var Constants = {
|
|
210
210
|
sdkVersion: version,
|
|
@@ -11209,6 +11209,9 @@ var mParticle = (function () {
|
|
|
11209
11209
|
this.pendingCheckoutIntents = [];
|
|
11210
11210
|
// Off until SDK init finds the Rokt connection receives auto button clicks.
|
|
11211
11211
|
this.autoButtonClicksForwarded = false;
|
|
11212
|
+
// Off until SDK init finds the Rokt connection receives auto link clicks, or
|
|
11213
|
+
// link tracking is off. Only link clicks lose their intent without it.
|
|
11214
|
+
this.autoLinkClicksForwarded = false;
|
|
11212
11215
|
}
|
|
11213
11216
|
/**
|
|
11214
11217
|
* Sets a callback to be invoked when RoktManager becomes ready
|
|
@@ -11338,6 +11341,14 @@ var mParticle = (function () {
|
|
|
11338
11341
|
RoktManager.prototype.setAutoButtonClicksForwarded = function (forwarded) {
|
|
11339
11342
|
this.autoButtonClicksForwarded = forwarded;
|
|
11340
11343
|
};
|
|
11344
|
+
RoktManager.prototype.setAutoLinkClicksForwarded = function (forwarded) {
|
|
11345
|
+
this.autoLinkClicksForwarded = forwarded;
|
|
11346
|
+
};
|
|
11347
|
+
// The Rokt kit reads this too: while false, its page views keep
|
|
11348
|
+
// dispatchDelayMs, since a checkout link could never release the wait.
|
|
11349
|
+
RoktManager.prototype.areAutoLinkClicksForwarded = function () {
|
|
11350
|
+
return this.autoLinkClicksForwarded;
|
|
11351
|
+
};
|
|
11341
11352
|
// noTargeting (which noDeviceId implies), doNotShareOrSell or Global Privacy
|
|
11342
11353
|
// Control. Unlike noFunctional, these also stop auto button and link clicks
|
|
11343
11354
|
// from being logged.
|
|
@@ -12472,6 +12483,9 @@ var mParticle = (function () {
|
|
|
12472
12483
|
}
|
|
12473
12484
|
|
|
12474
12485
|
var DOWNLOAD_EXTENSIONS = /\.(pdf|zip|csv|txt|ics|docx?|xlsx?|pptx?|dmg|exe|apk|mp3|mp4)$/i;
|
|
12486
|
+
// A link run by script reads as a link, as an anchor does, so whoever reads
|
|
12487
|
+
// the click treats it the same.
|
|
12488
|
+
var LINK_CONTROL = 'a[href]:not([role="button"]), [role~="link"]:not([role~="button"])';
|
|
12475
12489
|
function elementKind(control) {
|
|
12476
12490
|
if (isWalletElement(control)) {
|
|
12477
12491
|
return 'wallet';
|
|
@@ -12480,9 +12494,7 @@ var mParticle = (function () {
|
|
|
12480
12494
|
if (tag === 'button' || tag === 'input') {
|
|
12481
12495
|
return tag;
|
|
12482
12496
|
}
|
|
12483
|
-
|
|
12484
|
-
// the click treats it the same.
|
|
12485
|
-
return control.matches('a[href]:not([role="button"]), [role~="link"]:not([role~="button"])') ? 'link' : 'role';
|
|
12497
|
+
return control.matches(LINK_CONTROL) ? 'link' : 'role';
|
|
12486
12498
|
}
|
|
12487
12499
|
var NOT_RENDERED = 'script, style, template, [hidden], [aria-hidden="true"], [inert]';
|
|
12488
12500
|
// The most nodes read for one label source, and images looked at for one
|
|
@@ -12587,12 +12599,14 @@ var mParticle = (function () {
|
|
|
12587
12599
|
function textOf(element) {
|
|
12588
12600
|
return element && !isUnsafeTextSource(element) && isShown(element) ? renderedText(element) : '';
|
|
12589
12601
|
}
|
|
12590
|
-
// The control itself is already known to be shown.
|
|
12602
|
+
// The control itself is already known to be shown. An inline icon names
|
|
12603
|
+
// itself with aria-label rather than alt.
|
|
12591
12604
|
function shownImageAlt(control) {
|
|
12592
|
-
var images = control.querySelectorAll('img[alt]');
|
|
12605
|
+
var images = control.querySelectorAll('img[alt], svg[aria-label], [role="img"][aria-label]');
|
|
12593
12606
|
for (var i = 0; i < images.length && i < MAX_READS; i++) {
|
|
12594
|
-
|
|
12595
|
-
|
|
12607
|
+
var alt = nonBlank(images[i].getAttribute('alt') || images[i].getAttribute('aria-label'));
|
|
12608
|
+
if (alt && isShown(images[i], control) && isVisible(images[i])) {
|
|
12609
|
+
return alt;
|
|
12596
12610
|
}
|
|
12597
12611
|
}
|
|
12598
12612
|
return undefined;
|
|
@@ -12771,11 +12785,28 @@ var mParticle = (function () {
|
|
|
12771
12785
|
var digits = id.replace(/[^0-9]/g, '').length;
|
|
12772
12786
|
return id.length <= 64 && digits <= 3 && HAND_WRITTEN_ID.test(id) ? id : undefined;
|
|
12773
12787
|
}
|
|
12788
|
+
// An id React's useId generates, in any of the forms React has used: `:r1:`,
|
|
12789
|
+
// `\u00ABr1\u00BB` and `_r_1_`. On the client it is r and a short base-32 counter; on
|
|
12790
|
+
// the server, R and a base-32 tree id, where a component's later ids add an H
|
|
12791
|
+
// and a counter (`:R1H1:`). A word that only starts with r, such as
|
|
12792
|
+
// `:region:`, is not one.
|
|
12793
|
+
var REACT_ID = /:(?:r[0-9a-v]{1,4}|R[0-9a-v]+(?:H[0-9a-v]+)?):|\u00ab(?:r[0-9a-v]{1,4}|R[0-9a-v]+(?:H[0-9a-v]+)?)\u00bb|_(?:r_[0-9a-v]{1,4}|R_[0-9a-v]+(?:H[0-9a-v]+)?)_/g;
|
|
12794
|
+
// What a UI library puts before the React id it names an unnamed group with
|
|
12795
|
+
// (`radix-:r1:`, `react-aria-:R1:`). Left on its own once that id is removed,
|
|
12796
|
+
// it names the library, not the question.
|
|
12797
|
+
var LIBRARY_ID_PREFIX = /^(?:radix|react-aria|headlessui(?:-[a-z]+)*|mui|chakra|reach|ark|mantine|base-ui)$/i;
|
|
12774
12798
|
// A picker's input name, which names its question. Sites often end it with the
|
|
12775
|
-
// id of the product it belongs to (`color-swatches-48213907`)
|
|
12776
|
-
//
|
|
12799
|
+
// id of the product it belongs to (`color-swatches-48213907`), or build it
|
|
12800
|
+
// with a React id (`variant_group__R_1mn59b_`); without either it still names
|
|
12801
|
+
// the question.
|
|
12777
12802
|
function questionName(value) {
|
|
12778
|
-
|
|
12803
|
+
if (!value) {
|
|
12804
|
+
return undefined;
|
|
12805
|
+
}
|
|
12806
|
+
var trimmed = value.trim();
|
|
12807
|
+
var withoutReactId = trimmed.replace(REACT_ID, '-');
|
|
12808
|
+
var name = stableIdentifier(withoutReactId.replace(/([-_])[-_]+/g, '$1').replace(/^[-_]+|[-_]+$/g, '').replace(/[-_][0-9]{4,}$/, ''));
|
|
12809
|
+
return name && withoutReactId !== trimmed && LIBRARY_ID_PREFIX.test(name) ? undefined : name;
|
|
12779
12810
|
}
|
|
12780
12811
|
var TEST_ID_ATTRIBUTES = ['data-testid', 'data-test-id', 'data-test', 'data-qa', 'data-cy'];
|
|
12781
12812
|
// The first of these attributes that holds a developer-written identifier.
|
|
@@ -12796,10 +12827,13 @@ var mParticle = (function () {
|
|
|
12796
12827
|
return stableIdentifier(ariaControls ? ariaControls.trim().split(/\s+/)[0] : null) || firstIdentifier(control, ['popovertarget', 'commandfor']);
|
|
12797
12828
|
}
|
|
12798
12829
|
// The id of the form a button or input actually submits, which the browser
|
|
12799
|
-
// resolves from its form attribute or its owning form.
|
|
12800
|
-
//
|
|
12830
|
+
// resolves from its form attribute or its owning form. A role control, such as
|
|
12831
|
+
// a styled radio box, belongs to the form around it, read without following a
|
|
12832
|
+
// form attribute or leaving its shadow root, since neither makes it part of
|
|
12833
|
+
// the form; a link, anchor or role, to none. getAttribute, because a field
|
|
12834
|
+
// named "id" shadows form.id.
|
|
12801
12835
|
function formIdentifier(control) {
|
|
12802
|
-
var form = control instanceof HTMLButtonElement || control instanceof HTMLInputElement ? control.form : null;
|
|
12836
|
+
var form = control instanceof HTMLButtonElement || control instanceof HTMLInputElement ? control.form : control.matches(LINK_CONTROL) ? null : control.closest('form');
|
|
12803
12837
|
return form ? stableIdentifier(form.getAttribute('id')) : undefined;
|
|
12804
12838
|
}
|
|
12805
12839
|
// The browser's normalised type: a button defaults to 'submit' and an unknown
|
|
@@ -13002,7 +13036,7 @@ var mParticle = (function () {
|
|
|
13002
13036
|
// aria-label, aria-labelledby or legend, masked like a label and cut at its
|
|
13003
13037
|
// first colon, since a legend can repeat the pick ("Color: Navy"). Never the
|
|
13004
13038
|
// option's own text, which is the shopper's answer.
|
|
13005
|
-
var NAMED_GROUP = '[role="radiogroup"], [role="listbox"], [role="group"], fieldset';
|
|
13039
|
+
var NAMED_GROUP = '[role="radiogroup"], [role="listbox"], [role="group"], fieldset, ' + '[role="region"][aria-label], [role="region"][aria-labelledby]';
|
|
13006
13040
|
// A control such as the button that opens a list box shows the option picked.
|
|
13007
13041
|
var NOT_A_QUESTION = CHOICE + ', ' + CONTROL_SELECTOR + ', a[href], input, select, textarea, slot, [aria-haspopup], [role~="button"], ' + '[role~="link"], [role~="tab"], [role~="combobox"]';
|
|
13008
13042
|
var OPTION_KINDS = ['radio', 'menuitemradio', 'checkbox', 'menuitemcheckbox', 'switch', 'option'];
|
|
@@ -13027,6 +13061,113 @@ var mParticle = (function () {
|
|
|
13027
13061
|
var name = choice.getAttribute('name');
|
|
13028
13062
|
return option instanceof HTMLInputElement && option.type === choice.type && !!name && option.getAttribute('name') === name && option.form === choice.form;
|
|
13029
13063
|
}
|
|
13064
|
+
function isTransparent(element, until) {
|
|
13065
|
+
return someComposedAncestor(element, function (node) {
|
|
13066
|
+
return window.getComputedStyle(node).opacity === '0';
|
|
13067
|
+
}, until);
|
|
13068
|
+
}
|
|
13069
|
+
// Content that is never painted where it sits: SVG that is only referenced or
|
|
13070
|
+
// read, and a canvas's fallback, which some browsers still give boxes.
|
|
13071
|
+
var UNDRAWN = 'svg title, svg desc, svg metadata, svg defs, svg symbol, svg clipPath, ' + 'svg mask, svg pattern, svg marker, svg linearGradient, ' + 'svg radialGradient, svg filter, canvas';
|
|
13072
|
+
// Whether text sits in any closed details element outside its summary.
|
|
13073
|
+
function isInClosedDetails(text, parent) {
|
|
13074
|
+
var details = parent.closest('details:not([open])');
|
|
13075
|
+
while (details) {
|
|
13076
|
+
var summary = Array.from(details.children).filter(function (child) {
|
|
13077
|
+
return child.tagName === 'SUMMARY';
|
|
13078
|
+
})[0];
|
|
13079
|
+
if (!summary || !summary.contains(text)) {
|
|
13080
|
+
return true;
|
|
13081
|
+
}
|
|
13082
|
+
details = details.parentElement ? details.parentElement.closest('details:not([open])') : null;
|
|
13083
|
+
}
|
|
13084
|
+
return false;
|
|
13085
|
+
}
|
|
13086
|
+
// Whether the browser shows an element through every ancestor it renders
|
|
13087
|
+
// under, shadow trees included, which a walk of light ancestors can't see
|
|
13088
|
+
// into when a shadow root is closed. Where it can't say (checkVisibility
|
|
13089
|
+
// arrived in Chrome 105, Firefox 125 and Safari 17.4), the element counts as
|
|
13090
|
+
// not shown, so option rows name no group in older browsers.
|
|
13091
|
+
function isComposedVisible(element) {
|
|
13092
|
+
var check = element.checkVisibility;
|
|
13093
|
+
return isFunction(check) &&
|
|
13094
|
+
// Older Chrome versions read the first two names, newer browsers the rest.
|
|
13095
|
+
check.call(element, {
|
|
13096
|
+
checkOpacity: true,
|
|
13097
|
+
checkVisibilityCSS: true,
|
|
13098
|
+
opacityProperty: true,
|
|
13099
|
+
visibilityProperty: true
|
|
13100
|
+
});
|
|
13101
|
+
}
|
|
13102
|
+
// Whether the browser lays a text node out in a box of its own. Text it never
|
|
13103
|
+
// draws, such as an SVG definition, canvas fallback, closed details or an
|
|
13104
|
+
// unslotted child of a shadow host, has none. Where boxes can't be read, the
|
|
13105
|
+
// text counts as not drawn.
|
|
13106
|
+
function isDrawn(text) {
|
|
13107
|
+
var range = isFunction(document.createRange) ? document.createRange() : null;
|
|
13108
|
+
if (!range || !isFunction(range.getClientRects)) {
|
|
13109
|
+
return false;
|
|
13110
|
+
}
|
|
13111
|
+
range.selectNodeContents(text);
|
|
13112
|
+
return Array.from(range.getClientRects()).some(function (box) {
|
|
13113
|
+
return box.width > 0 && box.height > 0;
|
|
13114
|
+
});
|
|
13115
|
+
}
|
|
13116
|
+
// Whether a row shows text of its own: a drawn, shown, non-transparent text
|
|
13117
|
+
// node, outside any form field, editable area or opted-out part, beside
|
|
13118
|
+
// nothing but the row's own input. Not a row with a shadow root, slot or
|
|
13119
|
+
// custom element, whose rendered text a walk of its light children can't see.
|
|
13120
|
+
function showsText(row, own) {
|
|
13121
|
+
if (isUnsafeTextSource(row, own) || hasComposedAncestor(own, '[data-mp-no-track]') || row.shadowRoot || row.tagName.indexOf('-') !== -1 || row.querySelector('slot')) {
|
|
13122
|
+
return false;
|
|
13123
|
+
}
|
|
13124
|
+
// A row too large to check in full counts as showing nothing.
|
|
13125
|
+
var descendants = row.querySelectorAll('*');
|
|
13126
|
+
if (descendants.length > MAX_READS) {
|
|
13127
|
+
return false;
|
|
13128
|
+
}
|
|
13129
|
+
for (var i = 0; i < descendants.length; i++) {
|
|
13130
|
+
if (descendants[i].shadowRoot || descendants[i].tagName.indexOf('-') !== -1) {
|
|
13131
|
+
return false;
|
|
13132
|
+
}
|
|
13133
|
+
}
|
|
13134
|
+
var walker = document.createTreeWalker(row, NodeFilter.SHOW_TEXT);
|
|
13135
|
+
for (var i = 0; i < MAX_READS && walker.nextNode(); i++) {
|
|
13136
|
+
var parent_1 = walker.currentNode.parentElement;
|
|
13137
|
+
if (parent_1 && nonBlank(walker.currentNode.nodeValue) &&
|
|
13138
|
+
// Undrawn content, and the body of a closed details element,
|
|
13139
|
+
// which browsers still give layout boxes.
|
|
13140
|
+
!parent_1.closest(UNDRAWN) && !isInClosedDetails(walker.currentNode, parent_1) && isShown(parent_1, row) && isVisible(parent_1) && !isTransparent(parent_1, row) && isComposedVisible(parent_1) && isDrawn(walker.currentNode)) {
|
|
13141
|
+
return true;
|
|
13142
|
+
}
|
|
13143
|
+
}
|
|
13144
|
+
return false;
|
|
13145
|
+
}
|
|
13146
|
+
// A native input inside a shown control of its own, such as a menu option row
|
|
13147
|
+
// with a styled radio, which shows text of its own and doesn't also hold the
|
|
13148
|
+
// option picked.
|
|
13149
|
+
function showsRow(option, choice, group) {
|
|
13150
|
+
var row = option instanceof HTMLInputElement && option.parentElement ? option.parentElement.closest(CONTROL_SELECTOR) : null;
|
|
13151
|
+
return !!row && group.contains(row) && !row.contains(choice) && isShown(row, group) && isVisible(row) && !isTransparent(row, group) && showsText(row, option);
|
|
13152
|
+
}
|
|
13153
|
+
// Native boxes with no name, which the browser doesn't group, answer one
|
|
13154
|
+
// question only as menu option rows do: each in a shown row of its own, in the
|
|
13155
|
+
// same group. A card around a "make default" checkbox and another box has no
|
|
13156
|
+
// such rows. Rows alone can't tell a question from a card named for a person
|
|
13157
|
+
// around separate settings, so only a group that shows its question and holds
|
|
13158
|
+
// the rows directly counts.
|
|
13159
|
+
function unnamedOptionRows(option, choice, group) {
|
|
13160
|
+
return option instanceof HTMLInputElement && choice instanceof HTMLInputElement && option.type === choice.type && !option.getAttribute('name') && !choice.getAttribute('name') && option.form === choice.form && option.closest(NAMED_GROUP) === group && choice.closest(NAMED_GROUP) === group && showsRow(option, choice, group) && showsRow(choice, option, group) && showsQuestion(group);
|
|
13161
|
+
}
|
|
13162
|
+
// A native input the page hides, styling its label as the option instead, is
|
|
13163
|
+
// shown by that label: one of its own, in the group, that the browser draws
|
|
13164
|
+
// and that shows text of its own, as an option row must. Neither an opted-out
|
|
13165
|
+
// input nor an opted-out label counts.
|
|
13166
|
+
function showsLabel(option, choice, group) {
|
|
13167
|
+
return option instanceof HTMLInputElement && !!option.labels && !hasComposedAncestor(option, '[data-mp-no-track]') && Array.from(option.labels).some(function (label) {
|
|
13168
|
+
return group.contains(label) && !label.contains(choice) && !hasComposedAncestor(label, '[data-mp-no-track]') && isShown(label, group) && isVisible(label) && !isTransparent(label, group) && isComposedVisible(label) && showsText(label, option);
|
|
13169
|
+
});
|
|
13170
|
+
}
|
|
13030
13171
|
// Whether a group offers another answer to the question picked: a shown option
|
|
13031
13172
|
// to the same question that isn't part of the one picked. A card around one
|
|
13032
13173
|
// address radio and a "make default" checkbox, or around a role radio and the
|
|
@@ -13035,12 +13176,11 @@ var mParticle = (function () {
|
|
|
13035
13176
|
var options = group.querySelectorAll(CHOICE);
|
|
13036
13177
|
for (var i = 0; i < options.length; i++) {
|
|
13037
13178
|
var option = options[i];
|
|
13038
|
-
if (!option.contains(choice) && !choice.contains(option) && sameQuestion(option, choice) && isShown(option, group) && isVisible(option) &&
|
|
13039
|
-
// A fully transparent option, as a native input behind a
|
|
13040
|
-
// one often is, shows the shopper no second answer
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
}, group)) {
|
|
13179
|
+
if (!option.contains(choice) && !choice.contains(option) && (sameQuestion(option, choice) || unnamedOptionRows(option, choice, group)) && (isShown(option, group) && isVisible(option) && (
|
|
13180
|
+
// A fully transparent option, as a native input behind a
|
|
13181
|
+
// styled one often is, shows the shopper no second answer,
|
|
13182
|
+
// unless a shown row around it does.
|
|
13183
|
+
!isTransparent(option, group) || showsRow(option, choice, group)) || showsLabel(option, choice, group))) {
|
|
13044
13184
|
return true;
|
|
13045
13185
|
}
|
|
13046
13186
|
}
|
|
@@ -13058,35 +13198,72 @@ var mParticle = (function () {
|
|
|
13058
13198
|
});
|
|
13059
13199
|
return labels;
|
|
13060
13200
|
}
|
|
13061
|
-
// The group asking the question a pick answers. A role radio's
|
|
13062
|
-
// radiogroup and an option's its list box; a role toggle, such as
|
|
13063
|
-
// stands alone. A native box's is the nearest group offering other
|
|
13064
|
-
// since a group around one option, such as a saved address card, can
|
|
13065
|
-
// named by that option.
|
|
13066
|
-
|
|
13201
|
+
// The name of the group asking the question a pick answers. A role radio's
|
|
13202
|
+
// group is its radiogroup and an option's its list box; a role toggle, such as
|
|
13203
|
+
// a switch, stands alone. A native box's is the nearest group offering other
|
|
13204
|
+
// answers, since a group around one option, such as a saved address card, can
|
|
13205
|
+
// be named by that option. A region with no usable name is passed over, so a
|
|
13206
|
+
// group around it can still name the pick. Each group's name is read once.
|
|
13207
|
+
function groupName(choice) {
|
|
13067
13208
|
if (!(choice instanceof HTMLInputElement)) {
|
|
13068
13209
|
var container = choice.matches('[role~="option"]') ? choice.closest('[role="listbox"]') : choice.matches('[role~="radio"]') ? choice.closest('[role="radiogroup"]') : null;
|
|
13069
|
-
return container && holdsOptions(container, choice) ? container :
|
|
13210
|
+
return container && holdsOptions(container, choice) ? nameOf(container) : undefined;
|
|
13070
13211
|
}
|
|
13071
13212
|
var group = choice.closest(NAMED_GROUP);
|
|
13072
|
-
while (group
|
|
13213
|
+
while (group) {
|
|
13214
|
+
if (holdsOptions(group, choice)) {
|
|
13215
|
+
var name_2 = nameOf(group);
|
|
13216
|
+
if (name_2 || !group.matches('[role="region"]')) {
|
|
13217
|
+
return name_2;
|
|
13218
|
+
}
|
|
13219
|
+
}
|
|
13073
13220
|
group = group.parentElement ? group.parentElement.closest(NAMED_GROUP) : null;
|
|
13074
13221
|
}
|
|
13075
|
-
return
|
|
13222
|
+
return undefined;
|
|
13076
13223
|
}
|
|
13077
|
-
|
|
13078
|
-
|
|
13079
|
-
|
|
13080
|
-
|
|
13081
|
-
|
|
13224
|
+
// Whether what names a group is shown as its question: a fieldset's own
|
|
13225
|
+
// legend, or the header that opens a section. nameOf reads an aria-label first,
|
|
13226
|
+
// so a group carrying one is named by that instead.
|
|
13227
|
+
function showsQuestion(group) {
|
|
13228
|
+
if (group.tagName === 'FIELDSET') {
|
|
13229
|
+
return namedByLegend(group);
|
|
13230
|
+
}
|
|
13231
|
+
return !nonBlank(group.getAttribute('aria-label')) && opensRegion(group, labelledBy(group));
|
|
13232
|
+
}
|
|
13233
|
+
// A fieldset's own legend, a direct child, as the browser reads it.
|
|
13234
|
+
function legendOf(group) {
|
|
13235
|
+
return group.tagName === 'FIELDSET' ? Array.from(group.children).filter(function (child) {
|
|
13236
|
+
return child.tagName === 'LEGEND';
|
|
13237
|
+
})[0] : undefined;
|
|
13238
|
+
}
|
|
13239
|
+
// Whether a fieldset is named by its own legend, which nameOf reads only when
|
|
13240
|
+
// no aria-label overrides it and any aria-labelledby points at that legend.
|
|
13241
|
+
function namedByLegend(group) {
|
|
13242
|
+
var legend = legendOf(group);
|
|
13243
|
+
return !!legend && !nonBlank(group.getAttribute('aria-label')) && (!group.getAttribute('aria-labelledby') || labelledBy(group) === legend);
|
|
13244
|
+
}
|
|
13245
|
+
// The first element a group's aria-labelledby points at.
|
|
13246
|
+
function labelledBy(group) {
|
|
13247
|
+
var ids = group.getAttribute('aria-labelledby');
|
|
13248
|
+
var root = isFunction(group.getRootNode) ? group.getRootNode() : document;
|
|
13249
|
+
return ids && root.getElementById ? root.getElementById(ids.trim().split(/\s+/)[0]) : null;
|
|
13250
|
+
}
|
|
13251
|
+
// Whether a region is opened by this accordion header: a tab outside any tab
|
|
13252
|
+
// list, holding no control or option of its own.
|
|
13253
|
+
function opensRegion(group, header) {
|
|
13254
|
+
return !!header && group.matches('[role="region"]') && (header.getAttribute('role') || '').trim() === 'tab' && !hasComposedAncestor(header, '[role~="tablist"]') && !header.querySelector(NOT_A_QUESTION);
|
|
13255
|
+
}
|
|
13256
|
+
function nameOf(group) {
|
|
13082
13257
|
var raw = nonBlank(group.getAttribute('aria-label'));
|
|
13083
13258
|
if (!raw) {
|
|
13084
13259
|
var ids = group.getAttribute('aria-labelledby');
|
|
13085
|
-
var legend =
|
|
13086
|
-
return child.tagName === 'LEGEND';
|
|
13087
|
-
})[0] : undefined;
|
|
13260
|
+
var legend = legendOf(group);
|
|
13088
13261
|
var root_2 = isFunction(group.getRootNode) ? group.getRootNode() : document;
|
|
13089
|
-
var
|
|
13262
|
+
var target = ids ? labelledBy(group) : legend || null;
|
|
13263
|
+
// A region opened by an accordion header is named by the header's
|
|
13264
|
+
// first heading, never the rest of what it shows.
|
|
13265
|
+
var header_1 = ids && opensRegion(group, target) ? target : null;
|
|
13266
|
+
var source_1 = header_1 ? header_1.querySelector('h1, h2, h3, h4, h5, h6, [role="heading"]') : target;
|
|
13090
13267
|
// A label that is, holds or sits in an option or a control, or in an
|
|
13091
13268
|
// option's label, would name the answer.
|
|
13092
13269
|
var holder = source_1 ? source_1.closest('label') : null;
|
|
@@ -13097,7 +13274,9 @@ var mParticle = (function () {
|
|
|
13097
13274
|
return source_1.contains(label) || label.contains(source_1);
|
|
13098
13275
|
});
|
|
13099
13276
|
});
|
|
13100
|
-
raw = source_1 && !labelsOption && !
|
|
13277
|
+
raw = source_1 && !labelsOption && !someComposedAncestor(source_1, function (node) {
|
|
13278
|
+
return node !== header_1 && node.matches(NOT_A_QUESTION);
|
|
13279
|
+
}) && !source_1.querySelector(NOT_A_QUESTION) && !(holder && (holder.control || holder.querySelector(CHOICE))) ? textOf(source_1) : undefined;
|
|
13101
13280
|
}
|
|
13102
13281
|
return raw ? maskLabel(raw.split(':')[0]) : undefined;
|
|
13103
13282
|
}
|
|
@@ -13115,9 +13294,9 @@ var mParticle = (function () {
|
|
|
13115
13294
|
return PAYMENT_QUESTION.test(nameWords(words));
|
|
13116
13295
|
});
|
|
13117
13296
|
}
|
|
13118
|
-
// What names a payment option: the radio's accessible name
|
|
13119
|
-
// image of each label,
|
|
13120
|
-
function
|
|
13297
|
+
// What names a payment option to shoppers: the radio's accessible name and the
|
|
13298
|
+
// text and image of each label, masked like a label.
|
|
13299
|
+
function shownOptionNames(radio) {
|
|
13121
13300
|
var names = [maskLabel(accessibleName(radio).raw)];
|
|
13122
13301
|
var labels = radio instanceof HTMLInputElement && radio.labels ? Array.from(radio.labels).slice(0, 2) : [];
|
|
13123
13302
|
labels.forEach(function (label) {
|
|
@@ -13126,11 +13305,18 @@ var mParticle = (function () {
|
|
|
13126
13305
|
names.push(maskLabel(shownImageAlt(label)));
|
|
13127
13306
|
}
|
|
13128
13307
|
});
|
|
13129
|
-
names
|
|
13308
|
+
return names;
|
|
13309
|
+
}
|
|
13310
|
+
function distinctNames(names) {
|
|
13130
13311
|
return names.filter(function (name, index) {
|
|
13131
13312
|
return !!name && names.indexOf(name) === index;
|
|
13132
13313
|
});
|
|
13133
13314
|
}
|
|
13315
|
+
// What names a payment option: the names shoppers read, then its hand-written
|
|
13316
|
+
// ids.
|
|
13317
|
+
function optionNames(radio) {
|
|
13318
|
+
return distinctNames(shownOptionNames(radio).concat(stableIdentifier(radio.getAttribute('id')), firstIdentifier(radio, TEST_ID_ATTRIBUTES)));
|
|
13319
|
+
}
|
|
13134
13320
|
function describePaymentChoice(control, path) {
|
|
13135
13321
|
if (path === void 0) {
|
|
13136
13322
|
path = [];
|
|
@@ -13145,6 +13331,39 @@ var mParticle = (function () {
|
|
|
13145
13331
|
names: names
|
|
13146
13332
|
} : undefined;
|
|
13147
13333
|
}
|
|
13334
|
+
var CHECKED_RADIO = 'input[type="radio"]:checked, [role~="radio"][aria-checked="true"], [role~="menuitemradio"][aria-checked="true"]';
|
|
13335
|
+
// The payment radio the page holds checked, such as a card option checked by
|
|
13336
|
+
// default that the shopper never clicked. A page holding more than one option
|
|
13337
|
+
// names no single method, so it describes nothing. One option drawn twice
|
|
13338
|
+
// counts once: a role radio wrapping its native input, a hidden input a
|
|
13339
|
+
// component library keeps beside its role radio, or one group rendered for two
|
|
13340
|
+
// layouts, whose copies share the names shoppers read but not their ids. An
|
|
13341
|
+
// option shoppers see no name for is told apart by its ids.
|
|
13342
|
+
function describeCheckedPaymentChoice() {
|
|
13343
|
+
var radios = Array.from(document.querySelectorAll(CHECKED_RADIO)).filter(function (radio) {
|
|
13344
|
+
return isPicked(radio) && radio.getAttribute('aria-hidden') !== 'true' && !hasComposedAncestor(radio, '[data-mp-no-track]') && isPaymentQuestion(radio);
|
|
13345
|
+
});
|
|
13346
|
+
var choices = radios.filter(function (radio) {
|
|
13347
|
+
return !radios.some(function (other) {
|
|
13348
|
+
return other !== radio && radio.contains(other);
|
|
13349
|
+
});
|
|
13350
|
+
}).map(function (radio) {
|
|
13351
|
+
var shown = distinctNames(shownOptionNames(radio));
|
|
13352
|
+
var names = optionNames(radio);
|
|
13353
|
+
return {
|
|
13354
|
+
radio: radio,
|
|
13355
|
+
names: names,
|
|
13356
|
+
option: (shown.length ? shown : names).join('\n')
|
|
13357
|
+
};
|
|
13358
|
+
});
|
|
13359
|
+
var options = new Set(choices.map(function (choice) {
|
|
13360
|
+
return choice.option;
|
|
13361
|
+
}));
|
|
13362
|
+
return options.size === 1 && choices[0].names.length ? {
|
|
13363
|
+
radio: choices[0].radio,
|
|
13364
|
+
names: choices[0].names
|
|
13365
|
+
} : undefined;
|
|
13366
|
+
}
|
|
13148
13367
|
// Read once the page has handled the click, which may have cancelled it.
|
|
13149
13368
|
function isPicked(radio) {
|
|
13150
13369
|
return radio instanceof HTMLInputElement ? radio.checked : radio.getAttribute('aria-checked') === 'true';
|
|
@@ -13191,6 +13410,9 @@ var mParticle = (function () {
|
|
|
13191
13410
|
var walletPhrases = new RegExp('^(?:(?:' + WALLET_VERBS + ')(?: now| securely)? (?:with|using|via|through|by) (?:' + WALLET_NAMES + ')(?: express(?: checkout)?| checkout)?|(?:continue|proceed|go) (?:to|with) (?:' + WALLET_NAMES + '))$');
|
|
13192
13411
|
// A wallet's own name on a button: "PayPal", "Klarna checkout", "Apple Pay logo".
|
|
13193
13412
|
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))*)?$');
|
|
13413
|
+
// The wallets the Rokt kit reads from a click's label or identifiers, as words:
|
|
13414
|
+
// "Place order with PayPal!" and "paypal-pay-button" both name PayPal.
|
|
13415
|
+
var KIT_WALLET_WORDS = /(?:^| )(?:apple ?pay|google ?pay|g ?pay|android ?pay|venmo|pay ?pal|amazon ?pay|shop ?pay|klarna|after ?pay|clear ?pay|affirm|cash ?app|sezzle|samsung ?pay)(?= |$)/;
|
|
13194
13416
|
// Exact HTTPS hosts of hosted wallet button frames.
|
|
13195
13417
|
var walletFrameFamilies = {
|
|
13196
13418
|
'pay.google.com': 'google_pay',
|
|
@@ -13394,6 +13616,24 @@ var mParticle = (function () {
|
|
|
13394
13616
|
}
|
|
13395
13617
|
return cart;
|
|
13396
13618
|
}
|
|
13619
|
+
// The Rokt kit's own word split, so "PayPal!" and "paypal2" both read as
|
|
13620
|
+
// "paypal" here as they do there.
|
|
13621
|
+
function kitWords(value) {
|
|
13622
|
+
return (value || '').replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase().replace(/[^a-z]+/g, ' ').trim();
|
|
13623
|
+
}
|
|
13624
|
+
// A confirm control may name its wallet, so "Place order with PayPal" and a
|
|
13625
|
+
// "Place order" button with id paypal-pay-button are confirm clicks that still
|
|
13626
|
+
// name their own method. A logged click is judged on the fields the kit reads
|
|
13627
|
+
// a method from; a click that isn't logged, on the control's own label and
|
|
13628
|
+
// identifiers.
|
|
13629
|
+
function namesWallet(control, click) {
|
|
13630
|
+
var values = click ? [click.label, click.ariaLabel, click.elementId, click.elementName, click.testId] : labelSources(control).concat(['id', 'name'].concat(TEST_ID_ATTRIBUTES).map(function (attribute) {
|
|
13631
|
+
return control.getAttribute(attribute);
|
|
13632
|
+
}));
|
|
13633
|
+
return values.some(function (value) {
|
|
13634
|
+
return KIT_WALLET_WORDS.test(kitWords(value));
|
|
13635
|
+
});
|
|
13636
|
+
}
|
|
13397
13637
|
// The host is the domain or one of its subdomains, never a look-alike suffix.
|
|
13398
13638
|
function isOnDomain(host, domain) {
|
|
13399
13639
|
return host === domain || host.length > domain.length && host.slice(host.length - domain.length - 1) === '.' + domain;
|
|
@@ -13588,8 +13828,9 @@ var mParticle = (function () {
|
|
|
13588
13828
|
// Bumped on reset so classification queued before it is dropped.
|
|
13589
13829
|
this.generation = 0;
|
|
13590
13830
|
this.lastCommitClick = -Infinity;
|
|
13591
|
-
// The latest trusted click: whether the page excluded it
|
|
13592
|
-
// already carries to the kit, with its
|
|
13831
|
+
// The latest trusted click: whether the page excluded it or it was withheld
|
|
13832
|
+
// from the kit, and the intent it already carries to the kit, with its
|
|
13833
|
+
// source, if any.
|
|
13593
13834
|
this.lastClick = null;
|
|
13594
13835
|
this.lastSent = {};
|
|
13595
13836
|
this.pagePath = null;
|
|
@@ -13768,6 +14009,7 @@ var mParticle = (function () {
|
|
|
13768
14009
|
var source;
|
|
13769
14010
|
var adds;
|
|
13770
14011
|
var choice;
|
|
14012
|
+
var checkedNames;
|
|
13771
14013
|
var family;
|
|
13772
14014
|
var unconfirmedCommit = false;
|
|
13773
14015
|
if (layer === 'click') {
|
|
@@ -13776,11 +14018,19 @@ var mParticle = (function () {
|
|
|
13776
14018
|
var excluded = isExcludedPath(path);
|
|
13777
14019
|
var control = excluded ? undefined : findControl(path, true);
|
|
13778
14020
|
var logged = control || (excluded ? undefined : findControl(path, true, PATH_LIMIT) || findRoleControl(path, PATH_LIMIT));
|
|
14021
|
+
// A click that link tracking logs as Auto Link Click gives the kit no
|
|
14022
|
+
// intent when the Rokt connection does not receive those events.
|
|
14023
|
+
var withheld = false;
|
|
13779
14024
|
if (logged) {
|
|
13780
14025
|
// With links alone, only an anchor can be logged.
|
|
13781
|
-
|
|
14026
|
+
var logsThis = logsEvents && (this.logButtons || logged.matches('a[href]'));
|
|
14027
|
+
var linksWithheld = signalsKit && this.logLinks && !this.linkClicksReachKit();
|
|
14028
|
+
var described = logsThis || linksWithheld ? describeButtonClick(logged, path) : undefined;
|
|
14029
|
+
var linkClick = this.logLinks && !!described && isLinkClick(described);
|
|
14030
|
+
withheld = linksWithheld && linkClick;
|
|
14031
|
+
click = logsThis ? described : undefined;
|
|
13782
14032
|
if (click) {
|
|
13783
|
-
asLink =
|
|
14033
|
+
asLink = linkClick;
|
|
13784
14034
|
// Without link tracking, a link that leaves the page stays a
|
|
13785
14035
|
// button click, except a plain link to another page of the
|
|
13786
14036
|
// site, which button tracking never logged.
|
|
@@ -13793,17 +14043,28 @@ var mParticle = (function () {
|
|
|
13793
14043
|
box = logged;
|
|
13794
14044
|
}
|
|
13795
14045
|
}
|
|
13796
|
-
if (control) {
|
|
14046
|
+
if (control && !withheld) {
|
|
13797
14047
|
// Checkout intent is only worked out when the kit can use it.
|
|
13798
14048
|
var intent = signalsKit ? classifyIntent(control, pathname) : undefined;
|
|
13799
14049
|
kind = intent ? intent.kind : undefined;
|
|
13800
14050
|
source = intent ? intent.source : undefined;
|
|
13801
14051
|
adds = intent ? intent.adds : undefined;
|
|
13802
14052
|
choice = signalsKit ? describePaymentChoice(control, path) : undefined;
|
|
13803
|
-
|
|
14053
|
+
// A confirm or checkout-step click picks no radio itself, so it
|
|
14054
|
+
// carries the one the page holds checked as read here. It is not
|
|
14055
|
+
// read again at delivery: the page's own handlers may clear or
|
|
14056
|
+
// replace it by then. A wallet tap names its own method, and
|
|
14057
|
+
// so does a confirm that names a wallet.
|
|
14058
|
+
if (!choice && (kind === 'commit' || kind === 'checkout_step') && !namesWallet(control, click)) {
|
|
14059
|
+
var checked = describeCheckedPaymentChoice();
|
|
14060
|
+
checkedNames = checked ? checked.names : undefined;
|
|
14061
|
+
}
|
|
14062
|
+
}
|
|
14063
|
+
// A withheld click cannot start an Apple Pay session for the kit
|
|
14064
|
+
// either.
|
|
13804
14065
|
this.lastClick = {
|
|
13805
14066
|
t: t,
|
|
13806
|
-
excluded: excluded,
|
|
14067
|
+
excluded: excluded || withheld,
|
|
13807
14068
|
kind: kind,
|
|
13808
14069
|
source: source
|
|
13809
14070
|
};
|
|
@@ -13854,6 +14115,8 @@ var mParticle = (function () {
|
|
|
13854
14115
|
// with this pick.
|
|
13855
14116
|
if (choice && isPicked(choice.radio)) {
|
|
13856
14117
|
_this.pickPayment(t, pathname, choice.names);
|
|
14118
|
+
} else if (checkedNames) {
|
|
14119
|
+
_this.pickPayment(t, pathname, checkedNames);
|
|
13857
14120
|
} else if (family) {
|
|
13858
14121
|
_this.pickPayment(t, pathname, undefined, family);
|
|
13859
14122
|
}
|
|
@@ -13944,6 +14207,10 @@ var mParticle = (function () {
|
|
|
13944
14207
|
var roktManager = this.mpInstance._RoktManager;
|
|
13945
14208
|
return !this.hasRoktKit || !roktManager || roktManager.isCheckoutIntentSuppressed();
|
|
13946
14209
|
};
|
|
14210
|
+
ButtonTracker.prototype.linkClicksReachKit = function () {
|
|
14211
|
+
var roktManager = this.mpInstance._RoktManager;
|
|
14212
|
+
return !!roktManager && roktManager.areAutoLinkClicksForwarded();
|
|
14213
|
+
};
|
|
13947
14214
|
ButtonTracker.prototype.log = function (message) {
|
|
13948
14215
|
this.mpInstance.Logger.verbose('mParticle button tracking: ' + message);
|
|
13949
14216
|
};
|
|
@@ -14902,6 +15169,7 @@ var mParticle = (function () {
|
|
|
14902
15169
|
// Button tracking never runs as a native passthrough.
|
|
14903
15170
|
resetButtonTracking();
|
|
14904
15171
|
mpInstance._RoktManager.setAutoButtonClicksForwarded(false);
|
|
15172
|
+
mpInstance._RoktManager.setAutoLinkClicksForwarded(false);
|
|
14905
15173
|
} else {
|
|
14906
15174
|
// Main SDK initialization flow
|
|
14907
15175
|
// Load any settings/identities/attributes from cookie or localStorage
|
|
@@ -14952,14 +15220,15 @@ var mParticle = (function () {
|
|
|
14952
15220
|
// init or from a returning shopper's landing page view.
|
|
14953
15221
|
var logButtons = !!getFeatureFlag(AutoButtonTracking);
|
|
14954
15222
|
var logLinks = !!getFeatureFlag(AutoLinkTracking);
|
|
14955
|
-
//
|
|
14956
|
-
//
|
|
15223
|
+
// With link tracking on, a click logged as Auto Link Click feeds intent
|
|
15224
|
+
// only when the kit also receives those events; button clicks still do.
|
|
14957
15225
|
var buttonClickBlocker = roktConfig_1 ? getButtonClickBlocker(roktConfig_1, kitBlocker) : undefined;
|
|
14958
15226
|
var linkClickBlocker = roktConfig_1 && logLinks ? getButtonClickBlocker(roktConfig_1, kitBlocker, true) : undefined;
|
|
14959
15227
|
if (logButtons && (buttonClickBlocker || linkClickBlocker)) {
|
|
14960
|
-
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
|
|
15228
|
+
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 skips link clicks: the ".concat(linkClickBlocker, " keeps some or all Auto Link Click events from the Rokt kit."));
|
|
14961
15229
|
}
|
|
14962
|
-
mpInstance._RoktManager.setAutoButtonClicksForwarded(!!roktConfig_1 && !buttonClickBlocker
|
|
15230
|
+
mpInstance._RoktManager.setAutoButtonClicksForwarded(!!roktConfig_1 && !buttonClickBlocker);
|
|
15231
|
+
mpInstance._RoktManager.setAutoLinkClicksForwarded(!!roktConfig_1 && !linkClickBlocker);
|
|
14963
15232
|
mpInstance._Forwarders.processForwarders(config, mpInstance._APIClient.prepareForwardingStats);
|
|
14964
15233
|
mpInstance._Forwarders.processPixelConfigs(config);
|
|
14965
15234
|
// Checks if session is created, resumed, or needs to be ended
|
|
@@ -20,6 +20,7 @@ export interface IButtonClick {
|
|
|
20
20
|
fileExtension?: string;
|
|
21
21
|
checked?: boolean;
|
|
22
22
|
}
|
|
23
|
+
export declare const TEST_ID_ATTRIBUTES: string[];
|
|
23
24
|
export declare function isLinkClick(click: IButtonClick): boolean;
|
|
24
25
|
export declare function describeButtonClick(control: Element, path?: Array<EventTarget | null>): IButtonClick | undefined;
|
|
25
26
|
export interface IPaymentChoice {
|
|
@@ -27,4 +28,5 @@ export interface IPaymentChoice {
|
|
|
27
28
|
names: string[];
|
|
28
29
|
}
|
|
29
30
|
export declare function describePaymentChoice(control: Element, path?: Array<EventTarget | null>): IPaymentChoice | undefined;
|
|
31
|
+
export declare function describeCheckedPaymentChoice(): IPaymentChoice | undefined;
|
|
30
32
|
export declare function isPicked(radio: Element): boolean;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IButtonClick } from './buttonDescription';
|
|
1
2
|
export type CheckoutIntentKind = 'commit' | 'wallet' | 'checkout_step' | 'frame' | 'cart';
|
|
2
3
|
export type PaymentFrameFamily = 'apple_pay' | 'google_pay' | 'amazon_pay' | 'shop_pay' | 'card';
|
|
3
4
|
export type CheckoutIntentSource = 'vendor' | 'label' | 'brand' | 'frame' | 'submit' | 'name' | 'api';
|
|
@@ -7,6 +8,7 @@ export interface ICheckoutIntent {
|
|
|
7
8
|
adds?: true;
|
|
8
9
|
}
|
|
9
10
|
export declare function classifyIntent(control: Element, pathname: string): ICheckoutIntent | undefined;
|
|
11
|
+
export declare function namesWallet(control: Element, click?: IButtonClick): boolean;
|
|
10
12
|
export declare function classifyIntentControl(control: Element, pathname: string): Exclude<CheckoutIntentKind, 'frame'> | undefined;
|
|
11
13
|
export interface IPaymentFrame {
|
|
12
14
|
kind: 'wallet' | 'frame';
|
|
@@ -111,6 +111,7 @@ export default class RoktManager {
|
|
|
111
111
|
private stopRouteChangeWatch;
|
|
112
112
|
private pendingCheckoutIntents;
|
|
113
113
|
private autoButtonClicksForwarded;
|
|
114
|
+
private autoLinkClicksForwarded;
|
|
114
115
|
constructor(instanceName?: string);
|
|
115
116
|
/**
|
|
116
117
|
* Sets a callback to be invoked when RoktManager becomes ready
|
|
@@ -137,6 +138,8 @@ export default class RoktManager {
|
|
|
137
138
|
private watchRouteChanges;
|
|
138
139
|
private notifyRouteChange;
|
|
139
140
|
setAutoButtonClicksForwarded(forwarded: boolean): void;
|
|
141
|
+
setAutoLinkClicksForwarded(forwarded: boolean): void;
|
|
142
|
+
areAutoLinkClicksForwarded(): boolean;
|
|
140
143
|
hasTargetingOptOut(): boolean;
|
|
141
144
|
isCheckoutIntentSuppressed(): boolean;
|
|
142
145
|
isCheckoutIntentLive(): boolean;
|