@economist/web-apple-pay 0.1.3-beta.37 → 0.1.3-beta.39
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/index.js +36 -40
- package/dist/src/apple-pay-button.js +36 -40
- package/dist/src/apple-pay-button.stories.js +36 -40
- package/dist/src/apple-pay-modal.stories.js +36 -40
- package/dist/src/clients/payment-checkout/detects.js +5 -25
- package/dist/src/clients/payment-checkout/payment-handler.js +12 -6
- package/dist/src/index.js +36 -40
- package/dist/src/utils/expressCheckoutTracking.d.ts +4 -4
- package/dist/src/utils/expressCheckoutTracking.js +14 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1120,52 +1120,32 @@ var isAppleDeviceOrSafari = () => {
|
|
|
1120
1120
|
const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
|
|
1121
1121
|
return isIOSOrMacTouchDevice || isSafariBrowser;
|
|
1122
1122
|
};
|
|
1123
|
-
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null;
|
|
1123
|
+
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null && getApplePayConfig()?.debugBypassEnabled === true;
|
|
1124
1124
|
var isApplePayAvailable = async () => {
|
|
1125
1125
|
if (bypassApplePayChecks()) {
|
|
1126
|
-
console.log("[ApplePay] bypass active \u2014 displaying button");
|
|
1127
1126
|
return true;
|
|
1128
1127
|
}
|
|
1129
|
-
|
|
1130
|
-
const isAppleDevice = isAppleDeviceOrSafari();
|
|
1131
|
-
console.log("[ApplePay] detection:", JSON.stringify({
|
|
1132
|
-
applePaySessionExists: !!applePaySession,
|
|
1133
|
-
isAppleDevice,
|
|
1134
|
-
userAgent: navigator.userAgent,
|
|
1135
|
-
maxTouchPoints: navigator.maxTouchPoints
|
|
1136
|
-
}, null, 2));
|
|
1137
|
-
if (!applePaySession && !isAppleDevice) {
|
|
1138
|
-
console.log("[ApplePay] not available \u2014 no ApplePaySession and not Apple device");
|
|
1128
|
+
if (!isAppleDeviceOrSafari()) {
|
|
1139
1129
|
return false;
|
|
1140
1130
|
}
|
|
1131
|
+
const applePaySession = window.ApplePaySession;
|
|
1141
1132
|
if (!applePaySession) {
|
|
1142
|
-
console.log("[ApplePay] not available \u2014 Apple device but no ApplePaySession API");
|
|
1143
1133
|
return false;
|
|
1144
1134
|
}
|
|
1145
1135
|
try {
|
|
1146
1136
|
if (typeof applePaySession.canMakePayments !== "function") {
|
|
1147
|
-
console.log("[ApplePay] not available \u2014 canMakePayments is not a function");
|
|
1148
1137
|
return false;
|
|
1149
1138
|
}
|
|
1150
1139
|
if (!applePaySession.canMakePayments()) {
|
|
1151
|
-
console.log("[ApplePay] not available \u2014 canMakePayments returned false");
|
|
1152
1140
|
return false;
|
|
1153
1141
|
}
|
|
1154
1142
|
const merchantId = getApplePayConfig()?.merchantId;
|
|
1155
1143
|
if (!merchantId) {
|
|
1156
|
-
console.log("[ApplePay] not available \u2014 no merchantId configured");
|
|
1157
1144
|
return false;
|
|
1158
1145
|
}
|
|
1159
1146
|
const hasActiveCard = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
console.log("[ApplePay] not available \u2014 no active card for merchant");
|
|
1163
|
-
return false;
|
|
1164
|
-
}
|
|
1165
|
-
console.log("[ApplePay] available \u2014 displaying button");
|
|
1166
|
-
return true;
|
|
1167
|
-
} catch (error) {
|
|
1168
|
-
console.log("[ApplePay] not available \u2014 error:", JSON.stringify({ error: String(error) }, null, 2));
|
|
1147
|
+
return hasActiveCard;
|
|
1148
|
+
} catch {
|
|
1169
1149
|
return false;
|
|
1170
1150
|
}
|
|
1171
1151
|
};
|
|
@@ -1338,17 +1318,21 @@ var track = (action, extra) => {
|
|
|
1338
1318
|
...extra
|
|
1339
1319
|
});
|
|
1340
1320
|
};
|
|
1341
|
-
var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
1321
|
+
var trackExpressWalletImpression = (skuId, { entryPoint, country }, buttonLoadDurationMs) => {
|
|
1342
1322
|
track(EXPRESS_CHECKOUT_EVENTS.IMPRESSION, {
|
|
1343
1323
|
wallet_type: "apple_pay",
|
|
1344
1324
|
entry_point: entryPoint,
|
|
1345
1325
|
sku_id: skuId,
|
|
1346
1326
|
country,
|
|
1347
|
-
device: getDevice()
|
|
1327
|
+
device: getDevice(),
|
|
1328
|
+
...buttonLoadDurationMs !== void 0 && { button_load_duration_ms: buttonLoadDurationMs }
|
|
1348
1329
|
});
|
|
1349
1330
|
};
|
|
1350
|
-
var trackExpressWalletClick = (skuId) => {
|
|
1351
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1331
|
+
var trackExpressWalletClick = (skuId, modalRenderDurationMs) => {
|
|
1332
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1333
|
+
sku_id: skuId,
|
|
1334
|
+
...modalRenderDurationMs !== void 0 && { modal_render_duration_ms: modalRenderDurationMs }
|
|
1335
|
+
});
|
|
1352
1336
|
};
|
|
1353
1337
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1354
1338
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -1356,16 +1340,18 @@ var trackWalletPaymentSheetOpen = (skuId) => {
|
|
|
1356
1340
|
var trackWalletPaymentAuthorised = (skuId) => {
|
|
1357
1341
|
track(EXPRESS_CHECKOUT_EVENTS.AUTHORISED, { sku_id: skuId });
|
|
1358
1342
|
};
|
|
1359
|
-
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
1343
|
+
var trackWalletPaymentSuccess = (skuId, basketId, purchaseDurationMs) => {
|
|
1360
1344
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
1361
1345
|
sku_id: skuId,
|
|
1362
|
-
basket_id: basketId
|
|
1346
|
+
basket_id: basketId,
|
|
1347
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1363
1348
|
});
|
|
1364
1349
|
};
|
|
1365
|
-
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
1350
|
+
var trackWalletPaymentFailure = (skuId, reason, purchaseDurationMs) => {
|
|
1366
1351
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
1367
1352
|
sku_id: skuId,
|
|
1368
|
-
failure_reason: reason
|
|
1353
|
+
failure_reason: reason,
|
|
1354
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1369
1355
|
});
|
|
1370
1356
|
};
|
|
1371
1357
|
var trackFallbackCheckout = (skuId) => {
|
|
@@ -1627,12 +1613,14 @@ function handleStructuredError(ctx) {
|
|
|
1627
1613
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
1628
1614
|
const { skuId, returnUrl, country } = config;
|
|
1629
1615
|
let validatedEmail;
|
|
1616
|
+
let purchaseStartTime;
|
|
1630
1617
|
try {
|
|
1631
1618
|
validatedEmail = validateContacts(
|
|
1632
1619
|
event,
|
|
1633
1620
|
sessionData,
|
|
1634
1621
|
config.supportedBillingCountries
|
|
1635
1622
|
);
|
|
1623
|
+
purchaseStartTime = Date.now();
|
|
1636
1624
|
const result = await performPurchase({
|
|
1637
1625
|
applePayToken: event.payment.token,
|
|
1638
1626
|
skuId: config.skuId,
|
|
@@ -1643,7 +1631,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1643
1631
|
},
|
|
1644
1632
|
recaptchaTokens: config.recaptchaTokens
|
|
1645
1633
|
});
|
|
1646
|
-
|
|
1634
|
+
const purchaseDurationMs = Date.now() - purchaseStartTime;
|
|
1635
|
+
trackWalletPaymentSuccess(skuId, result.basketId, purchaseDurationMs);
|
|
1647
1636
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1648
1637
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
1649
1638
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
@@ -1661,7 +1650,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1661
1650
|
return;
|
|
1662
1651
|
}
|
|
1663
1652
|
const walletError = parseWalletApiError(err);
|
|
1664
|
-
|
|
1653
|
+
const purchaseDurationMs = purchaseStartTime !== void 0 ? Date.now() - purchaseStartTime : void 0;
|
|
1654
|
+
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN", purchaseDurationMs);
|
|
1665
1655
|
failApplePaySession(session);
|
|
1666
1656
|
if (!walletError) {
|
|
1667
1657
|
redirectFallback(skuId, returnUrl, country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
@@ -1984,6 +1974,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1984
1974
|
#country = "";
|
|
1985
1975
|
#rendering = false;
|
|
1986
1976
|
#readyPromise = null;
|
|
1977
|
+
#loadStartTime = 0;
|
|
1987
1978
|
#sessionData = null;
|
|
1988
1979
|
#paymentOptions = null;
|
|
1989
1980
|
#returnUrl = "";
|
|
@@ -2059,6 +2050,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2059
2050
|
}
|
|
2060
2051
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
2061
2052
|
async #run() {
|
|
2053
|
+
this.#loadStartTime = Date.now();
|
|
2062
2054
|
try {
|
|
2063
2055
|
this.#renderTemplate();
|
|
2064
2056
|
if (await this.#checkAvailability()) return;
|
|
@@ -2158,10 +2150,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2158
2150
|
button.classList.remove("wap-loading");
|
|
2159
2151
|
this.#updateDisabledState();
|
|
2160
2152
|
this.#scheduleRecaptchaTokens();
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2153
|
+
const buttonLoadDurationMs = Date.now() - this.#loadStartTime;
|
|
2154
|
+
trackExpressWalletImpression(
|
|
2155
|
+
this.#offer.sku_id,
|
|
2156
|
+
{ entryPoint: this.#entryPoint, country: this.#country },
|
|
2157
|
+
buttonLoadDurationMs
|
|
2158
|
+
);
|
|
2165
2159
|
}
|
|
2166
2160
|
}
|
|
2167
2161
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
@@ -2184,7 +2178,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2184
2178
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2185
2179
|
return;
|
|
2186
2180
|
}
|
|
2187
|
-
|
|
2181
|
+
const modalOpenStart = Date.now();
|
|
2188
2182
|
ApplePayModal.define();
|
|
2189
2183
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2190
2184
|
modal.offer = this.#offer;
|
|
@@ -2199,6 +2193,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2199
2193
|
this.#scheduleRecaptchaTokens();
|
|
2200
2194
|
};
|
|
2201
2195
|
modal.open(this.#recaptchaTokensPromise);
|
|
2196
|
+
const modalRenderDurationMs = Date.now() - modalOpenStart;
|
|
2197
|
+
trackExpressWalletClick(skuId, modalRenderDurationMs);
|
|
2202
2198
|
}
|
|
2203
2199
|
/**
|
|
2204
2200
|
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
@@ -1115,52 +1115,32 @@ var isAppleDeviceOrSafari = () => {
|
|
|
1115
1115
|
const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
|
|
1116
1116
|
return isIOSOrMacTouchDevice || isSafariBrowser;
|
|
1117
1117
|
};
|
|
1118
|
-
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null;
|
|
1118
|
+
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null && getApplePayConfig()?.debugBypassEnabled === true;
|
|
1119
1119
|
var isApplePayAvailable = async () => {
|
|
1120
1120
|
if (bypassApplePayChecks()) {
|
|
1121
|
-
console.log("[ApplePay] bypass active \u2014 displaying button");
|
|
1122
1121
|
return true;
|
|
1123
1122
|
}
|
|
1124
|
-
|
|
1125
|
-
const isAppleDevice = isAppleDeviceOrSafari();
|
|
1126
|
-
console.log("[ApplePay] detection:", JSON.stringify({
|
|
1127
|
-
applePaySessionExists: !!applePaySession,
|
|
1128
|
-
isAppleDevice,
|
|
1129
|
-
userAgent: navigator.userAgent,
|
|
1130
|
-
maxTouchPoints: navigator.maxTouchPoints
|
|
1131
|
-
}, null, 2));
|
|
1132
|
-
if (!applePaySession && !isAppleDevice) {
|
|
1133
|
-
console.log("[ApplePay] not available \u2014 no ApplePaySession and not Apple device");
|
|
1123
|
+
if (!isAppleDeviceOrSafari()) {
|
|
1134
1124
|
return false;
|
|
1135
1125
|
}
|
|
1126
|
+
const applePaySession = window.ApplePaySession;
|
|
1136
1127
|
if (!applePaySession) {
|
|
1137
|
-
console.log("[ApplePay] not available \u2014 Apple device but no ApplePaySession API");
|
|
1138
1128
|
return false;
|
|
1139
1129
|
}
|
|
1140
1130
|
try {
|
|
1141
1131
|
if (typeof applePaySession.canMakePayments !== "function") {
|
|
1142
|
-
console.log("[ApplePay] not available \u2014 canMakePayments is not a function");
|
|
1143
1132
|
return false;
|
|
1144
1133
|
}
|
|
1145
1134
|
if (!applePaySession.canMakePayments()) {
|
|
1146
|
-
console.log("[ApplePay] not available \u2014 canMakePayments returned false");
|
|
1147
1135
|
return false;
|
|
1148
1136
|
}
|
|
1149
1137
|
const merchantId = getApplePayConfig()?.merchantId;
|
|
1150
1138
|
if (!merchantId) {
|
|
1151
|
-
console.log("[ApplePay] not available \u2014 no merchantId configured");
|
|
1152
1139
|
return false;
|
|
1153
1140
|
}
|
|
1154
1141
|
const hasActiveCard = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
console.log("[ApplePay] not available \u2014 no active card for merchant");
|
|
1158
|
-
return false;
|
|
1159
|
-
}
|
|
1160
|
-
console.log("[ApplePay] available \u2014 displaying button");
|
|
1161
|
-
return true;
|
|
1162
|
-
} catch (error) {
|
|
1163
|
-
console.log("[ApplePay] not available \u2014 error:", JSON.stringify({ error: String(error) }, null, 2));
|
|
1142
|
+
return hasActiveCard;
|
|
1143
|
+
} catch {
|
|
1164
1144
|
return false;
|
|
1165
1145
|
}
|
|
1166
1146
|
};
|
|
@@ -1333,17 +1313,21 @@ var track = (action, extra) => {
|
|
|
1333
1313
|
...extra
|
|
1334
1314
|
});
|
|
1335
1315
|
};
|
|
1336
|
-
var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
1316
|
+
var trackExpressWalletImpression = (skuId, { entryPoint, country }, buttonLoadDurationMs) => {
|
|
1337
1317
|
track(EXPRESS_CHECKOUT_EVENTS.IMPRESSION, {
|
|
1338
1318
|
wallet_type: "apple_pay",
|
|
1339
1319
|
entry_point: entryPoint,
|
|
1340
1320
|
sku_id: skuId,
|
|
1341
1321
|
country,
|
|
1342
|
-
device: getDevice()
|
|
1322
|
+
device: getDevice(),
|
|
1323
|
+
...buttonLoadDurationMs !== void 0 && { button_load_duration_ms: buttonLoadDurationMs }
|
|
1343
1324
|
});
|
|
1344
1325
|
};
|
|
1345
|
-
var trackExpressWalletClick = (skuId) => {
|
|
1346
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1326
|
+
var trackExpressWalletClick = (skuId, modalRenderDurationMs) => {
|
|
1327
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1328
|
+
sku_id: skuId,
|
|
1329
|
+
...modalRenderDurationMs !== void 0 && { modal_render_duration_ms: modalRenderDurationMs }
|
|
1330
|
+
});
|
|
1347
1331
|
};
|
|
1348
1332
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1349
1333
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -1351,16 +1335,18 @@ var trackWalletPaymentSheetOpen = (skuId) => {
|
|
|
1351
1335
|
var trackWalletPaymentAuthorised = (skuId) => {
|
|
1352
1336
|
track(EXPRESS_CHECKOUT_EVENTS.AUTHORISED, { sku_id: skuId });
|
|
1353
1337
|
};
|
|
1354
|
-
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
1338
|
+
var trackWalletPaymentSuccess = (skuId, basketId, purchaseDurationMs) => {
|
|
1355
1339
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
1356
1340
|
sku_id: skuId,
|
|
1357
|
-
basket_id: basketId
|
|
1341
|
+
basket_id: basketId,
|
|
1342
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1358
1343
|
});
|
|
1359
1344
|
};
|
|
1360
|
-
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
1345
|
+
var trackWalletPaymentFailure = (skuId, reason, purchaseDurationMs) => {
|
|
1361
1346
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
1362
1347
|
sku_id: skuId,
|
|
1363
|
-
failure_reason: reason
|
|
1348
|
+
failure_reason: reason,
|
|
1349
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1364
1350
|
});
|
|
1365
1351
|
};
|
|
1366
1352
|
var trackFallbackCheckout = (skuId) => {
|
|
@@ -1622,12 +1608,14 @@ function handleStructuredError(ctx) {
|
|
|
1622
1608
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
1623
1609
|
const { skuId, returnUrl, country } = config;
|
|
1624
1610
|
let validatedEmail;
|
|
1611
|
+
let purchaseStartTime;
|
|
1625
1612
|
try {
|
|
1626
1613
|
validatedEmail = validateContacts(
|
|
1627
1614
|
event,
|
|
1628
1615
|
sessionData,
|
|
1629
1616
|
config.supportedBillingCountries
|
|
1630
1617
|
);
|
|
1618
|
+
purchaseStartTime = Date.now();
|
|
1631
1619
|
const result = await performPurchase({
|
|
1632
1620
|
applePayToken: event.payment.token,
|
|
1633
1621
|
skuId: config.skuId,
|
|
@@ -1638,7 +1626,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1638
1626
|
},
|
|
1639
1627
|
recaptchaTokens: config.recaptchaTokens
|
|
1640
1628
|
});
|
|
1641
|
-
|
|
1629
|
+
const purchaseDurationMs = Date.now() - purchaseStartTime;
|
|
1630
|
+
trackWalletPaymentSuccess(skuId, result.basketId, purchaseDurationMs);
|
|
1642
1631
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1643
1632
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
1644
1633
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
@@ -1656,7 +1645,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1656
1645
|
return;
|
|
1657
1646
|
}
|
|
1658
1647
|
const walletError = parseWalletApiError(err);
|
|
1659
|
-
|
|
1648
|
+
const purchaseDurationMs = purchaseStartTime !== void 0 ? Date.now() - purchaseStartTime : void 0;
|
|
1649
|
+
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN", purchaseDurationMs);
|
|
1660
1650
|
failApplePaySession(session);
|
|
1661
1651
|
if (!walletError) {
|
|
1662
1652
|
redirectFallback(skuId, returnUrl, country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
@@ -1979,6 +1969,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1979
1969
|
#country = "";
|
|
1980
1970
|
#rendering = false;
|
|
1981
1971
|
#readyPromise = null;
|
|
1972
|
+
#loadStartTime = 0;
|
|
1982
1973
|
#sessionData = null;
|
|
1983
1974
|
#paymentOptions = null;
|
|
1984
1975
|
#returnUrl = "";
|
|
@@ -2054,6 +2045,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2054
2045
|
}
|
|
2055
2046
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
2056
2047
|
async #run() {
|
|
2048
|
+
this.#loadStartTime = Date.now();
|
|
2057
2049
|
try {
|
|
2058
2050
|
this.#renderTemplate();
|
|
2059
2051
|
if (await this.#checkAvailability()) return;
|
|
@@ -2153,10 +2145,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2153
2145
|
button.classList.remove("wap-loading");
|
|
2154
2146
|
this.#updateDisabledState();
|
|
2155
2147
|
this.#scheduleRecaptchaTokens();
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2148
|
+
const buttonLoadDurationMs = Date.now() - this.#loadStartTime;
|
|
2149
|
+
trackExpressWalletImpression(
|
|
2150
|
+
this.#offer.sku_id,
|
|
2151
|
+
{ entryPoint: this.#entryPoint, country: this.#country },
|
|
2152
|
+
buttonLoadDurationMs
|
|
2153
|
+
);
|
|
2160
2154
|
}
|
|
2161
2155
|
}
|
|
2162
2156
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
@@ -2179,7 +2173,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2179
2173
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2180
2174
|
return;
|
|
2181
2175
|
}
|
|
2182
|
-
|
|
2176
|
+
const modalOpenStart = Date.now();
|
|
2183
2177
|
ApplePayModal.define();
|
|
2184
2178
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2185
2179
|
modal.offer = this.#offer;
|
|
@@ -2194,6 +2188,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2194
2188
|
this.#scheduleRecaptchaTokens();
|
|
2195
2189
|
};
|
|
2196
2190
|
modal.open(this.#recaptchaTokensPromise);
|
|
2191
|
+
const modalRenderDurationMs = Date.now() - modalOpenStart;
|
|
2192
|
+
trackExpressWalletClick(skuId, modalRenderDurationMs);
|
|
2197
2193
|
}
|
|
2198
2194
|
/**
|
|
2199
2195
|
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
@@ -1123,52 +1123,32 @@ var isAppleDeviceOrSafari = () => {
|
|
|
1123
1123
|
const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
|
|
1124
1124
|
return isIOSOrMacTouchDevice || isSafariBrowser;
|
|
1125
1125
|
};
|
|
1126
|
-
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null;
|
|
1126
|
+
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null && getApplePayConfig()?.debugBypassEnabled === true;
|
|
1127
1127
|
var isApplePayAvailable = async () => {
|
|
1128
1128
|
if (bypassApplePayChecks()) {
|
|
1129
|
-
console.log("[ApplePay] bypass active \u2014 displaying button");
|
|
1130
1129
|
return true;
|
|
1131
1130
|
}
|
|
1132
|
-
|
|
1133
|
-
const isAppleDevice = isAppleDeviceOrSafari();
|
|
1134
|
-
console.log("[ApplePay] detection:", JSON.stringify({
|
|
1135
|
-
applePaySessionExists: !!applePaySession,
|
|
1136
|
-
isAppleDevice,
|
|
1137
|
-
userAgent: navigator.userAgent,
|
|
1138
|
-
maxTouchPoints: navigator.maxTouchPoints
|
|
1139
|
-
}, null, 2));
|
|
1140
|
-
if (!applePaySession && !isAppleDevice) {
|
|
1141
|
-
console.log("[ApplePay] not available \u2014 no ApplePaySession and not Apple device");
|
|
1131
|
+
if (!isAppleDeviceOrSafari()) {
|
|
1142
1132
|
return false;
|
|
1143
1133
|
}
|
|
1134
|
+
const applePaySession = window.ApplePaySession;
|
|
1144
1135
|
if (!applePaySession) {
|
|
1145
|
-
console.log("[ApplePay] not available \u2014 Apple device but no ApplePaySession API");
|
|
1146
1136
|
return false;
|
|
1147
1137
|
}
|
|
1148
1138
|
try {
|
|
1149
1139
|
if (typeof applePaySession.canMakePayments !== "function") {
|
|
1150
|
-
console.log("[ApplePay] not available \u2014 canMakePayments is not a function");
|
|
1151
1140
|
return false;
|
|
1152
1141
|
}
|
|
1153
1142
|
if (!applePaySession.canMakePayments()) {
|
|
1154
|
-
console.log("[ApplePay] not available \u2014 canMakePayments returned false");
|
|
1155
1143
|
return false;
|
|
1156
1144
|
}
|
|
1157
1145
|
const merchantId = getApplePayConfig()?.merchantId;
|
|
1158
1146
|
if (!merchantId) {
|
|
1159
|
-
console.log("[ApplePay] not available \u2014 no merchantId configured");
|
|
1160
1147
|
return false;
|
|
1161
1148
|
}
|
|
1162
1149
|
const hasActiveCard = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
console.log("[ApplePay] not available \u2014 no active card for merchant");
|
|
1166
|
-
return false;
|
|
1167
|
-
}
|
|
1168
|
-
console.log("[ApplePay] available \u2014 displaying button");
|
|
1169
|
-
return true;
|
|
1170
|
-
} catch (error) {
|
|
1171
|
-
console.log("[ApplePay] not available \u2014 error:", JSON.stringify({ error: String(error) }, null, 2));
|
|
1150
|
+
return hasActiveCard;
|
|
1151
|
+
} catch {
|
|
1172
1152
|
return false;
|
|
1173
1153
|
}
|
|
1174
1154
|
};
|
|
@@ -1341,17 +1321,21 @@ var track = (action, extra) => {
|
|
|
1341
1321
|
...extra
|
|
1342
1322
|
});
|
|
1343
1323
|
};
|
|
1344
|
-
var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
1324
|
+
var trackExpressWalletImpression = (skuId, { entryPoint, country }, buttonLoadDurationMs) => {
|
|
1345
1325
|
track(EXPRESS_CHECKOUT_EVENTS.IMPRESSION, {
|
|
1346
1326
|
wallet_type: "apple_pay",
|
|
1347
1327
|
entry_point: entryPoint,
|
|
1348
1328
|
sku_id: skuId,
|
|
1349
1329
|
country,
|
|
1350
|
-
device: getDevice()
|
|
1330
|
+
device: getDevice(),
|
|
1331
|
+
...buttonLoadDurationMs !== void 0 && { button_load_duration_ms: buttonLoadDurationMs }
|
|
1351
1332
|
});
|
|
1352
1333
|
};
|
|
1353
|
-
var trackExpressWalletClick = (skuId) => {
|
|
1354
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1334
|
+
var trackExpressWalletClick = (skuId, modalRenderDurationMs) => {
|
|
1335
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1336
|
+
sku_id: skuId,
|
|
1337
|
+
...modalRenderDurationMs !== void 0 && { modal_render_duration_ms: modalRenderDurationMs }
|
|
1338
|
+
});
|
|
1355
1339
|
};
|
|
1356
1340
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1357
1341
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -1359,16 +1343,18 @@ var trackWalletPaymentSheetOpen = (skuId) => {
|
|
|
1359
1343
|
var trackWalletPaymentAuthorised = (skuId) => {
|
|
1360
1344
|
track(EXPRESS_CHECKOUT_EVENTS.AUTHORISED, { sku_id: skuId });
|
|
1361
1345
|
};
|
|
1362
|
-
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
1346
|
+
var trackWalletPaymentSuccess = (skuId, basketId, purchaseDurationMs) => {
|
|
1363
1347
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
1364
1348
|
sku_id: skuId,
|
|
1365
|
-
basket_id: basketId
|
|
1349
|
+
basket_id: basketId,
|
|
1350
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1366
1351
|
});
|
|
1367
1352
|
};
|
|
1368
|
-
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
1353
|
+
var trackWalletPaymentFailure = (skuId, reason, purchaseDurationMs) => {
|
|
1369
1354
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
1370
1355
|
sku_id: skuId,
|
|
1371
|
-
failure_reason: reason
|
|
1356
|
+
failure_reason: reason,
|
|
1357
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1372
1358
|
});
|
|
1373
1359
|
};
|
|
1374
1360
|
var trackFallbackCheckout = (skuId) => {
|
|
@@ -1630,12 +1616,14 @@ function handleStructuredError(ctx) {
|
|
|
1630
1616
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
1631
1617
|
const { skuId, returnUrl, country } = config;
|
|
1632
1618
|
let validatedEmail;
|
|
1619
|
+
let purchaseStartTime;
|
|
1633
1620
|
try {
|
|
1634
1621
|
validatedEmail = validateContacts(
|
|
1635
1622
|
event,
|
|
1636
1623
|
sessionData,
|
|
1637
1624
|
config.supportedBillingCountries
|
|
1638
1625
|
);
|
|
1626
|
+
purchaseStartTime = Date.now();
|
|
1639
1627
|
const result = await performPurchase({
|
|
1640
1628
|
applePayToken: event.payment.token,
|
|
1641
1629
|
skuId: config.skuId,
|
|
@@ -1646,7 +1634,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1646
1634
|
},
|
|
1647
1635
|
recaptchaTokens: config.recaptchaTokens
|
|
1648
1636
|
});
|
|
1649
|
-
|
|
1637
|
+
const purchaseDurationMs = Date.now() - purchaseStartTime;
|
|
1638
|
+
trackWalletPaymentSuccess(skuId, result.basketId, purchaseDurationMs);
|
|
1650
1639
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1651
1640
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
1652
1641
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
@@ -1664,7 +1653,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1664
1653
|
return;
|
|
1665
1654
|
}
|
|
1666
1655
|
const walletError = parseWalletApiError(err);
|
|
1667
|
-
|
|
1656
|
+
const purchaseDurationMs = purchaseStartTime !== void 0 ? Date.now() - purchaseStartTime : void 0;
|
|
1657
|
+
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN", purchaseDurationMs);
|
|
1668
1658
|
failApplePaySession(session);
|
|
1669
1659
|
if (!walletError) {
|
|
1670
1660
|
redirectFallback(skuId, returnUrl, country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
@@ -1987,6 +1977,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1987
1977
|
#country = "";
|
|
1988
1978
|
#rendering = false;
|
|
1989
1979
|
#readyPromise = null;
|
|
1980
|
+
#loadStartTime = 0;
|
|
1990
1981
|
#sessionData = null;
|
|
1991
1982
|
#paymentOptions = null;
|
|
1992
1983
|
#returnUrl = "";
|
|
@@ -2062,6 +2053,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2062
2053
|
}
|
|
2063
2054
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
2064
2055
|
async #run() {
|
|
2056
|
+
this.#loadStartTime = Date.now();
|
|
2065
2057
|
try {
|
|
2066
2058
|
this.#renderTemplate();
|
|
2067
2059
|
if (await this.#checkAvailability()) return;
|
|
@@ -2161,10 +2153,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2161
2153
|
button.classList.remove("wap-loading");
|
|
2162
2154
|
this.#updateDisabledState();
|
|
2163
2155
|
this.#scheduleRecaptchaTokens();
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2156
|
+
const buttonLoadDurationMs = Date.now() - this.#loadStartTime;
|
|
2157
|
+
trackExpressWalletImpression(
|
|
2158
|
+
this.#offer.sku_id,
|
|
2159
|
+
{ entryPoint: this.#entryPoint, country: this.#country },
|
|
2160
|
+
buttonLoadDurationMs
|
|
2161
|
+
);
|
|
2168
2162
|
}
|
|
2169
2163
|
}
|
|
2170
2164
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
@@ -2187,7 +2181,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2187
2181
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2188
2182
|
return;
|
|
2189
2183
|
}
|
|
2190
|
-
|
|
2184
|
+
const modalOpenStart = Date.now();
|
|
2191
2185
|
ApplePayModal.define();
|
|
2192
2186
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2193
2187
|
modal.offer = this.#offer;
|
|
@@ -2202,6 +2196,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2202
2196
|
this.#scheduleRecaptchaTokens();
|
|
2203
2197
|
};
|
|
2204
2198
|
modal.open(this.#recaptchaTokensPromise);
|
|
2199
|
+
const modalRenderDurationMs = Date.now() - modalOpenStart;
|
|
2200
|
+
trackExpressWalletClick(skuId, modalRenderDurationMs);
|
|
2205
2201
|
}
|
|
2206
2202
|
/**
|
|
2207
2203
|
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
@@ -1115,52 +1115,32 @@ var isAppleDeviceOrSafari = () => {
|
|
|
1115
1115
|
const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
|
|
1116
1116
|
return isIOSOrMacTouchDevice || isSafariBrowser;
|
|
1117
1117
|
};
|
|
1118
|
-
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null;
|
|
1118
|
+
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null && getApplePayConfig()?.debugBypassEnabled === true;
|
|
1119
1119
|
var isApplePayAvailable = async () => {
|
|
1120
1120
|
if (bypassApplePayChecks()) {
|
|
1121
|
-
console.log("[ApplePay] bypass active \u2014 displaying button");
|
|
1122
1121
|
return true;
|
|
1123
1122
|
}
|
|
1124
|
-
|
|
1125
|
-
const isAppleDevice = isAppleDeviceOrSafari();
|
|
1126
|
-
console.log("[ApplePay] detection:", JSON.stringify({
|
|
1127
|
-
applePaySessionExists: !!applePaySession,
|
|
1128
|
-
isAppleDevice,
|
|
1129
|
-
userAgent: navigator.userAgent,
|
|
1130
|
-
maxTouchPoints: navigator.maxTouchPoints
|
|
1131
|
-
}, null, 2));
|
|
1132
|
-
if (!applePaySession && !isAppleDevice) {
|
|
1133
|
-
console.log("[ApplePay] not available \u2014 no ApplePaySession and not Apple device");
|
|
1123
|
+
if (!isAppleDeviceOrSafari()) {
|
|
1134
1124
|
return false;
|
|
1135
1125
|
}
|
|
1126
|
+
const applePaySession = window.ApplePaySession;
|
|
1136
1127
|
if (!applePaySession) {
|
|
1137
|
-
console.log("[ApplePay] not available \u2014 Apple device but no ApplePaySession API");
|
|
1138
1128
|
return false;
|
|
1139
1129
|
}
|
|
1140
1130
|
try {
|
|
1141
1131
|
if (typeof applePaySession.canMakePayments !== "function") {
|
|
1142
|
-
console.log("[ApplePay] not available \u2014 canMakePayments is not a function");
|
|
1143
1132
|
return false;
|
|
1144
1133
|
}
|
|
1145
1134
|
if (!applePaySession.canMakePayments()) {
|
|
1146
|
-
console.log("[ApplePay] not available \u2014 canMakePayments returned false");
|
|
1147
1135
|
return false;
|
|
1148
1136
|
}
|
|
1149
1137
|
const merchantId = getApplePayConfig()?.merchantId;
|
|
1150
1138
|
if (!merchantId) {
|
|
1151
|
-
console.log("[ApplePay] not available \u2014 no merchantId configured");
|
|
1152
1139
|
return false;
|
|
1153
1140
|
}
|
|
1154
1141
|
const hasActiveCard = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
console.log("[ApplePay] not available \u2014 no active card for merchant");
|
|
1158
|
-
return false;
|
|
1159
|
-
}
|
|
1160
|
-
console.log("[ApplePay] available \u2014 displaying button");
|
|
1161
|
-
return true;
|
|
1162
|
-
} catch (error) {
|
|
1163
|
-
console.log("[ApplePay] not available \u2014 error:", JSON.stringify({ error: String(error) }, null, 2));
|
|
1142
|
+
return hasActiveCard;
|
|
1143
|
+
} catch {
|
|
1164
1144
|
return false;
|
|
1165
1145
|
}
|
|
1166
1146
|
};
|
|
@@ -1333,17 +1313,21 @@ var track = (action, extra) => {
|
|
|
1333
1313
|
...extra
|
|
1334
1314
|
});
|
|
1335
1315
|
};
|
|
1336
|
-
var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
1316
|
+
var trackExpressWalletImpression = (skuId, { entryPoint, country }, buttonLoadDurationMs) => {
|
|
1337
1317
|
track(EXPRESS_CHECKOUT_EVENTS.IMPRESSION, {
|
|
1338
1318
|
wallet_type: "apple_pay",
|
|
1339
1319
|
entry_point: entryPoint,
|
|
1340
1320
|
sku_id: skuId,
|
|
1341
1321
|
country,
|
|
1342
|
-
device: getDevice()
|
|
1322
|
+
device: getDevice(),
|
|
1323
|
+
...buttonLoadDurationMs !== void 0 && { button_load_duration_ms: buttonLoadDurationMs }
|
|
1343
1324
|
});
|
|
1344
1325
|
};
|
|
1345
|
-
var trackExpressWalletClick = (skuId) => {
|
|
1346
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1326
|
+
var trackExpressWalletClick = (skuId, modalRenderDurationMs) => {
|
|
1327
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1328
|
+
sku_id: skuId,
|
|
1329
|
+
...modalRenderDurationMs !== void 0 && { modal_render_duration_ms: modalRenderDurationMs }
|
|
1330
|
+
});
|
|
1347
1331
|
};
|
|
1348
1332
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1349
1333
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -1351,16 +1335,18 @@ var trackWalletPaymentSheetOpen = (skuId) => {
|
|
|
1351
1335
|
var trackWalletPaymentAuthorised = (skuId) => {
|
|
1352
1336
|
track(EXPRESS_CHECKOUT_EVENTS.AUTHORISED, { sku_id: skuId });
|
|
1353
1337
|
};
|
|
1354
|
-
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
1338
|
+
var trackWalletPaymentSuccess = (skuId, basketId, purchaseDurationMs) => {
|
|
1355
1339
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
1356
1340
|
sku_id: skuId,
|
|
1357
|
-
basket_id: basketId
|
|
1341
|
+
basket_id: basketId,
|
|
1342
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1358
1343
|
});
|
|
1359
1344
|
};
|
|
1360
|
-
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
1345
|
+
var trackWalletPaymentFailure = (skuId, reason, purchaseDurationMs) => {
|
|
1361
1346
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
1362
1347
|
sku_id: skuId,
|
|
1363
|
-
failure_reason: reason
|
|
1348
|
+
failure_reason: reason,
|
|
1349
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1364
1350
|
});
|
|
1365
1351
|
};
|
|
1366
1352
|
var trackFallbackCheckout = (skuId) => {
|
|
@@ -1622,12 +1608,14 @@ function handleStructuredError(ctx) {
|
|
|
1622
1608
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
1623
1609
|
const { skuId, returnUrl, country } = config;
|
|
1624
1610
|
let validatedEmail;
|
|
1611
|
+
let purchaseStartTime;
|
|
1625
1612
|
try {
|
|
1626
1613
|
validatedEmail = validateContacts(
|
|
1627
1614
|
event,
|
|
1628
1615
|
sessionData,
|
|
1629
1616
|
config.supportedBillingCountries
|
|
1630
1617
|
);
|
|
1618
|
+
purchaseStartTime = Date.now();
|
|
1631
1619
|
const result = await performPurchase({
|
|
1632
1620
|
applePayToken: event.payment.token,
|
|
1633
1621
|
skuId: config.skuId,
|
|
@@ -1638,7 +1626,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1638
1626
|
},
|
|
1639
1627
|
recaptchaTokens: config.recaptchaTokens
|
|
1640
1628
|
});
|
|
1641
|
-
|
|
1629
|
+
const purchaseDurationMs = Date.now() - purchaseStartTime;
|
|
1630
|
+
trackWalletPaymentSuccess(skuId, result.basketId, purchaseDurationMs);
|
|
1642
1631
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1643
1632
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
1644
1633
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
@@ -1656,7 +1645,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1656
1645
|
return;
|
|
1657
1646
|
}
|
|
1658
1647
|
const walletError = parseWalletApiError(err);
|
|
1659
|
-
|
|
1648
|
+
const purchaseDurationMs = purchaseStartTime !== void 0 ? Date.now() - purchaseStartTime : void 0;
|
|
1649
|
+
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN", purchaseDurationMs);
|
|
1660
1650
|
failApplePaySession(session);
|
|
1661
1651
|
if (!walletError) {
|
|
1662
1652
|
redirectFallback(skuId, returnUrl, country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
@@ -1979,6 +1969,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1979
1969
|
#country = "";
|
|
1980
1970
|
#rendering = false;
|
|
1981
1971
|
#readyPromise = null;
|
|
1972
|
+
#loadStartTime = 0;
|
|
1982
1973
|
#sessionData = null;
|
|
1983
1974
|
#paymentOptions = null;
|
|
1984
1975
|
#returnUrl = "";
|
|
@@ -2054,6 +2045,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2054
2045
|
}
|
|
2055
2046
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
2056
2047
|
async #run() {
|
|
2048
|
+
this.#loadStartTime = Date.now();
|
|
2057
2049
|
try {
|
|
2058
2050
|
this.#renderTemplate();
|
|
2059
2051
|
if (await this.#checkAvailability()) return;
|
|
@@ -2153,10 +2145,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2153
2145
|
button.classList.remove("wap-loading");
|
|
2154
2146
|
this.#updateDisabledState();
|
|
2155
2147
|
this.#scheduleRecaptchaTokens();
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2148
|
+
const buttonLoadDurationMs = Date.now() - this.#loadStartTime;
|
|
2149
|
+
trackExpressWalletImpression(
|
|
2150
|
+
this.#offer.sku_id,
|
|
2151
|
+
{ entryPoint: this.#entryPoint, country: this.#country },
|
|
2152
|
+
buttonLoadDurationMs
|
|
2153
|
+
);
|
|
2160
2154
|
}
|
|
2161
2155
|
}
|
|
2162
2156
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
@@ -2179,7 +2173,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2179
2173
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2180
2174
|
return;
|
|
2181
2175
|
}
|
|
2182
|
-
|
|
2176
|
+
const modalOpenStart = Date.now();
|
|
2183
2177
|
ApplePayModal.define();
|
|
2184
2178
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2185
2179
|
modal.offer = this.#offer;
|
|
@@ -2194,6 +2188,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2194
2188
|
this.#scheduleRecaptchaTokens();
|
|
2195
2189
|
};
|
|
2196
2190
|
modal.open(this.#recaptchaTokensPromise);
|
|
2191
|
+
const modalRenderDurationMs = Date.now() - modalOpenStart;
|
|
2192
|
+
trackExpressWalletClick(skuId, modalRenderDurationMs);
|
|
2197
2193
|
}
|
|
2198
2194
|
/**
|
|
2199
2195
|
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
@@ -8,52 +8,32 @@ var isAppleDeviceOrSafari = () => {
|
|
|
8
8
|
const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
|
|
9
9
|
return isIOSOrMacTouchDevice || isSafariBrowser;
|
|
10
10
|
};
|
|
11
|
-
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null;
|
|
11
|
+
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null && getApplePayConfig()?.debugBypassEnabled === true;
|
|
12
12
|
var isApplePayAvailable = async () => {
|
|
13
13
|
if (bypassApplePayChecks()) {
|
|
14
|
-
console.log("[ApplePay] bypass active \u2014 displaying button");
|
|
15
14
|
return true;
|
|
16
15
|
}
|
|
17
|
-
|
|
18
|
-
const isAppleDevice = isAppleDeviceOrSafari();
|
|
19
|
-
console.log("[ApplePay] detection:", JSON.stringify({
|
|
20
|
-
applePaySessionExists: !!applePaySession,
|
|
21
|
-
isAppleDevice,
|
|
22
|
-
userAgent: navigator.userAgent,
|
|
23
|
-
maxTouchPoints: navigator.maxTouchPoints
|
|
24
|
-
}, null, 2));
|
|
25
|
-
if (!applePaySession && !isAppleDevice) {
|
|
26
|
-
console.log("[ApplePay] not available \u2014 no ApplePaySession and not Apple device");
|
|
16
|
+
if (!isAppleDeviceOrSafari()) {
|
|
27
17
|
return false;
|
|
28
18
|
}
|
|
19
|
+
const applePaySession = window.ApplePaySession;
|
|
29
20
|
if (!applePaySession) {
|
|
30
|
-
console.log("[ApplePay] not available \u2014 Apple device but no ApplePaySession API");
|
|
31
21
|
return false;
|
|
32
22
|
}
|
|
33
23
|
try {
|
|
34
24
|
if (typeof applePaySession.canMakePayments !== "function") {
|
|
35
|
-
console.log("[ApplePay] not available \u2014 canMakePayments is not a function");
|
|
36
25
|
return false;
|
|
37
26
|
}
|
|
38
27
|
if (!applePaySession.canMakePayments()) {
|
|
39
|
-
console.log("[ApplePay] not available \u2014 canMakePayments returned false");
|
|
40
28
|
return false;
|
|
41
29
|
}
|
|
42
30
|
const merchantId = getApplePayConfig()?.merchantId;
|
|
43
31
|
if (!merchantId) {
|
|
44
|
-
console.log("[ApplePay] not available \u2014 no merchantId configured");
|
|
45
32
|
return false;
|
|
46
33
|
}
|
|
47
34
|
const hasActiveCard = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
console.log("[ApplePay] not available \u2014 no active card for merchant");
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
console.log("[ApplePay] available \u2014 displaying button");
|
|
54
|
-
return true;
|
|
55
|
-
} catch (error) {
|
|
56
|
-
console.log("[ApplePay] not available \u2014 error:", JSON.stringify({ error: String(error) }, null, 2));
|
|
35
|
+
return hasActiveCard;
|
|
36
|
+
} catch {
|
|
57
37
|
return false;
|
|
58
38
|
}
|
|
59
39
|
};
|
|
@@ -93,16 +93,18 @@ var track = (action, extra) => {
|
|
|
93
93
|
...extra
|
|
94
94
|
});
|
|
95
95
|
};
|
|
96
|
-
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
96
|
+
var trackWalletPaymentSuccess = (skuId, basketId, purchaseDurationMs) => {
|
|
97
97
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
98
98
|
sku_id: skuId,
|
|
99
|
-
basket_id: basketId
|
|
99
|
+
basket_id: basketId,
|
|
100
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
100
101
|
});
|
|
101
102
|
};
|
|
102
|
-
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
103
|
+
var trackWalletPaymentFailure = (skuId, reason, purchaseDurationMs) => {
|
|
103
104
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
104
105
|
sku_id: skuId,
|
|
105
|
-
failure_reason: reason
|
|
106
|
+
failure_reason: reason,
|
|
107
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
106
108
|
});
|
|
107
109
|
};
|
|
108
110
|
var trackFallbackCheckout = (skuId) => {
|
|
@@ -345,12 +347,14 @@ function handleStructuredError(ctx) {
|
|
|
345
347
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
346
348
|
const { skuId, returnUrl, country } = config;
|
|
347
349
|
let validatedEmail;
|
|
350
|
+
let purchaseStartTime;
|
|
348
351
|
try {
|
|
349
352
|
validatedEmail = validateContacts(
|
|
350
353
|
event,
|
|
351
354
|
sessionData,
|
|
352
355
|
config.supportedBillingCountries
|
|
353
356
|
);
|
|
357
|
+
purchaseStartTime = Date.now();
|
|
354
358
|
const result = await performPurchase({
|
|
355
359
|
applePayToken: event.payment.token,
|
|
356
360
|
skuId: config.skuId,
|
|
@@ -361,7 +365,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
361
365
|
},
|
|
362
366
|
recaptchaTokens: config.recaptchaTokens
|
|
363
367
|
});
|
|
364
|
-
|
|
368
|
+
const purchaseDurationMs = Date.now() - purchaseStartTime;
|
|
369
|
+
trackWalletPaymentSuccess(skuId, result.basketId, purchaseDurationMs);
|
|
365
370
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
366
371
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
367
372
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
@@ -379,7 +384,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
379
384
|
return;
|
|
380
385
|
}
|
|
381
386
|
const walletError = parseWalletApiError(err);
|
|
382
|
-
|
|
387
|
+
const purchaseDurationMs = purchaseStartTime !== void 0 ? Date.now() - purchaseStartTime : void 0;
|
|
388
|
+
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN", purchaseDurationMs);
|
|
383
389
|
failApplePaySession(session);
|
|
384
390
|
if (!walletError) {
|
|
385
391
|
redirectFallback(skuId, returnUrl, country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
package/dist/src/index.js
CHANGED
|
@@ -1120,52 +1120,32 @@ var isAppleDeviceOrSafari = () => {
|
|
|
1120
1120
|
const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
|
|
1121
1121
|
return isIOSOrMacTouchDevice || isSafariBrowser;
|
|
1122
1122
|
};
|
|
1123
|
-
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null;
|
|
1123
|
+
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null && getApplePayConfig()?.debugBypassEnabled === true;
|
|
1124
1124
|
var isApplePayAvailable = async () => {
|
|
1125
1125
|
if (bypassApplePayChecks()) {
|
|
1126
|
-
console.log("[ApplePay] bypass active \u2014 displaying button");
|
|
1127
1126
|
return true;
|
|
1128
1127
|
}
|
|
1129
|
-
|
|
1130
|
-
const isAppleDevice = isAppleDeviceOrSafari();
|
|
1131
|
-
console.log("[ApplePay] detection:", JSON.stringify({
|
|
1132
|
-
applePaySessionExists: !!applePaySession,
|
|
1133
|
-
isAppleDevice,
|
|
1134
|
-
userAgent: navigator.userAgent,
|
|
1135
|
-
maxTouchPoints: navigator.maxTouchPoints
|
|
1136
|
-
}, null, 2));
|
|
1137
|
-
if (!applePaySession && !isAppleDevice) {
|
|
1138
|
-
console.log("[ApplePay] not available \u2014 no ApplePaySession and not Apple device");
|
|
1128
|
+
if (!isAppleDeviceOrSafari()) {
|
|
1139
1129
|
return false;
|
|
1140
1130
|
}
|
|
1131
|
+
const applePaySession = window.ApplePaySession;
|
|
1141
1132
|
if (!applePaySession) {
|
|
1142
|
-
console.log("[ApplePay] not available \u2014 Apple device but no ApplePaySession API");
|
|
1143
1133
|
return false;
|
|
1144
1134
|
}
|
|
1145
1135
|
try {
|
|
1146
1136
|
if (typeof applePaySession.canMakePayments !== "function") {
|
|
1147
|
-
console.log("[ApplePay] not available \u2014 canMakePayments is not a function");
|
|
1148
1137
|
return false;
|
|
1149
1138
|
}
|
|
1150
1139
|
if (!applePaySession.canMakePayments()) {
|
|
1151
|
-
console.log("[ApplePay] not available \u2014 canMakePayments returned false");
|
|
1152
1140
|
return false;
|
|
1153
1141
|
}
|
|
1154
1142
|
const merchantId = getApplePayConfig()?.merchantId;
|
|
1155
1143
|
if (!merchantId) {
|
|
1156
|
-
console.log("[ApplePay] not available \u2014 no merchantId configured");
|
|
1157
1144
|
return false;
|
|
1158
1145
|
}
|
|
1159
1146
|
const hasActiveCard = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
console.log("[ApplePay] not available \u2014 no active card for merchant");
|
|
1163
|
-
return false;
|
|
1164
|
-
}
|
|
1165
|
-
console.log("[ApplePay] available \u2014 displaying button");
|
|
1166
|
-
return true;
|
|
1167
|
-
} catch (error) {
|
|
1168
|
-
console.log("[ApplePay] not available \u2014 error:", JSON.stringify({ error: String(error) }, null, 2));
|
|
1147
|
+
return hasActiveCard;
|
|
1148
|
+
} catch {
|
|
1169
1149
|
return false;
|
|
1170
1150
|
}
|
|
1171
1151
|
};
|
|
@@ -1338,17 +1318,21 @@ var track = (action, extra) => {
|
|
|
1338
1318
|
...extra
|
|
1339
1319
|
});
|
|
1340
1320
|
};
|
|
1341
|
-
var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
1321
|
+
var trackExpressWalletImpression = (skuId, { entryPoint, country }, buttonLoadDurationMs) => {
|
|
1342
1322
|
track(EXPRESS_CHECKOUT_EVENTS.IMPRESSION, {
|
|
1343
1323
|
wallet_type: "apple_pay",
|
|
1344
1324
|
entry_point: entryPoint,
|
|
1345
1325
|
sku_id: skuId,
|
|
1346
1326
|
country,
|
|
1347
|
-
device: getDevice()
|
|
1327
|
+
device: getDevice(),
|
|
1328
|
+
...buttonLoadDurationMs !== void 0 && { button_load_duration_ms: buttonLoadDurationMs }
|
|
1348
1329
|
});
|
|
1349
1330
|
};
|
|
1350
|
-
var trackExpressWalletClick = (skuId) => {
|
|
1351
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1331
|
+
var trackExpressWalletClick = (skuId, modalRenderDurationMs) => {
|
|
1332
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1333
|
+
sku_id: skuId,
|
|
1334
|
+
...modalRenderDurationMs !== void 0 && { modal_render_duration_ms: modalRenderDurationMs }
|
|
1335
|
+
});
|
|
1352
1336
|
};
|
|
1353
1337
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1354
1338
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -1356,16 +1340,18 @@ var trackWalletPaymentSheetOpen = (skuId) => {
|
|
|
1356
1340
|
var trackWalletPaymentAuthorised = (skuId) => {
|
|
1357
1341
|
track(EXPRESS_CHECKOUT_EVENTS.AUTHORISED, { sku_id: skuId });
|
|
1358
1342
|
};
|
|
1359
|
-
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
1343
|
+
var trackWalletPaymentSuccess = (skuId, basketId, purchaseDurationMs) => {
|
|
1360
1344
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
1361
1345
|
sku_id: skuId,
|
|
1362
|
-
basket_id: basketId
|
|
1346
|
+
basket_id: basketId,
|
|
1347
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1363
1348
|
});
|
|
1364
1349
|
};
|
|
1365
|
-
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
1350
|
+
var trackWalletPaymentFailure = (skuId, reason, purchaseDurationMs) => {
|
|
1366
1351
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
1367
1352
|
sku_id: skuId,
|
|
1368
|
-
failure_reason: reason
|
|
1353
|
+
failure_reason: reason,
|
|
1354
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1369
1355
|
});
|
|
1370
1356
|
};
|
|
1371
1357
|
var trackFallbackCheckout = (skuId) => {
|
|
@@ -1627,12 +1613,14 @@ function handleStructuredError(ctx) {
|
|
|
1627
1613
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
1628
1614
|
const { skuId, returnUrl, country } = config;
|
|
1629
1615
|
let validatedEmail;
|
|
1616
|
+
let purchaseStartTime;
|
|
1630
1617
|
try {
|
|
1631
1618
|
validatedEmail = validateContacts(
|
|
1632
1619
|
event,
|
|
1633
1620
|
sessionData,
|
|
1634
1621
|
config.supportedBillingCountries
|
|
1635
1622
|
);
|
|
1623
|
+
purchaseStartTime = Date.now();
|
|
1636
1624
|
const result = await performPurchase({
|
|
1637
1625
|
applePayToken: event.payment.token,
|
|
1638
1626
|
skuId: config.skuId,
|
|
@@ -1643,7 +1631,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1643
1631
|
},
|
|
1644
1632
|
recaptchaTokens: config.recaptchaTokens
|
|
1645
1633
|
});
|
|
1646
|
-
|
|
1634
|
+
const purchaseDurationMs = Date.now() - purchaseStartTime;
|
|
1635
|
+
trackWalletPaymentSuccess(skuId, result.basketId, purchaseDurationMs);
|
|
1647
1636
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1648
1637
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
1649
1638
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
@@ -1661,7 +1650,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1661
1650
|
return;
|
|
1662
1651
|
}
|
|
1663
1652
|
const walletError = parseWalletApiError(err);
|
|
1664
|
-
|
|
1653
|
+
const purchaseDurationMs = purchaseStartTime !== void 0 ? Date.now() - purchaseStartTime : void 0;
|
|
1654
|
+
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN", purchaseDurationMs);
|
|
1665
1655
|
failApplePaySession(session);
|
|
1666
1656
|
if (!walletError) {
|
|
1667
1657
|
redirectFallback(skuId, returnUrl, country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
@@ -1984,6 +1974,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1984
1974
|
#country = "";
|
|
1985
1975
|
#rendering = false;
|
|
1986
1976
|
#readyPromise = null;
|
|
1977
|
+
#loadStartTime = 0;
|
|
1987
1978
|
#sessionData = null;
|
|
1988
1979
|
#paymentOptions = null;
|
|
1989
1980
|
#returnUrl = "";
|
|
@@ -2059,6 +2050,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2059
2050
|
}
|
|
2060
2051
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
2061
2052
|
async #run() {
|
|
2053
|
+
this.#loadStartTime = Date.now();
|
|
2062
2054
|
try {
|
|
2063
2055
|
this.#renderTemplate();
|
|
2064
2056
|
if (await this.#checkAvailability()) return;
|
|
@@ -2158,10 +2150,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2158
2150
|
button.classList.remove("wap-loading");
|
|
2159
2151
|
this.#updateDisabledState();
|
|
2160
2152
|
this.#scheduleRecaptchaTokens();
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2153
|
+
const buttonLoadDurationMs = Date.now() - this.#loadStartTime;
|
|
2154
|
+
trackExpressWalletImpression(
|
|
2155
|
+
this.#offer.sku_id,
|
|
2156
|
+
{ entryPoint: this.#entryPoint, country: this.#country },
|
|
2157
|
+
buttonLoadDurationMs
|
|
2158
|
+
);
|
|
2165
2159
|
}
|
|
2166
2160
|
}
|
|
2167
2161
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
@@ -2184,7 +2178,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2184
2178
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2185
2179
|
return;
|
|
2186
2180
|
}
|
|
2187
|
-
|
|
2181
|
+
const modalOpenStart = Date.now();
|
|
2188
2182
|
ApplePayModal.define();
|
|
2189
2183
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2190
2184
|
modal.offer = this.#offer;
|
|
@@ -2199,6 +2193,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2199
2193
|
this.#scheduleRecaptchaTokens();
|
|
2200
2194
|
};
|
|
2201
2195
|
modal.open(this.#recaptchaTokensPromise);
|
|
2196
|
+
const modalRenderDurationMs = Date.now() - modalOpenStart;
|
|
2197
|
+
trackExpressWalletClick(skuId, modalRenderDurationMs);
|
|
2202
2198
|
}
|
|
2203
2199
|
/**
|
|
2204
2200
|
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
@@ -47,17 +47,17 @@ export type ImpressionMetadata = {
|
|
|
47
47
|
country: string;
|
|
48
48
|
};
|
|
49
49
|
/** Wallet button displayed — emits all 5 required analytics dimensions. */
|
|
50
|
-
export declare const trackExpressWalletImpression: (skuId: string, { entryPoint, country }: ImpressionMetadata) => void;
|
|
50
|
+
export declare const trackExpressWalletImpression: (skuId: string, { entryPoint, country }: ImpressionMetadata, buttonLoadDurationMs?: number) => void;
|
|
51
51
|
/** Wallet button clicked */
|
|
52
|
-
export declare const trackExpressWalletClick: (skuId: string) => void;
|
|
52
|
+
export declare const trackExpressWalletClick: (skuId: string, modalRenderDurationMs?: number) => void;
|
|
53
53
|
/** Apple Pay sheet opened (session.begin() called) */
|
|
54
54
|
export declare const trackWalletPaymentSheetOpen: (skuId: string) => void;
|
|
55
55
|
/** Payment authorised by the user in the Apple Pay sheet */
|
|
56
56
|
export declare const trackWalletPaymentAuthorised: (skuId: string) => void;
|
|
57
57
|
/** Purchase completed — BFF returned success */
|
|
58
|
-
export declare const trackWalletPaymentSuccess: (skuId: string, basketId: string) => void;
|
|
58
|
+
export declare const trackWalletPaymentSuccess: (skuId: string, basketId: string, purchaseDurationMs?: number) => void;
|
|
59
59
|
/** Payment failed — BFF returned an error */
|
|
60
|
-
export declare const trackWalletPaymentFailure: (skuId: string, reason: string) => void;
|
|
60
|
+
export declare const trackWalletPaymentFailure: (skuId: string, reason: string, purchaseDurationMs?: number) => void;
|
|
61
61
|
/** Redirect to standard checkout triggered */
|
|
62
62
|
export declare const trackFallbackCheckout: (skuId: string) => void;
|
|
63
63
|
/** Billing/shipping field failed validation (emitted per-field when Apple Pay sheet stays open) */
|
|
@@ -35,17 +35,21 @@ var track = (action, extra) => {
|
|
|
35
35
|
...extra
|
|
36
36
|
});
|
|
37
37
|
};
|
|
38
|
-
var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
38
|
+
var trackExpressWalletImpression = (skuId, { entryPoint, country }, buttonLoadDurationMs) => {
|
|
39
39
|
track(EXPRESS_CHECKOUT_EVENTS.IMPRESSION, {
|
|
40
40
|
wallet_type: "apple_pay",
|
|
41
41
|
entry_point: entryPoint,
|
|
42
42
|
sku_id: skuId,
|
|
43
43
|
country,
|
|
44
|
-
device: getDevice()
|
|
44
|
+
device: getDevice(),
|
|
45
|
+
...buttonLoadDurationMs !== void 0 && { button_load_duration_ms: buttonLoadDurationMs }
|
|
45
46
|
});
|
|
46
47
|
};
|
|
47
|
-
var trackExpressWalletClick = (skuId) => {
|
|
48
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
48
|
+
var trackExpressWalletClick = (skuId, modalRenderDurationMs) => {
|
|
49
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
50
|
+
sku_id: skuId,
|
|
51
|
+
...modalRenderDurationMs !== void 0 && { modal_render_duration_ms: modalRenderDurationMs }
|
|
52
|
+
});
|
|
49
53
|
};
|
|
50
54
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
51
55
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -53,16 +57,18 @@ var trackWalletPaymentSheetOpen = (skuId) => {
|
|
|
53
57
|
var trackWalletPaymentAuthorised = (skuId) => {
|
|
54
58
|
track(EXPRESS_CHECKOUT_EVENTS.AUTHORISED, { sku_id: skuId });
|
|
55
59
|
};
|
|
56
|
-
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
60
|
+
var trackWalletPaymentSuccess = (skuId, basketId, purchaseDurationMs) => {
|
|
57
61
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
58
62
|
sku_id: skuId,
|
|
59
|
-
basket_id: basketId
|
|
63
|
+
basket_id: basketId,
|
|
64
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
60
65
|
});
|
|
61
66
|
};
|
|
62
|
-
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
67
|
+
var trackWalletPaymentFailure = (skuId, reason, purchaseDurationMs) => {
|
|
63
68
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
64
69
|
sku_id: skuId,
|
|
65
|
-
failure_reason: reason
|
|
70
|
+
failure_reason: reason,
|
|
71
|
+
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
66
72
|
});
|
|
67
73
|
};
|
|
68
74
|
var trackFallbackCheckout = (skuId) => {
|
package/package.json
CHANGED