@economist/web-apple-pay 1.9.5 → 1.10.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/dist/index.js +64 -26
- package/dist/src/apple-pay-button.d.ts +10 -8
- package/dist/src/apple-pay-button.js +61 -26
- package/dist/src/apple-pay-button.stories.js +61 -26
- package/dist/src/apple-pay-modal.stories.js +61 -26
- package/dist/src/constants.d.ts +18 -2
- package/dist/src/constants.js +2 -0
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.js +64 -26
- package/dist/src/utils/applePayExpressEligibility.d.ts +11 -7
- package/dist/src/utils/applePayExpressEligibility.js +3 -1
- package/dist/src/utils/expressCheckoutTracking.d.ts +9 -4
- package/dist/src/utils/expressCheckoutTracking.js +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1311,6 +1311,7 @@ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
|
|
|
1311
1311
|
return ApplePayEntryPoint2;
|
|
1312
1312
|
})(ApplePayEntryPoint || {});
|
|
1313
1313
|
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
1314
|
+
var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
1314
1315
|
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
1315
1316
|
CONTROL: "control",
|
|
1316
1317
|
TREATMENT: "treatment"
|
|
@@ -1353,7 +1354,7 @@ var track = (action, extra) => {
|
|
|
1353
1354
|
...extra
|
|
1354
1355
|
});
|
|
1355
1356
|
};
|
|
1356
|
-
var trackApplePayExperimentExposure = (variant, experimentKey) => {
|
|
1357
|
+
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey = APPLE_PAY_EXPRESS_EXPERIMENT_KEY) => {
|
|
1357
1358
|
const isActiveVariant = variant === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || variant === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
1358
1359
|
if (!isActiveVariant) {
|
|
1359
1360
|
return;
|
|
@@ -1361,14 +1362,14 @@ var trackApplePayExperimentExposure = (variant, experimentKey) => {
|
|
|
1361
1362
|
const exposures = window.__applePayExperimentExposures ?? {};
|
|
1362
1363
|
window.__applePayExperimentExposures = exposures;
|
|
1363
1364
|
const pathname = window.location?.pathname ?? "";
|
|
1364
|
-
const dedupeKey = `${pathname}:${
|
|
1365
|
+
const dedupeKey = `${pathname}:${flagKey}:${variant}`;
|
|
1365
1366
|
if (exposures[dedupeKey]) {
|
|
1366
1367
|
return;
|
|
1367
1368
|
}
|
|
1368
1369
|
exposures[dedupeKey] = true;
|
|
1369
1370
|
emitTedlEvent({
|
|
1370
1371
|
name: "$exposure",
|
|
1371
|
-
flag_key:
|
|
1372
|
+
flag_key: flagKey,
|
|
1372
1373
|
variant,
|
|
1373
1374
|
...experimentKey ? { experiment_key: experimentKey } : {}
|
|
1374
1375
|
});
|
|
@@ -2006,8 +2007,23 @@ var getExperimentKeyFromNextData = (flagKey) => {
|
|
|
2006
2007
|
// src/utils/applePayExpressEligibility.ts
|
|
2007
2008
|
var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
|
|
2008
2009
|
var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
|
|
2010
|
+
var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
|
|
2009
2011
|
|
|
2010
2012
|
// src/apple-pay-button.ts
|
|
2013
|
+
var ENTRY_POINT_CONFIG = {
|
|
2014
|
+
["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
|
|
2015
|
+
isEligible: isEligibleForApplePayExpressExperiment,
|
|
2016
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
|
|
2017
|
+
},
|
|
2018
|
+
["article_paywall" /* PAYWALL */]: {
|
|
2019
|
+
isEligible: isEligibleForApplePayExpressPaywallExperiment,
|
|
2020
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY
|
|
2021
|
+
},
|
|
2022
|
+
["article_regwall" /* REGWALL */]: {
|
|
2023
|
+
isEligible: () => true,
|
|
2024
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
|
|
2025
|
+
}
|
|
2026
|
+
};
|
|
2011
2027
|
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
2012
2028
|
var TOTAL_LABEL = "The Economist";
|
|
2013
2029
|
var DEFAULT_CURRENCY = "USD";
|
|
@@ -2026,9 +2042,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2026
2042
|
/**
|
|
2027
2043
|
* Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
|
|
2028
2044
|
*
|
|
2029
|
-
* Reads the experiment variant from `window.experimentIntegration.getVariant
|
|
2030
|
-
* {@link
|
|
2031
|
-
*
|
|
2045
|
+
* Reads the experiment variant from `window.experimentIntegration.getVariant`:
|
|
2046
|
+
* - {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY} for `PAYWALL`
|
|
2047
|
+
* - {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY} for `REGWALL` / `DUAL_OFFER_BANNER`
|
|
2048
|
+
*
|
|
2049
|
+
* The host page is responsible for setting up `window.experimentIntegration`
|
|
2050
|
+
* before calling this method.
|
|
2032
2051
|
*
|
|
2033
2052
|
* - `treatment` → button created and returned
|
|
2034
2053
|
* - `control` / missing / anything else → returns null (button suppressed)
|
|
@@ -2038,11 +2057,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2038
2057
|
* `window.experimentIntegration`. Once all consumers are migrated, the URL param
|
|
2039
2058
|
* fallback will be removed.
|
|
2040
2059
|
*
|
|
2041
|
-
* **
|
|
2042
|
-
*
|
|
2043
|
-
*
|
|
2044
|
-
*
|
|
2045
|
-
* the dual-offer banner is only mounted for anonymous visitors.
|
|
2060
|
+
* **Eligibility:**
|
|
2061
|
+
* - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone (SMA-3301)
|
|
2062
|
+
* - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
|
|
2063
|
+
* - `REGWALL`: no host-side placement gate (pre-SMA-3301 article behaviour)
|
|
2046
2064
|
*
|
|
2047
2065
|
* @param offer - The offer to display in the Apple Pay flow.
|
|
2048
2066
|
* @param country - The user's country code.
|
|
@@ -2058,13 +2076,18 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2058
2076
|
const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
|
|
2059
2077
|
FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
|
|
2060
2078
|
);
|
|
2061
|
-
const
|
|
2062
|
-
const
|
|
2063
|
-
if (
|
|
2079
|
+
const resolvedEntryPoint = entryPoint || "dual_offer_banner" /* DUAL_OFFER_BANNER */;
|
|
2080
|
+
const config = ENTRY_POINT_CONFIG[resolvedEntryPoint];
|
|
2081
|
+
if (!config) {
|
|
2082
|
+
return null;
|
|
2083
|
+
}
|
|
2084
|
+
const { isEligible: eligibilityCheck, experimentFlagKey } = config;
|
|
2085
|
+
const isEligible = eligibilityCheck();
|
|
2086
|
+
if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
|
|
2064
2087
|
return null;
|
|
2065
2088
|
}
|
|
2066
2089
|
const experimentValue = window.experimentIntegration?.getVariant?.(
|
|
2067
|
-
|
|
2090
|
+
experimentFlagKey
|
|
2068
2091
|
);
|
|
2069
2092
|
const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
2070
2093
|
if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
|
|
@@ -2072,7 +2095,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2072
2095
|
if (available) {
|
|
2073
2096
|
trackApplePayExperimentExposure(
|
|
2074
2097
|
experimentValue,
|
|
2075
|
-
getExperimentKeyFromNextData(
|
|
2098
|
+
getExperimentKeyFromNextData(experimentFlagKey),
|
|
2099
|
+
experimentFlagKey
|
|
2076
2100
|
);
|
|
2077
2101
|
}
|
|
2078
2102
|
});
|
|
@@ -2187,18 +2211,32 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2187
2211
|
if (await this.#fetchAndCacheOptions()) return;
|
|
2188
2212
|
this.#finishLoading();
|
|
2189
2213
|
} catch {
|
|
2190
|
-
this
|
|
2191
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2214
|
+
this.#hide();
|
|
2192
2215
|
} finally {
|
|
2193
2216
|
this.#rendering = false;
|
|
2194
2217
|
}
|
|
2195
2218
|
}
|
|
2219
|
+
/**
|
|
2220
|
+
* Stop the loading spinner before tear-down so Safari does not leave a GPU
|
|
2221
|
+
* ghost of `.apple-pay-btn.wap-loading::before` after the container is removed.
|
|
2222
|
+
*/
|
|
2223
|
+
#hide() {
|
|
2224
|
+
const button = this.querySelector(SEL_BUTTON);
|
|
2225
|
+
if (button) {
|
|
2226
|
+
button.classList.remove("wap-loading");
|
|
2227
|
+
button.removeAttribute("aria-busy");
|
|
2228
|
+
button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2229
|
+
}
|
|
2230
|
+
this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2231
|
+
void this.offsetHeight;
|
|
2232
|
+
this.style.display = "none";
|
|
2233
|
+
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2234
|
+
}
|
|
2196
2235
|
/** Returns `true` (hide) when Apple Pay is unavailable on this device/browser. */
|
|
2197
2236
|
async #checkAvailability() {
|
|
2198
2237
|
const available = await isApplePayAvailable();
|
|
2199
2238
|
if (!available) {
|
|
2200
|
-
this
|
|
2201
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2239
|
+
this.#hide();
|
|
2202
2240
|
return true;
|
|
2203
2241
|
}
|
|
2204
2242
|
return false;
|
|
@@ -2210,8 +2248,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2210
2248
|
async #checkSession() {
|
|
2211
2249
|
this.#sessionData = await this.#fetchSession();
|
|
2212
2250
|
if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
|
|
2213
|
-
this
|
|
2214
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2251
|
+
this.#hide();
|
|
2215
2252
|
return true;
|
|
2216
2253
|
}
|
|
2217
2254
|
return false;
|
|
@@ -2219,8 +2256,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2219
2256
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2220
2257
|
#checkOffer() {
|
|
2221
2258
|
if (!this.#offer) {
|
|
2222
|
-
this
|
|
2223
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2259
|
+
this.#hide();
|
|
2224
2260
|
return true;
|
|
2225
2261
|
}
|
|
2226
2262
|
return false;
|
|
@@ -2247,8 +2283,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2247
2283
|
async #fetchAndCacheOptions() {
|
|
2248
2284
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2249
2285
|
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2250
|
-
this
|
|
2251
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2286
|
+
this.#hide();
|
|
2252
2287
|
return true;
|
|
2253
2288
|
}
|
|
2254
2289
|
return false;
|
|
@@ -2393,6 +2428,9 @@ function defineApplePayElements() {
|
|
|
2393
2428
|
}
|
|
2394
2429
|
export {
|
|
2395
2430
|
APPLE_PAY_EXCLUDED_VARIANTS,
|
|
2431
|
+
APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
|
|
2432
|
+
APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY,
|
|
2433
|
+
APPLE_PAY_EXPRESS_VARIANTS,
|
|
2396
2434
|
ApplePayButton,
|
|
2397
2435
|
ApplePayEntryPoint,
|
|
2398
2436
|
ApplePayModal,
|
|
@@ -8,9 +8,12 @@ export declare class ApplePayButton extends HTMLElement {
|
|
|
8
8
|
/**
|
|
9
9
|
* Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
|
|
10
10
|
*
|
|
11
|
-
* Reads the experiment variant from `window.experimentIntegration.getVariant
|
|
12
|
-
* {@link
|
|
13
|
-
*
|
|
11
|
+
* Reads the experiment variant from `window.experimentIntegration.getVariant`:
|
|
12
|
+
* - {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY} for `PAYWALL`
|
|
13
|
+
* - {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY} for `REGWALL` / `DUAL_OFFER_BANNER`
|
|
14
|
+
*
|
|
15
|
+
* The host page is responsible for setting up `window.experimentIntegration`
|
|
16
|
+
* before calling this method.
|
|
14
17
|
*
|
|
15
18
|
* - `treatment` → button created and returned
|
|
16
19
|
* - `control` / missing / anything else → returns null (button suppressed)
|
|
@@ -20,11 +23,10 @@ export declare class ApplePayButton extends HTMLElement {
|
|
|
20
23
|
* `window.experimentIntegration`. Once all consumers are migrated, the URL param
|
|
21
24
|
* fallback will be removed.
|
|
22
25
|
*
|
|
23
|
-
* **
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* the dual-offer banner is only mounted for anonymous visitors.
|
|
26
|
+
* **Eligibility:**
|
|
27
|
+
* - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone (SMA-3301)
|
|
28
|
+
* - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
|
|
29
|
+
* - `REGWALL`: no host-side placement gate (pre-SMA-3301 article behaviour)
|
|
28
30
|
*
|
|
29
31
|
* @param offer - The offer to display in the Apple Pay flow.
|
|
30
32
|
* @param country - The user's country code.
|
|
@@ -1300,6 +1300,7 @@ var redirectToCheckoutFallback = (params) => {
|
|
|
1300
1300
|
|
|
1301
1301
|
// src/constants.ts
|
|
1302
1302
|
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
1303
|
+
var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
1303
1304
|
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
1304
1305
|
CONTROL: "control",
|
|
1305
1306
|
TREATMENT: "treatment"
|
|
@@ -1342,7 +1343,7 @@ var track = (action, extra) => {
|
|
|
1342
1343
|
...extra
|
|
1343
1344
|
});
|
|
1344
1345
|
};
|
|
1345
|
-
var trackApplePayExperimentExposure = (variant, experimentKey) => {
|
|
1346
|
+
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey = APPLE_PAY_EXPRESS_EXPERIMENT_KEY) => {
|
|
1346
1347
|
const isActiveVariant = variant === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || variant === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
1347
1348
|
if (!isActiveVariant) {
|
|
1348
1349
|
return;
|
|
@@ -1350,14 +1351,14 @@ var trackApplePayExperimentExposure = (variant, experimentKey) => {
|
|
|
1350
1351
|
const exposures = window.__applePayExperimentExposures ?? {};
|
|
1351
1352
|
window.__applePayExperimentExposures = exposures;
|
|
1352
1353
|
const pathname = window.location?.pathname ?? "";
|
|
1353
|
-
const dedupeKey = `${pathname}:${
|
|
1354
|
+
const dedupeKey = `${pathname}:${flagKey}:${variant}`;
|
|
1354
1355
|
if (exposures[dedupeKey]) {
|
|
1355
1356
|
return;
|
|
1356
1357
|
}
|
|
1357
1358
|
exposures[dedupeKey] = true;
|
|
1358
1359
|
emitTedlEvent({
|
|
1359
1360
|
name: "$exposure",
|
|
1360
|
-
flag_key:
|
|
1361
|
+
flag_key: flagKey,
|
|
1361
1362
|
variant,
|
|
1362
1363
|
...experimentKey ? { experiment_key: experimentKey } : {}
|
|
1363
1364
|
});
|
|
@@ -1995,8 +1996,23 @@ var getExperimentKeyFromNextData = (flagKey) => {
|
|
|
1995
1996
|
// src/utils/applePayExpressEligibility.ts
|
|
1996
1997
|
var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
|
|
1997
1998
|
var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
|
|
1999
|
+
var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
|
|
1998
2000
|
|
|
1999
2001
|
// src/apple-pay-button.ts
|
|
2002
|
+
var ENTRY_POINT_CONFIG = {
|
|
2003
|
+
["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
|
|
2004
|
+
isEligible: isEligibleForApplePayExpressExperiment,
|
|
2005
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
|
|
2006
|
+
},
|
|
2007
|
+
["article_paywall" /* PAYWALL */]: {
|
|
2008
|
+
isEligible: isEligibleForApplePayExpressPaywallExperiment,
|
|
2009
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY
|
|
2010
|
+
},
|
|
2011
|
+
["article_regwall" /* REGWALL */]: {
|
|
2012
|
+
isEligible: () => true,
|
|
2013
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
|
|
2014
|
+
}
|
|
2015
|
+
};
|
|
2000
2016
|
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
2001
2017
|
var TOTAL_LABEL = "The Economist";
|
|
2002
2018
|
var DEFAULT_CURRENCY = "USD";
|
|
@@ -2015,9 +2031,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2015
2031
|
/**
|
|
2016
2032
|
* Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
|
|
2017
2033
|
*
|
|
2018
|
-
* Reads the experiment variant from `window.experimentIntegration.getVariant
|
|
2019
|
-
* {@link
|
|
2020
|
-
*
|
|
2034
|
+
* Reads the experiment variant from `window.experimentIntegration.getVariant`:
|
|
2035
|
+
* - {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY} for `PAYWALL`
|
|
2036
|
+
* - {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY} for `REGWALL` / `DUAL_OFFER_BANNER`
|
|
2037
|
+
*
|
|
2038
|
+
* The host page is responsible for setting up `window.experimentIntegration`
|
|
2039
|
+
* before calling this method.
|
|
2021
2040
|
*
|
|
2022
2041
|
* - `treatment` → button created and returned
|
|
2023
2042
|
* - `control` / missing / anything else → returns null (button suppressed)
|
|
@@ -2027,11 +2046,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2027
2046
|
* `window.experimentIntegration`. Once all consumers are migrated, the URL param
|
|
2028
2047
|
* fallback will be removed.
|
|
2029
2048
|
*
|
|
2030
|
-
* **
|
|
2031
|
-
*
|
|
2032
|
-
*
|
|
2033
|
-
*
|
|
2034
|
-
* the dual-offer banner is only mounted for anonymous visitors.
|
|
2049
|
+
* **Eligibility:**
|
|
2050
|
+
* - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone (SMA-3301)
|
|
2051
|
+
* - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
|
|
2052
|
+
* - `REGWALL`: no host-side placement gate (pre-SMA-3301 article behaviour)
|
|
2035
2053
|
*
|
|
2036
2054
|
* @param offer - The offer to display in the Apple Pay flow.
|
|
2037
2055
|
* @param country - The user's country code.
|
|
@@ -2047,13 +2065,18 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2047
2065
|
const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
|
|
2048
2066
|
FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
|
|
2049
2067
|
);
|
|
2050
|
-
const
|
|
2051
|
-
const
|
|
2052
|
-
if (
|
|
2068
|
+
const resolvedEntryPoint = entryPoint || "dual_offer_banner" /* DUAL_OFFER_BANNER */;
|
|
2069
|
+
const config = ENTRY_POINT_CONFIG[resolvedEntryPoint];
|
|
2070
|
+
if (!config) {
|
|
2071
|
+
return null;
|
|
2072
|
+
}
|
|
2073
|
+
const { isEligible: eligibilityCheck, experimentFlagKey } = config;
|
|
2074
|
+
const isEligible = eligibilityCheck();
|
|
2075
|
+
if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
|
|
2053
2076
|
return null;
|
|
2054
2077
|
}
|
|
2055
2078
|
const experimentValue = window.experimentIntegration?.getVariant?.(
|
|
2056
|
-
|
|
2079
|
+
experimentFlagKey
|
|
2057
2080
|
);
|
|
2058
2081
|
const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
2059
2082
|
if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
|
|
@@ -2061,7 +2084,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2061
2084
|
if (available) {
|
|
2062
2085
|
trackApplePayExperimentExposure(
|
|
2063
2086
|
experimentValue,
|
|
2064
|
-
getExperimentKeyFromNextData(
|
|
2087
|
+
getExperimentKeyFromNextData(experimentFlagKey),
|
|
2088
|
+
experimentFlagKey
|
|
2065
2089
|
);
|
|
2066
2090
|
}
|
|
2067
2091
|
});
|
|
@@ -2176,18 +2200,32 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2176
2200
|
if (await this.#fetchAndCacheOptions()) return;
|
|
2177
2201
|
this.#finishLoading();
|
|
2178
2202
|
} catch {
|
|
2179
|
-
this
|
|
2180
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2203
|
+
this.#hide();
|
|
2181
2204
|
} finally {
|
|
2182
2205
|
this.#rendering = false;
|
|
2183
2206
|
}
|
|
2184
2207
|
}
|
|
2208
|
+
/**
|
|
2209
|
+
* Stop the loading spinner before tear-down so Safari does not leave a GPU
|
|
2210
|
+
* ghost of `.apple-pay-btn.wap-loading::before` after the container is removed.
|
|
2211
|
+
*/
|
|
2212
|
+
#hide() {
|
|
2213
|
+
const button = this.querySelector(SEL_BUTTON);
|
|
2214
|
+
if (button) {
|
|
2215
|
+
button.classList.remove("wap-loading");
|
|
2216
|
+
button.removeAttribute("aria-busy");
|
|
2217
|
+
button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2218
|
+
}
|
|
2219
|
+
this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2220
|
+
void this.offsetHeight;
|
|
2221
|
+
this.style.display = "none";
|
|
2222
|
+
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2223
|
+
}
|
|
2185
2224
|
/** Returns `true` (hide) when Apple Pay is unavailable on this device/browser. */
|
|
2186
2225
|
async #checkAvailability() {
|
|
2187
2226
|
const available = await isApplePayAvailable();
|
|
2188
2227
|
if (!available) {
|
|
2189
|
-
this
|
|
2190
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2228
|
+
this.#hide();
|
|
2191
2229
|
return true;
|
|
2192
2230
|
}
|
|
2193
2231
|
return false;
|
|
@@ -2199,8 +2237,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2199
2237
|
async #checkSession() {
|
|
2200
2238
|
this.#sessionData = await this.#fetchSession();
|
|
2201
2239
|
if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
|
|
2202
|
-
this
|
|
2203
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2240
|
+
this.#hide();
|
|
2204
2241
|
return true;
|
|
2205
2242
|
}
|
|
2206
2243
|
return false;
|
|
@@ -2208,8 +2245,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2208
2245
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2209
2246
|
#checkOffer() {
|
|
2210
2247
|
if (!this.#offer) {
|
|
2211
|
-
this
|
|
2212
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2248
|
+
this.#hide();
|
|
2213
2249
|
return true;
|
|
2214
2250
|
}
|
|
2215
2251
|
return false;
|
|
@@ -2236,8 +2272,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2236
2272
|
async #fetchAndCacheOptions() {
|
|
2237
2273
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2238
2274
|
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2239
|
-
this
|
|
2240
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2275
|
+
this.#hide();
|
|
2241
2276
|
return true;
|
|
2242
2277
|
}
|
|
2243
2278
|
return false;
|
|
@@ -1308,6 +1308,7 @@ var redirectToCheckoutFallback = (params) => {
|
|
|
1308
1308
|
|
|
1309
1309
|
// src/constants.ts
|
|
1310
1310
|
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
1311
|
+
var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
1311
1312
|
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
1312
1313
|
CONTROL: "control",
|
|
1313
1314
|
TREATMENT: "treatment"
|
|
@@ -1350,7 +1351,7 @@ var track = (action, extra) => {
|
|
|
1350
1351
|
...extra
|
|
1351
1352
|
});
|
|
1352
1353
|
};
|
|
1353
|
-
var trackApplePayExperimentExposure = (variant, experimentKey) => {
|
|
1354
|
+
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey = APPLE_PAY_EXPRESS_EXPERIMENT_KEY) => {
|
|
1354
1355
|
const isActiveVariant = variant === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || variant === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
1355
1356
|
if (!isActiveVariant) {
|
|
1356
1357
|
return;
|
|
@@ -1358,14 +1359,14 @@ var trackApplePayExperimentExposure = (variant, experimentKey) => {
|
|
|
1358
1359
|
const exposures = window.__applePayExperimentExposures ?? {};
|
|
1359
1360
|
window.__applePayExperimentExposures = exposures;
|
|
1360
1361
|
const pathname = window.location?.pathname ?? "";
|
|
1361
|
-
const dedupeKey = `${pathname}:${
|
|
1362
|
+
const dedupeKey = `${pathname}:${flagKey}:${variant}`;
|
|
1362
1363
|
if (exposures[dedupeKey]) {
|
|
1363
1364
|
return;
|
|
1364
1365
|
}
|
|
1365
1366
|
exposures[dedupeKey] = true;
|
|
1366
1367
|
emitTedlEvent({
|
|
1367
1368
|
name: "$exposure",
|
|
1368
|
-
flag_key:
|
|
1369
|
+
flag_key: flagKey,
|
|
1369
1370
|
variant,
|
|
1370
1371
|
...experimentKey ? { experiment_key: experimentKey } : {}
|
|
1371
1372
|
});
|
|
@@ -2003,8 +2004,23 @@ var getExperimentKeyFromNextData = (flagKey) => {
|
|
|
2003
2004
|
// src/utils/applePayExpressEligibility.ts
|
|
2004
2005
|
var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
|
|
2005
2006
|
var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
|
|
2007
|
+
var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
|
|
2006
2008
|
|
|
2007
2009
|
// src/apple-pay-button.ts
|
|
2010
|
+
var ENTRY_POINT_CONFIG = {
|
|
2011
|
+
["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
|
|
2012
|
+
isEligible: isEligibleForApplePayExpressExperiment,
|
|
2013
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
|
|
2014
|
+
},
|
|
2015
|
+
["article_paywall" /* PAYWALL */]: {
|
|
2016
|
+
isEligible: isEligibleForApplePayExpressPaywallExperiment,
|
|
2017
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY
|
|
2018
|
+
},
|
|
2019
|
+
["article_regwall" /* REGWALL */]: {
|
|
2020
|
+
isEligible: () => true,
|
|
2021
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
|
|
2022
|
+
}
|
|
2023
|
+
};
|
|
2008
2024
|
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
2009
2025
|
var TOTAL_LABEL = "The Economist";
|
|
2010
2026
|
var DEFAULT_CURRENCY = "USD";
|
|
@@ -2023,9 +2039,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2023
2039
|
/**
|
|
2024
2040
|
* Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
|
|
2025
2041
|
*
|
|
2026
|
-
* Reads the experiment variant from `window.experimentIntegration.getVariant
|
|
2027
|
-
* {@link
|
|
2028
|
-
*
|
|
2042
|
+
* Reads the experiment variant from `window.experimentIntegration.getVariant`:
|
|
2043
|
+
* - {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY} for `PAYWALL`
|
|
2044
|
+
* - {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY} for `REGWALL` / `DUAL_OFFER_BANNER`
|
|
2045
|
+
*
|
|
2046
|
+
* The host page is responsible for setting up `window.experimentIntegration`
|
|
2047
|
+
* before calling this method.
|
|
2029
2048
|
*
|
|
2030
2049
|
* - `treatment` → button created and returned
|
|
2031
2050
|
* - `control` / missing / anything else → returns null (button suppressed)
|
|
@@ -2035,11 +2054,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2035
2054
|
* `window.experimentIntegration`. Once all consumers are migrated, the URL param
|
|
2036
2055
|
* fallback will be removed.
|
|
2037
2056
|
*
|
|
2038
|
-
* **
|
|
2039
|
-
*
|
|
2040
|
-
*
|
|
2041
|
-
*
|
|
2042
|
-
* the dual-offer banner is only mounted for anonymous visitors.
|
|
2057
|
+
* **Eligibility:**
|
|
2058
|
+
* - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone (SMA-3301)
|
|
2059
|
+
* - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
|
|
2060
|
+
* - `REGWALL`: no host-side placement gate (pre-SMA-3301 article behaviour)
|
|
2043
2061
|
*
|
|
2044
2062
|
* @param offer - The offer to display in the Apple Pay flow.
|
|
2045
2063
|
* @param country - The user's country code.
|
|
@@ -2055,13 +2073,18 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2055
2073
|
const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
|
|
2056
2074
|
FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
|
|
2057
2075
|
);
|
|
2058
|
-
const
|
|
2059
|
-
const
|
|
2060
|
-
if (
|
|
2076
|
+
const resolvedEntryPoint = entryPoint || "dual_offer_banner" /* DUAL_OFFER_BANNER */;
|
|
2077
|
+
const config = ENTRY_POINT_CONFIG[resolvedEntryPoint];
|
|
2078
|
+
if (!config) {
|
|
2079
|
+
return null;
|
|
2080
|
+
}
|
|
2081
|
+
const { isEligible: eligibilityCheck, experimentFlagKey } = config;
|
|
2082
|
+
const isEligible = eligibilityCheck();
|
|
2083
|
+
if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
|
|
2061
2084
|
return null;
|
|
2062
2085
|
}
|
|
2063
2086
|
const experimentValue = window.experimentIntegration?.getVariant?.(
|
|
2064
|
-
|
|
2087
|
+
experimentFlagKey
|
|
2065
2088
|
);
|
|
2066
2089
|
const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
2067
2090
|
if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
|
|
@@ -2069,7 +2092,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2069
2092
|
if (available) {
|
|
2070
2093
|
trackApplePayExperimentExposure(
|
|
2071
2094
|
experimentValue,
|
|
2072
|
-
getExperimentKeyFromNextData(
|
|
2095
|
+
getExperimentKeyFromNextData(experimentFlagKey),
|
|
2096
|
+
experimentFlagKey
|
|
2073
2097
|
);
|
|
2074
2098
|
}
|
|
2075
2099
|
});
|
|
@@ -2184,18 +2208,32 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2184
2208
|
if (await this.#fetchAndCacheOptions()) return;
|
|
2185
2209
|
this.#finishLoading();
|
|
2186
2210
|
} catch {
|
|
2187
|
-
this
|
|
2188
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2211
|
+
this.#hide();
|
|
2189
2212
|
} finally {
|
|
2190
2213
|
this.#rendering = false;
|
|
2191
2214
|
}
|
|
2192
2215
|
}
|
|
2216
|
+
/**
|
|
2217
|
+
* Stop the loading spinner before tear-down so Safari does not leave a GPU
|
|
2218
|
+
* ghost of `.apple-pay-btn.wap-loading::before` after the container is removed.
|
|
2219
|
+
*/
|
|
2220
|
+
#hide() {
|
|
2221
|
+
const button = this.querySelector(SEL_BUTTON);
|
|
2222
|
+
if (button) {
|
|
2223
|
+
button.classList.remove("wap-loading");
|
|
2224
|
+
button.removeAttribute("aria-busy");
|
|
2225
|
+
button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2226
|
+
}
|
|
2227
|
+
this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2228
|
+
void this.offsetHeight;
|
|
2229
|
+
this.style.display = "none";
|
|
2230
|
+
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2231
|
+
}
|
|
2193
2232
|
/** Returns `true` (hide) when Apple Pay is unavailable on this device/browser. */
|
|
2194
2233
|
async #checkAvailability() {
|
|
2195
2234
|
const available = await isApplePayAvailable();
|
|
2196
2235
|
if (!available) {
|
|
2197
|
-
this
|
|
2198
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2236
|
+
this.#hide();
|
|
2199
2237
|
return true;
|
|
2200
2238
|
}
|
|
2201
2239
|
return false;
|
|
@@ -2207,8 +2245,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2207
2245
|
async #checkSession() {
|
|
2208
2246
|
this.#sessionData = await this.#fetchSession();
|
|
2209
2247
|
if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
|
|
2210
|
-
this
|
|
2211
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2248
|
+
this.#hide();
|
|
2212
2249
|
return true;
|
|
2213
2250
|
}
|
|
2214
2251
|
return false;
|
|
@@ -2216,8 +2253,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2216
2253
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2217
2254
|
#checkOffer() {
|
|
2218
2255
|
if (!this.#offer) {
|
|
2219
|
-
this
|
|
2220
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2256
|
+
this.#hide();
|
|
2221
2257
|
return true;
|
|
2222
2258
|
}
|
|
2223
2259
|
return false;
|
|
@@ -2244,8 +2280,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2244
2280
|
async #fetchAndCacheOptions() {
|
|
2245
2281
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2246
2282
|
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2247
|
-
this
|
|
2248
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2283
|
+
this.#hide();
|
|
2249
2284
|
return true;
|
|
2250
2285
|
}
|
|
2251
2286
|
return false;
|
|
@@ -1300,6 +1300,7 @@ var redirectToCheckoutFallback = (params) => {
|
|
|
1300
1300
|
|
|
1301
1301
|
// src/constants.ts
|
|
1302
1302
|
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
1303
|
+
var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
1303
1304
|
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
1304
1305
|
CONTROL: "control",
|
|
1305
1306
|
TREATMENT: "treatment"
|
|
@@ -1342,7 +1343,7 @@ var track = (action, extra) => {
|
|
|
1342
1343
|
...extra
|
|
1343
1344
|
});
|
|
1344
1345
|
};
|
|
1345
|
-
var trackApplePayExperimentExposure = (variant, experimentKey) => {
|
|
1346
|
+
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey = APPLE_PAY_EXPRESS_EXPERIMENT_KEY) => {
|
|
1346
1347
|
const isActiveVariant = variant === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || variant === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
1347
1348
|
if (!isActiveVariant) {
|
|
1348
1349
|
return;
|
|
@@ -1350,14 +1351,14 @@ var trackApplePayExperimentExposure = (variant, experimentKey) => {
|
|
|
1350
1351
|
const exposures = window.__applePayExperimentExposures ?? {};
|
|
1351
1352
|
window.__applePayExperimentExposures = exposures;
|
|
1352
1353
|
const pathname = window.location?.pathname ?? "";
|
|
1353
|
-
const dedupeKey = `${pathname}:${
|
|
1354
|
+
const dedupeKey = `${pathname}:${flagKey}:${variant}`;
|
|
1354
1355
|
if (exposures[dedupeKey]) {
|
|
1355
1356
|
return;
|
|
1356
1357
|
}
|
|
1357
1358
|
exposures[dedupeKey] = true;
|
|
1358
1359
|
emitTedlEvent({
|
|
1359
1360
|
name: "$exposure",
|
|
1360
|
-
flag_key:
|
|
1361
|
+
flag_key: flagKey,
|
|
1361
1362
|
variant,
|
|
1362
1363
|
...experimentKey ? { experiment_key: experimentKey } : {}
|
|
1363
1364
|
});
|
|
@@ -1995,8 +1996,23 @@ var getExperimentKeyFromNextData = (flagKey) => {
|
|
|
1995
1996
|
// src/utils/applePayExpressEligibility.ts
|
|
1996
1997
|
var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
|
|
1997
1998
|
var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
|
|
1999
|
+
var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
|
|
1998
2000
|
|
|
1999
2001
|
// src/apple-pay-button.ts
|
|
2002
|
+
var ENTRY_POINT_CONFIG = {
|
|
2003
|
+
["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
|
|
2004
|
+
isEligible: isEligibleForApplePayExpressExperiment,
|
|
2005
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
|
|
2006
|
+
},
|
|
2007
|
+
["article_paywall" /* PAYWALL */]: {
|
|
2008
|
+
isEligible: isEligibleForApplePayExpressPaywallExperiment,
|
|
2009
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY
|
|
2010
|
+
},
|
|
2011
|
+
["article_regwall" /* REGWALL */]: {
|
|
2012
|
+
isEligible: () => true,
|
|
2013
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
|
|
2014
|
+
}
|
|
2015
|
+
};
|
|
2000
2016
|
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
2001
2017
|
var TOTAL_LABEL = "The Economist";
|
|
2002
2018
|
var DEFAULT_CURRENCY = "USD";
|
|
@@ -2015,9 +2031,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2015
2031
|
/**
|
|
2016
2032
|
* Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
|
|
2017
2033
|
*
|
|
2018
|
-
* Reads the experiment variant from `window.experimentIntegration.getVariant
|
|
2019
|
-
* {@link
|
|
2020
|
-
*
|
|
2034
|
+
* Reads the experiment variant from `window.experimentIntegration.getVariant`:
|
|
2035
|
+
* - {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY} for `PAYWALL`
|
|
2036
|
+
* - {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY} for `REGWALL` / `DUAL_OFFER_BANNER`
|
|
2037
|
+
*
|
|
2038
|
+
* The host page is responsible for setting up `window.experimentIntegration`
|
|
2039
|
+
* before calling this method.
|
|
2021
2040
|
*
|
|
2022
2041
|
* - `treatment` → button created and returned
|
|
2023
2042
|
* - `control` / missing / anything else → returns null (button suppressed)
|
|
@@ -2027,11 +2046,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2027
2046
|
* `window.experimentIntegration`. Once all consumers are migrated, the URL param
|
|
2028
2047
|
* fallback will be removed.
|
|
2029
2048
|
*
|
|
2030
|
-
* **
|
|
2031
|
-
*
|
|
2032
|
-
*
|
|
2033
|
-
*
|
|
2034
|
-
* the dual-offer banner is only mounted for anonymous visitors.
|
|
2049
|
+
* **Eligibility:**
|
|
2050
|
+
* - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone (SMA-3301)
|
|
2051
|
+
* - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
|
|
2052
|
+
* - `REGWALL`: no host-side placement gate (pre-SMA-3301 article behaviour)
|
|
2035
2053
|
*
|
|
2036
2054
|
* @param offer - The offer to display in the Apple Pay flow.
|
|
2037
2055
|
* @param country - The user's country code.
|
|
@@ -2047,13 +2065,18 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2047
2065
|
const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
|
|
2048
2066
|
FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
|
|
2049
2067
|
);
|
|
2050
|
-
const
|
|
2051
|
-
const
|
|
2052
|
-
if (
|
|
2068
|
+
const resolvedEntryPoint = entryPoint || "dual_offer_banner" /* DUAL_OFFER_BANNER */;
|
|
2069
|
+
const config = ENTRY_POINT_CONFIG[resolvedEntryPoint];
|
|
2070
|
+
if (!config) {
|
|
2071
|
+
return null;
|
|
2072
|
+
}
|
|
2073
|
+
const { isEligible: eligibilityCheck, experimentFlagKey } = config;
|
|
2074
|
+
const isEligible = eligibilityCheck();
|
|
2075
|
+
if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
|
|
2053
2076
|
return null;
|
|
2054
2077
|
}
|
|
2055
2078
|
const experimentValue = window.experimentIntegration?.getVariant?.(
|
|
2056
|
-
|
|
2079
|
+
experimentFlagKey
|
|
2057
2080
|
);
|
|
2058
2081
|
const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
2059
2082
|
if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
|
|
@@ -2061,7 +2084,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2061
2084
|
if (available) {
|
|
2062
2085
|
trackApplePayExperimentExposure(
|
|
2063
2086
|
experimentValue,
|
|
2064
|
-
getExperimentKeyFromNextData(
|
|
2087
|
+
getExperimentKeyFromNextData(experimentFlagKey),
|
|
2088
|
+
experimentFlagKey
|
|
2065
2089
|
);
|
|
2066
2090
|
}
|
|
2067
2091
|
});
|
|
@@ -2176,18 +2200,32 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2176
2200
|
if (await this.#fetchAndCacheOptions()) return;
|
|
2177
2201
|
this.#finishLoading();
|
|
2178
2202
|
} catch {
|
|
2179
|
-
this
|
|
2180
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2203
|
+
this.#hide();
|
|
2181
2204
|
} finally {
|
|
2182
2205
|
this.#rendering = false;
|
|
2183
2206
|
}
|
|
2184
2207
|
}
|
|
2208
|
+
/**
|
|
2209
|
+
* Stop the loading spinner before tear-down so Safari does not leave a GPU
|
|
2210
|
+
* ghost of `.apple-pay-btn.wap-loading::before` after the container is removed.
|
|
2211
|
+
*/
|
|
2212
|
+
#hide() {
|
|
2213
|
+
const button = this.querySelector(SEL_BUTTON);
|
|
2214
|
+
if (button) {
|
|
2215
|
+
button.classList.remove("wap-loading");
|
|
2216
|
+
button.removeAttribute("aria-busy");
|
|
2217
|
+
button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2218
|
+
}
|
|
2219
|
+
this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2220
|
+
void this.offsetHeight;
|
|
2221
|
+
this.style.display = "none";
|
|
2222
|
+
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2223
|
+
}
|
|
2185
2224
|
/** Returns `true` (hide) when Apple Pay is unavailable on this device/browser. */
|
|
2186
2225
|
async #checkAvailability() {
|
|
2187
2226
|
const available = await isApplePayAvailable();
|
|
2188
2227
|
if (!available) {
|
|
2189
|
-
this
|
|
2190
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2228
|
+
this.#hide();
|
|
2191
2229
|
return true;
|
|
2192
2230
|
}
|
|
2193
2231
|
return false;
|
|
@@ -2199,8 +2237,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2199
2237
|
async #checkSession() {
|
|
2200
2238
|
this.#sessionData = await this.#fetchSession();
|
|
2201
2239
|
if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
|
|
2202
|
-
this
|
|
2203
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2240
|
+
this.#hide();
|
|
2204
2241
|
return true;
|
|
2205
2242
|
}
|
|
2206
2243
|
return false;
|
|
@@ -2208,8 +2245,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2208
2245
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2209
2246
|
#checkOffer() {
|
|
2210
2247
|
if (!this.#offer) {
|
|
2211
|
-
this
|
|
2212
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2248
|
+
this.#hide();
|
|
2213
2249
|
return true;
|
|
2214
2250
|
}
|
|
2215
2251
|
return false;
|
|
@@ -2236,8 +2272,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2236
2272
|
async #fetchAndCacheOptions() {
|
|
2237
2273
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2238
2274
|
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2239
|
-
this
|
|
2240
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2275
|
+
this.#hide();
|
|
2241
2276
|
return true;
|
|
2242
2277
|
}
|
|
2243
2278
|
return false;
|
package/dist/src/constants.d.ts
CHANGED
|
@@ -4,10 +4,12 @@ export declare enum ApplePayEntryPoint {
|
|
|
4
4
|
DUAL_OFFER_BANNER = "dual_offer_banner"
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
|
-
* Amplitude experiment key for Apple Pay Express Checkout on banners
|
|
7
|
+
* Amplitude experiment key for Apple Pay Express Checkout on homepage banners
|
|
8
|
+
* (dual-offer banner) and article banner regwalls.
|
|
9
|
+
*
|
|
8
10
|
* This package reads the variant for this key internally via
|
|
9
11
|
* `window.experimentIntegration.getVariant()` — set up by the host page
|
|
10
|
-
* before `createIfEnabled` is called.
|
|
12
|
+
* before `createIfEnabled` is called.
|
|
11
13
|
*
|
|
12
14
|
* Fail-closed: missing integration, missing key, `control`, or Amplitude fetch
|
|
13
15
|
* failure on the host → button is hidden (unless QA URL param is present).
|
|
@@ -16,6 +18,20 @@ export declare enum ApplePayEntryPoint {
|
|
|
16
18
|
* (Engagement / Insider / Podcasts).
|
|
17
19
|
*/
|
|
18
20
|
export declare const APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
21
|
+
/**
|
|
22
|
+
* Amplitude experiment key for Apple Pay Express Checkout on article paywalls
|
|
23
|
+
* (`ApplePayEntryPoint.PAYWALL`, e.g. single-offer-paywall / multi-offer paywall).
|
|
24
|
+
*
|
|
25
|
+
* Same fail-closed / QA-param behaviour as {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY}.
|
|
26
|
+
* Eligibility for this flag ignores homepage and requires Safari/Apple device
|
|
27
|
+
* (plus `isApplePayAvailable` before `$exposure`).
|
|
28
|
+
*/
|
|
29
|
+
export declare const APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
30
|
+
/**
|
|
31
|
+
* Known Amplitude experiment flag keys for Apple Pay Express Checkout.
|
|
32
|
+
* Narrowed so callers cannot pass an arbitrary typo'd string.
|
|
33
|
+
*/
|
|
34
|
+
export type ApplePayExperimentFlagKey = typeof APPLE_PAY_EXPRESS_EXPERIMENT_KEY | typeof APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY;
|
|
19
35
|
/**
|
|
20
36
|
* Amplitude variant values for the Apple Pay Express Checkout experiment.
|
|
21
37
|
* CONTROL → button hidden (baseline)
|
package/dist/src/constants.js
CHANGED
|
@@ -6,12 +6,14 @@ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
|
|
|
6
6
|
return ApplePayEntryPoint2;
|
|
7
7
|
})(ApplePayEntryPoint || {});
|
|
8
8
|
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
9
|
+
var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
9
10
|
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
10
11
|
CONTROL: "control",
|
|
11
12
|
TREATMENT: "treatment"
|
|
12
13
|
};
|
|
13
14
|
export {
|
|
14
15
|
APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
|
|
16
|
+
APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY,
|
|
15
17
|
APPLE_PAY_EXPRESS_VARIANTS,
|
|
16
18
|
ApplePayEntryPoint
|
|
17
19
|
};
|
package/dist/src/index.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ export { ApplePayButton, APPLE_PAY_EXCLUDED_VARIANTS, } from './apple-pay-button
|
|
|
2
2
|
export { ApplePayModal } from './apple-pay-modal';
|
|
3
3
|
export { ensureApplePayLogoSymbol } from './apple-pay-logo';
|
|
4
4
|
export { configureApplePay } from './clients/payment-checkout/config';
|
|
5
|
-
export { ApplePayEntryPoint } from './constants';
|
|
5
|
+
export { ApplePayEntryPoint, APPLE_PAY_EXPRESS_EXPERIMENT_KEY, APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY, APPLE_PAY_EXPRESS_VARIANTS, } from './constants';
|
|
6
|
+
export type { ApplePayExperimentFlagKey } from './constants';
|
|
6
7
|
export type { ApplePayRuntimeConfig } from './clients/payment-checkout/config';
|
|
7
8
|
export type { Offer } from './types/offer.types';
|
|
8
9
|
export declare function defineApplePayElements(): void;
|
package/dist/src/index.js
CHANGED
|
@@ -1311,6 +1311,7 @@ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
|
|
|
1311
1311
|
return ApplePayEntryPoint2;
|
|
1312
1312
|
})(ApplePayEntryPoint || {});
|
|
1313
1313
|
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
1314
|
+
var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
1314
1315
|
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
1315
1316
|
CONTROL: "control",
|
|
1316
1317
|
TREATMENT: "treatment"
|
|
@@ -1353,7 +1354,7 @@ var track = (action, extra) => {
|
|
|
1353
1354
|
...extra
|
|
1354
1355
|
});
|
|
1355
1356
|
};
|
|
1356
|
-
var trackApplePayExperimentExposure = (variant, experimentKey) => {
|
|
1357
|
+
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey = APPLE_PAY_EXPRESS_EXPERIMENT_KEY) => {
|
|
1357
1358
|
const isActiveVariant = variant === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || variant === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
1358
1359
|
if (!isActiveVariant) {
|
|
1359
1360
|
return;
|
|
@@ -1361,14 +1362,14 @@ var trackApplePayExperimentExposure = (variant, experimentKey) => {
|
|
|
1361
1362
|
const exposures = window.__applePayExperimentExposures ?? {};
|
|
1362
1363
|
window.__applePayExperimentExposures = exposures;
|
|
1363
1364
|
const pathname = window.location?.pathname ?? "";
|
|
1364
|
-
const dedupeKey = `${pathname}:${
|
|
1365
|
+
const dedupeKey = `${pathname}:${flagKey}:${variant}`;
|
|
1365
1366
|
if (exposures[dedupeKey]) {
|
|
1366
1367
|
return;
|
|
1367
1368
|
}
|
|
1368
1369
|
exposures[dedupeKey] = true;
|
|
1369
1370
|
emitTedlEvent({
|
|
1370
1371
|
name: "$exposure",
|
|
1371
|
-
flag_key:
|
|
1372
|
+
flag_key: flagKey,
|
|
1372
1373
|
variant,
|
|
1373
1374
|
...experimentKey ? { experiment_key: experimentKey } : {}
|
|
1374
1375
|
});
|
|
@@ -2006,8 +2007,23 @@ var getExperimentKeyFromNextData = (flagKey) => {
|
|
|
2006
2007
|
// src/utils/applePayExpressEligibility.ts
|
|
2007
2008
|
var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
|
|
2008
2009
|
var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
|
|
2010
|
+
var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
|
|
2009
2011
|
|
|
2010
2012
|
// src/apple-pay-button.ts
|
|
2013
|
+
var ENTRY_POINT_CONFIG = {
|
|
2014
|
+
["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
|
|
2015
|
+
isEligible: isEligibleForApplePayExpressExperiment,
|
|
2016
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
|
|
2017
|
+
},
|
|
2018
|
+
["article_paywall" /* PAYWALL */]: {
|
|
2019
|
+
isEligible: isEligibleForApplePayExpressPaywallExperiment,
|
|
2020
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY
|
|
2021
|
+
},
|
|
2022
|
+
["article_regwall" /* REGWALL */]: {
|
|
2023
|
+
isEligible: () => true,
|
|
2024
|
+
experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
|
|
2025
|
+
}
|
|
2026
|
+
};
|
|
2011
2027
|
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
2012
2028
|
var TOTAL_LABEL = "The Economist";
|
|
2013
2029
|
var DEFAULT_CURRENCY = "USD";
|
|
@@ -2026,9 +2042,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2026
2042
|
/**
|
|
2027
2043
|
* Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
|
|
2028
2044
|
*
|
|
2029
|
-
* Reads the experiment variant from `window.experimentIntegration.getVariant
|
|
2030
|
-
* {@link
|
|
2031
|
-
*
|
|
2045
|
+
* Reads the experiment variant from `window.experimentIntegration.getVariant`:
|
|
2046
|
+
* - {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY} for `PAYWALL`
|
|
2047
|
+
* - {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY} for `REGWALL` / `DUAL_OFFER_BANNER`
|
|
2048
|
+
*
|
|
2049
|
+
* The host page is responsible for setting up `window.experimentIntegration`
|
|
2050
|
+
* before calling this method.
|
|
2032
2051
|
*
|
|
2033
2052
|
* - `treatment` → button created and returned
|
|
2034
2053
|
* - `control` / missing / anything else → returns null (button suppressed)
|
|
@@ -2038,11 +2057,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2038
2057
|
* `window.experimentIntegration`. Once all consumers are migrated, the URL param
|
|
2039
2058
|
* fallback will be removed.
|
|
2040
2059
|
*
|
|
2041
|
-
* **
|
|
2042
|
-
*
|
|
2043
|
-
*
|
|
2044
|
-
*
|
|
2045
|
-
* the dual-offer banner is only mounted for anonymous visitors.
|
|
2060
|
+
* **Eligibility:**
|
|
2061
|
+
* - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone (SMA-3301)
|
|
2062
|
+
* - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
|
|
2063
|
+
* - `REGWALL`: no host-side placement gate (pre-SMA-3301 article behaviour)
|
|
2046
2064
|
*
|
|
2047
2065
|
* @param offer - The offer to display in the Apple Pay flow.
|
|
2048
2066
|
* @param country - The user's country code.
|
|
@@ -2058,13 +2076,18 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2058
2076
|
const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
|
|
2059
2077
|
FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
|
|
2060
2078
|
);
|
|
2061
|
-
const
|
|
2062
|
-
const
|
|
2063
|
-
if (
|
|
2079
|
+
const resolvedEntryPoint = entryPoint || "dual_offer_banner" /* DUAL_OFFER_BANNER */;
|
|
2080
|
+
const config = ENTRY_POINT_CONFIG[resolvedEntryPoint];
|
|
2081
|
+
if (!config) {
|
|
2082
|
+
return null;
|
|
2083
|
+
}
|
|
2084
|
+
const { isEligible: eligibilityCheck, experimentFlagKey } = config;
|
|
2085
|
+
const isEligible = eligibilityCheck();
|
|
2086
|
+
if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
|
|
2064
2087
|
return null;
|
|
2065
2088
|
}
|
|
2066
2089
|
const experimentValue = window.experimentIntegration?.getVariant?.(
|
|
2067
|
-
|
|
2090
|
+
experimentFlagKey
|
|
2068
2091
|
);
|
|
2069
2092
|
const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
2070
2093
|
if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
|
|
@@ -2072,7 +2095,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2072
2095
|
if (available) {
|
|
2073
2096
|
trackApplePayExperimentExposure(
|
|
2074
2097
|
experimentValue,
|
|
2075
|
-
getExperimentKeyFromNextData(
|
|
2098
|
+
getExperimentKeyFromNextData(experimentFlagKey),
|
|
2099
|
+
experimentFlagKey
|
|
2076
2100
|
);
|
|
2077
2101
|
}
|
|
2078
2102
|
});
|
|
@@ -2187,18 +2211,32 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2187
2211
|
if (await this.#fetchAndCacheOptions()) return;
|
|
2188
2212
|
this.#finishLoading();
|
|
2189
2213
|
} catch {
|
|
2190
|
-
this
|
|
2191
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2214
|
+
this.#hide();
|
|
2192
2215
|
} finally {
|
|
2193
2216
|
this.#rendering = false;
|
|
2194
2217
|
}
|
|
2195
2218
|
}
|
|
2219
|
+
/**
|
|
2220
|
+
* Stop the loading spinner before tear-down so Safari does not leave a GPU
|
|
2221
|
+
* ghost of `.apple-pay-btn.wap-loading::before` after the container is removed.
|
|
2222
|
+
*/
|
|
2223
|
+
#hide() {
|
|
2224
|
+
const button = this.querySelector(SEL_BUTTON);
|
|
2225
|
+
if (button) {
|
|
2226
|
+
button.classList.remove("wap-loading");
|
|
2227
|
+
button.removeAttribute("aria-busy");
|
|
2228
|
+
button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2229
|
+
}
|
|
2230
|
+
this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2231
|
+
void this.offsetHeight;
|
|
2232
|
+
this.style.display = "none";
|
|
2233
|
+
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2234
|
+
}
|
|
2196
2235
|
/** Returns `true` (hide) when Apple Pay is unavailable on this device/browser. */
|
|
2197
2236
|
async #checkAvailability() {
|
|
2198
2237
|
const available = await isApplePayAvailable();
|
|
2199
2238
|
if (!available) {
|
|
2200
|
-
this
|
|
2201
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2239
|
+
this.#hide();
|
|
2202
2240
|
return true;
|
|
2203
2241
|
}
|
|
2204
2242
|
return false;
|
|
@@ -2210,8 +2248,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2210
2248
|
async #checkSession() {
|
|
2211
2249
|
this.#sessionData = await this.#fetchSession();
|
|
2212
2250
|
if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
|
|
2213
|
-
this
|
|
2214
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2251
|
+
this.#hide();
|
|
2215
2252
|
return true;
|
|
2216
2253
|
}
|
|
2217
2254
|
return false;
|
|
@@ -2219,8 +2256,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2219
2256
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2220
2257
|
#checkOffer() {
|
|
2221
2258
|
if (!this.#offer) {
|
|
2222
|
-
this
|
|
2223
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2259
|
+
this.#hide();
|
|
2224
2260
|
return true;
|
|
2225
2261
|
}
|
|
2226
2262
|
return false;
|
|
@@ -2247,8 +2283,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2247
2283
|
async #fetchAndCacheOptions() {
|
|
2248
2284
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2249
2285
|
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2250
|
-
this
|
|
2251
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2286
|
+
this.#hide();
|
|
2252
2287
|
return true;
|
|
2253
2288
|
}
|
|
2254
2289
|
return false;
|
|
@@ -2393,6 +2428,9 @@ function defineApplePayElements() {
|
|
|
2393
2428
|
}
|
|
2394
2429
|
export {
|
|
2395
2430
|
APPLE_PAY_EXCLUDED_VARIANTS,
|
|
2431
|
+
APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
|
|
2432
|
+
APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY,
|
|
2433
|
+
APPLE_PAY_EXPRESS_VARIANTS,
|
|
2396
2434
|
ApplePayButton,
|
|
2397
2435
|
ApplePayEntryPoint,
|
|
2398
2436
|
ApplePayModal,
|
|
@@ -2,15 +2,19 @@
|
|
|
2
2
|
* Host-side eligibility for Apple Pay Express Feature Experiment (SMA-3301).
|
|
3
3
|
*
|
|
4
4
|
* Gates createIfEnabled before getVariant / $exposure so only the intended
|
|
5
|
-
* population
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* respected). Amplitude audience targeting uses generic user_properties from
|
|
9
|
-
* Engagement.
|
|
5
|
+
* population participates. Exposure is further gated on isApplePayAvailable()
|
|
6
|
+
* (BYPASS_APPLE_PAY_CHECKS respected). Amplitude audience targeting uses
|
|
7
|
+
* generic user_properties from Engagement.
|
|
10
8
|
*/
|
|
11
9
|
export declare const isApplePayExpressHomepage: (pathname?: string) => boolean;
|
|
12
10
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* Dual-offer homepage banner: homepage + Safari/iPhone.
|
|
12
|
+
* Anonymous is assumed because the dual-offer banner is only mounted for
|
|
13
|
+
* anonymous visitors.
|
|
15
14
|
*/
|
|
16
15
|
export declare const isEligibleForApplePayExpressExperiment: () => boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Article paywalls (`ApplePayEntryPoint.PAYWALL`): Safari/Apple device only.
|
|
18
|
+
* Homepage targeting does not apply — paywalls render on article pages.
|
|
19
|
+
*/
|
|
20
|
+
export declare const isEligibleForApplePayExpressPaywallExperiment: () => boolean;
|
|
@@ -8,7 +8,9 @@ var isAppleDeviceOrSafari = () => {
|
|
|
8
8
|
// src/utils/applePayExpressEligibility.ts
|
|
9
9
|
var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
|
|
10
10
|
var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
|
|
11
|
+
var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
|
|
11
12
|
export {
|
|
12
13
|
isApplePayExpressHomepage,
|
|
13
|
-
isEligibleForApplePayExpressExperiment
|
|
14
|
+
isEligibleForApplePayExpressExperiment,
|
|
15
|
+
isEligibleForApplePayExpressPaywallExperiment
|
|
14
16
|
};
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Event names are aligned to the PRD spec (section 10 — Tracking & Analytics).
|
|
13
13
|
*/
|
|
14
|
+
import { type ApplePayExperimentFlagKey } from '../constants';
|
|
14
15
|
declare global {
|
|
15
16
|
interface Window {
|
|
16
17
|
tedl?: {
|
|
@@ -51,11 +52,15 @@ export type ImpressionMetadata = {
|
|
|
51
52
|
* Amplitude Experiment exposure for Apple Pay Express (SMA-3301).
|
|
52
53
|
*
|
|
53
54
|
* Fired from createIfEnabled only after isApplePayAvailable() succeeds
|
|
54
|
-
* (control or treatment). Deduped per pathname + variant so
|
|
55
|
-
* renders on the same page do not over-count. Includes
|
|
56
|
-
* Engagement SSR (__NEXT_DATA__) when present for run
|
|
55
|
+
* (control or treatment). Deduped per pathname + flag_key + variant so
|
|
56
|
+
* repeated renders on the same page do not over-count. Includes
|
|
57
|
+
* experiment_key from Engagement SSR (__NEXT_DATA__) when present for run
|
|
58
|
+
* attribution.
|
|
59
|
+
*
|
|
60
|
+
* @param flagKey - Amplitude flag_key. Defaults to the banners experiment;
|
|
61
|
+
* paywalls pass {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}.
|
|
57
62
|
*/
|
|
58
|
-
export declare const trackApplePayExperimentExposure: (variant: string, experimentKey?: string) => void;
|
|
63
|
+
export declare const trackApplePayExperimentExposure: (variant: string, experimentKey?: string, flagKey?: ApplePayExperimentFlagKey) => void;
|
|
59
64
|
/** Wallet button displayed — emits all 5 required analytics dimensions. */
|
|
60
65
|
export declare const trackExpressWalletImpression: (skuId: string, { entryPoint, country }: ImpressionMetadata) => void;
|
|
61
66
|
/** Wallet button clicked */
|
|
@@ -42,7 +42,7 @@ var track = (action, extra) => {
|
|
|
42
42
|
...extra
|
|
43
43
|
});
|
|
44
44
|
};
|
|
45
|
-
var trackApplePayExperimentExposure = (variant, experimentKey) => {
|
|
45
|
+
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey = APPLE_PAY_EXPRESS_EXPERIMENT_KEY) => {
|
|
46
46
|
const isActiveVariant = variant === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || variant === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
47
47
|
if (!isActiveVariant) {
|
|
48
48
|
return;
|
|
@@ -50,14 +50,14 @@ var trackApplePayExperimentExposure = (variant, experimentKey) => {
|
|
|
50
50
|
const exposures = window.__applePayExperimentExposures ?? {};
|
|
51
51
|
window.__applePayExperimentExposures = exposures;
|
|
52
52
|
const pathname = window.location?.pathname ?? "";
|
|
53
|
-
const dedupeKey = `${pathname}:${
|
|
53
|
+
const dedupeKey = `${pathname}:${flagKey}:${variant}`;
|
|
54
54
|
if (exposures[dedupeKey]) {
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
57
|
exposures[dedupeKey] = true;
|
|
58
58
|
emitTedlEvent({
|
|
59
59
|
name: "$exposure",
|
|
60
|
-
flag_key:
|
|
60
|
+
flag_key: flagKey,
|
|
61
61
|
variant,
|
|
62
62
|
...experimentKey ? { experiment_key: experimentKey } : {}
|
|
63
63
|
});
|