@economist/web-apple-pay 1.9.4 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1304,13 +1304,14 @@ var redirectToCheckoutFallback = (params) => {
1304
1304
  };
1305
1305
 
1306
1306
  // src/constants.ts
1307
- var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint3) => {
1308
- ApplePayEntryPoint3["PAYWALL"] = "article_paywall";
1309
- ApplePayEntryPoint3["REGWALL"] = "article_regwall";
1310
- ApplePayEntryPoint3["DUAL_OFFER_BANNER"] = "dual_offer_banner";
1311
- return ApplePayEntryPoint3;
1307
+ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
1308
+ ApplePayEntryPoint2["PAYWALL"] = "article_paywall";
1309
+ ApplePayEntryPoint2["REGWALL"] = "article_regwall";
1310
+ ApplePayEntryPoint2["DUAL_OFFER_BANNER"] = "dual_offer_banner";
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}:${APPLE_PAY_EXPRESS_EXPERIMENT_KEY}:${variant}`;
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: APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
1372
+ flag_key: flagKey,
1372
1373
  variant,
1373
1374
  ...experimentKey ? { experiment_key: experimentKey } : {}
1374
1375
  });
@@ -2003,7 +2004,26 @@ var getExperimentKeyFromNextData = (flagKey) => {
2003
2004
  return typeof experimentKey === "string" ? experimentKey : void 0;
2004
2005
  };
2005
2006
 
2007
+ // src/utils/applePayExpressEligibility.ts
2008
+ var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
2009
+ var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
2010
+ var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
2011
+
2006
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
+ };
2007
2027
  var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
2008
2028
  var TOTAL_LABEL = "The Economist";
2009
2029
  var DEFAULT_CURRENCY = "USD";
@@ -2022,9 +2042,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2022
2042
  /**
2023
2043
  * Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
2024
2044
  *
2025
- * Reads the experiment variant from `window.experimentIntegration.getVariant` using
2026
- * {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY}. The host page is responsible
2027
- * for setting up `window.experimentIntegration` before calling this method.
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.
2028
2051
  *
2029
2052
  * - `treatment` → button created and returned
2030
2053
  * - `control` / missing / anything else → returns null (button suppressed)
@@ -2034,6 +2057,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2034
2057
  * `window.experimentIntegration`. Once all consumers are migrated, the URL param
2035
2058
  * fallback will be removed.
2036
2059
  *
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)
2064
+ *
2037
2065
  * @param offer - The offer to display in the Apple Pay flow.
2038
2066
  * @param country - The user's country code.
2039
2067
  * @param entryPoint - Where the button is being rendered (e.g. paywall, banner).
@@ -2045,19 +2073,35 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2045
2073
  if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
2046
2074
  return null;
2047
2075
  }
2076
+ const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
2077
+ FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
2078
+ );
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) {
2087
+ return null;
2088
+ }
2048
2089
  const experimentValue = window.experimentIntegration?.getVariant?.(
2049
- APPLE_PAY_EXPRESS_EXPERIMENT_KEY
2090
+ experimentFlagKey
2050
2091
  );
2051
- if (experimentValue) {
2052
- trackApplePayExperimentExposure(
2053
- experimentValue,
2054
- getExperimentKeyFromNextData(APPLE_PAY_EXPRESS_EXPERIMENT_KEY)
2055
- );
2092
+ const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2093
+ if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2094
+ void isApplePayAvailable().then((available) => {
2095
+ if (available) {
2096
+ trackApplePayExperimentExposure(
2097
+ experimentValue,
2098
+ getExperimentKeyFromNextData(experimentFlagKey),
2099
+ experimentFlagKey
2100
+ );
2101
+ }
2102
+ });
2056
2103
  }
2057
2104
  const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2058
- const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
2059
- FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
2060
- );
2061
2105
  if (!isTreatment && !hasUrlParamFlag) {
2062
2106
  return null;
2063
2107
  }
@@ -2373,6 +2417,9 @@ function defineApplePayElements() {
2373
2417
  }
2374
2418
  export {
2375
2419
  APPLE_PAY_EXCLUDED_VARIANTS,
2420
+ APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
2421
+ APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY,
2422
+ APPLE_PAY_EXPRESS_VARIANTS,
2376
2423
  ApplePayButton,
2377
2424
  ApplePayEntryPoint,
2378
2425
  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` using
12
- * {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY}. The host page is responsible
13
- * for setting up `window.experimentIntegration` before calling this method.
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,6 +23,11 @@ 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
  *
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)
30
+ *
23
31
  * @param offer - The offer to display in the Apple Pay flow.
24
32
  * @param country - The user's country code.
25
33
  * @param entryPoint - Where the button is being rendered (e.g. paywall, banner).
@@ -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}:${APPLE_PAY_EXPRESS_EXPERIMENT_KEY}:${variant}`;
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: APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
1361
+ flag_key: flagKey,
1361
1362
  variant,
1362
1363
  ...experimentKey ? { experiment_key: experimentKey } : {}
1363
1364
  });
@@ -1992,7 +1993,26 @@ var getExperimentKeyFromNextData = (flagKey) => {
1992
1993
  return typeof experimentKey === "string" ? experimentKey : void 0;
1993
1994
  };
1994
1995
 
1996
+ // src/utils/applePayExpressEligibility.ts
1997
+ var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
1998
+ var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
1999
+ var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
2000
+
1995
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
+ };
1996
2016
  var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
1997
2017
  var TOTAL_LABEL = "The Economist";
1998
2018
  var DEFAULT_CURRENCY = "USD";
@@ -2011,9 +2031,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2011
2031
  /**
2012
2032
  * Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
2013
2033
  *
2014
- * Reads the experiment variant from `window.experimentIntegration.getVariant` using
2015
- * {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY}. The host page is responsible
2016
- * for setting up `window.experimentIntegration` before calling this method.
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.
2017
2040
  *
2018
2041
  * - `treatment` → button created and returned
2019
2042
  * - `control` / missing / anything else → returns null (button suppressed)
@@ -2023,6 +2046,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2023
2046
  * `window.experimentIntegration`. Once all consumers are migrated, the URL param
2024
2047
  * fallback will be removed.
2025
2048
  *
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)
2053
+ *
2026
2054
  * @param offer - The offer to display in the Apple Pay flow.
2027
2055
  * @param country - The user's country code.
2028
2056
  * @param entryPoint - Where the button is being rendered (e.g. paywall, banner).
@@ -2034,19 +2062,35 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2034
2062
  if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
2035
2063
  return null;
2036
2064
  }
2065
+ const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
2066
+ FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
2067
+ );
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) {
2076
+ return null;
2077
+ }
2037
2078
  const experimentValue = window.experimentIntegration?.getVariant?.(
2038
- APPLE_PAY_EXPRESS_EXPERIMENT_KEY
2079
+ experimentFlagKey
2039
2080
  );
2040
- if (experimentValue) {
2041
- trackApplePayExperimentExposure(
2042
- experimentValue,
2043
- getExperimentKeyFromNextData(APPLE_PAY_EXPRESS_EXPERIMENT_KEY)
2044
- );
2081
+ const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2082
+ if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2083
+ void isApplePayAvailable().then((available) => {
2084
+ if (available) {
2085
+ trackApplePayExperimentExposure(
2086
+ experimentValue,
2087
+ getExperimentKeyFromNextData(experimentFlagKey),
2088
+ experimentFlagKey
2089
+ );
2090
+ }
2091
+ });
2045
2092
  }
2046
2093
  const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2047
- const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
2048
- FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
2049
- );
2050
2094
  if (!isTreatment && !hasUrlParamFlag) {
2051
2095
  return null;
2052
2096
  }
@@ -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}:${APPLE_PAY_EXPRESS_EXPERIMENT_KEY}:${variant}`;
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: APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
1369
+ flag_key: flagKey,
1369
1370
  variant,
1370
1371
  ...experimentKey ? { experiment_key: experimentKey } : {}
1371
1372
  });
@@ -2000,7 +2001,26 @@ var getExperimentKeyFromNextData = (flagKey) => {
2000
2001
  return typeof experimentKey === "string" ? experimentKey : void 0;
2001
2002
  };
2002
2003
 
2004
+ // src/utils/applePayExpressEligibility.ts
2005
+ var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
2006
+ var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
2007
+ var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
2008
+
2003
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
+ };
2004
2024
  var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
2005
2025
  var TOTAL_LABEL = "The Economist";
2006
2026
  var DEFAULT_CURRENCY = "USD";
@@ -2019,9 +2039,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2019
2039
  /**
2020
2040
  * Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
2021
2041
  *
2022
- * Reads the experiment variant from `window.experimentIntegration.getVariant` using
2023
- * {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY}. The host page is responsible
2024
- * for setting up `window.experimentIntegration` before calling this method.
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.
2025
2048
  *
2026
2049
  * - `treatment` → button created and returned
2027
2050
  * - `control` / missing / anything else → returns null (button suppressed)
@@ -2031,6 +2054,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2031
2054
  * `window.experimentIntegration`. Once all consumers are migrated, the URL param
2032
2055
  * fallback will be removed.
2033
2056
  *
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)
2061
+ *
2034
2062
  * @param offer - The offer to display in the Apple Pay flow.
2035
2063
  * @param country - The user's country code.
2036
2064
  * @param entryPoint - Where the button is being rendered (e.g. paywall, banner).
@@ -2042,19 +2070,35 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2042
2070
  if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
2043
2071
  return null;
2044
2072
  }
2073
+ const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
2074
+ FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
2075
+ );
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) {
2084
+ return null;
2085
+ }
2045
2086
  const experimentValue = window.experimentIntegration?.getVariant?.(
2046
- APPLE_PAY_EXPRESS_EXPERIMENT_KEY
2087
+ experimentFlagKey
2047
2088
  );
2048
- if (experimentValue) {
2049
- trackApplePayExperimentExposure(
2050
- experimentValue,
2051
- getExperimentKeyFromNextData(APPLE_PAY_EXPRESS_EXPERIMENT_KEY)
2052
- );
2089
+ const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2090
+ if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2091
+ void isApplePayAvailable().then((available) => {
2092
+ if (available) {
2093
+ trackApplePayExperimentExposure(
2094
+ experimentValue,
2095
+ getExperimentKeyFromNextData(experimentFlagKey),
2096
+ experimentFlagKey
2097
+ );
2098
+ }
2099
+ });
2053
2100
  }
2054
2101
  const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2055
- const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
2056
- FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
2057
- );
2058
2102
  if (!isTreatment && !hasUrlParamFlag) {
2059
2103
  return null;
2060
2104
  }
@@ -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}:${APPLE_PAY_EXPRESS_EXPERIMENT_KEY}:${variant}`;
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: APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
1361
+ flag_key: flagKey,
1361
1362
  variant,
1362
1363
  ...experimentKey ? { experiment_key: experimentKey } : {}
1363
1364
  });
@@ -1992,7 +1993,26 @@ var getExperimentKeyFromNextData = (flagKey) => {
1992
1993
  return typeof experimentKey === "string" ? experimentKey : void 0;
1993
1994
  };
1994
1995
 
1996
+ // src/utils/applePayExpressEligibility.ts
1997
+ var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
1998
+ var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
1999
+ var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
2000
+
1995
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
+ };
1996
2016
  var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
1997
2017
  var TOTAL_LABEL = "The Economist";
1998
2018
  var DEFAULT_CURRENCY = "USD";
@@ -2011,9 +2031,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2011
2031
  /**
2012
2032
  * Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
2013
2033
  *
2014
- * Reads the experiment variant from `window.experimentIntegration.getVariant` using
2015
- * {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY}. The host page is responsible
2016
- * for setting up `window.experimentIntegration` before calling this method.
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.
2017
2040
  *
2018
2041
  * - `treatment` → button created and returned
2019
2042
  * - `control` / missing / anything else → returns null (button suppressed)
@@ -2023,6 +2046,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2023
2046
  * `window.experimentIntegration`. Once all consumers are migrated, the URL param
2024
2047
  * fallback will be removed.
2025
2048
  *
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)
2053
+ *
2026
2054
  * @param offer - The offer to display in the Apple Pay flow.
2027
2055
  * @param country - The user's country code.
2028
2056
  * @param entryPoint - Where the button is being rendered (e.g. paywall, banner).
@@ -2034,19 +2062,35 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2034
2062
  if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
2035
2063
  return null;
2036
2064
  }
2065
+ const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
2066
+ FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
2067
+ );
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) {
2076
+ return null;
2077
+ }
2037
2078
  const experimentValue = window.experimentIntegration?.getVariant?.(
2038
- APPLE_PAY_EXPRESS_EXPERIMENT_KEY
2079
+ experimentFlagKey
2039
2080
  );
2040
- if (experimentValue) {
2041
- trackApplePayExperimentExposure(
2042
- experimentValue,
2043
- getExperimentKeyFromNextData(APPLE_PAY_EXPRESS_EXPERIMENT_KEY)
2044
- );
2081
+ const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2082
+ if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2083
+ void isApplePayAvailable().then((available) => {
2084
+ if (available) {
2085
+ trackApplePayExperimentExposure(
2086
+ experimentValue,
2087
+ getExperimentKeyFromNextData(experimentFlagKey),
2088
+ experimentFlagKey
2089
+ );
2090
+ }
2091
+ });
2045
2092
  }
2046
2093
  const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2047
- const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
2048
- FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
2049
- );
2050
2094
  if (!isTreatment && !hasUrlParamFlag) {
2051
2095
  return null;
2052
2096
  }
@@ -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. Gates all entry points (paywall, regwall, banner).
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)
@@ -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
  };
@@ -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
@@ -1304,13 +1304,14 @@ var redirectToCheckoutFallback = (params) => {
1304
1304
  };
1305
1305
 
1306
1306
  // src/constants.ts
1307
- var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint3) => {
1308
- ApplePayEntryPoint3["PAYWALL"] = "article_paywall";
1309
- ApplePayEntryPoint3["REGWALL"] = "article_regwall";
1310
- ApplePayEntryPoint3["DUAL_OFFER_BANNER"] = "dual_offer_banner";
1311
- return ApplePayEntryPoint3;
1307
+ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
1308
+ ApplePayEntryPoint2["PAYWALL"] = "article_paywall";
1309
+ ApplePayEntryPoint2["REGWALL"] = "article_regwall";
1310
+ ApplePayEntryPoint2["DUAL_OFFER_BANNER"] = "dual_offer_banner";
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}:${APPLE_PAY_EXPRESS_EXPERIMENT_KEY}:${variant}`;
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: APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
1372
+ flag_key: flagKey,
1372
1373
  variant,
1373
1374
  ...experimentKey ? { experiment_key: experimentKey } : {}
1374
1375
  });
@@ -2003,7 +2004,26 @@ var getExperimentKeyFromNextData = (flagKey) => {
2003
2004
  return typeof experimentKey === "string" ? experimentKey : void 0;
2004
2005
  };
2005
2006
 
2007
+ // src/utils/applePayExpressEligibility.ts
2008
+ var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
2009
+ var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
2010
+ var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
2011
+
2006
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
+ };
2007
2027
  var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
2008
2028
  var TOTAL_LABEL = "The Economist";
2009
2029
  var DEFAULT_CURRENCY = "USD";
@@ -2022,9 +2042,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2022
2042
  /**
2023
2043
  * Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
2024
2044
  *
2025
- * Reads the experiment variant from `window.experimentIntegration.getVariant` using
2026
- * {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY}. The host page is responsible
2027
- * for setting up `window.experimentIntegration` before calling this method.
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.
2028
2051
  *
2029
2052
  * - `treatment` → button created and returned
2030
2053
  * - `control` / missing / anything else → returns null (button suppressed)
@@ -2034,6 +2057,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2034
2057
  * `window.experimentIntegration`. Once all consumers are migrated, the URL param
2035
2058
  * fallback will be removed.
2036
2059
  *
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)
2064
+ *
2037
2065
  * @param offer - The offer to display in the Apple Pay flow.
2038
2066
  * @param country - The user's country code.
2039
2067
  * @param entryPoint - Where the button is being rendered (e.g. paywall, banner).
@@ -2045,19 +2073,35 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2045
2073
  if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
2046
2074
  return null;
2047
2075
  }
2076
+ const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
2077
+ FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
2078
+ );
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) {
2087
+ return null;
2088
+ }
2048
2089
  const experimentValue = window.experimentIntegration?.getVariant?.(
2049
- APPLE_PAY_EXPRESS_EXPERIMENT_KEY
2090
+ experimentFlagKey
2050
2091
  );
2051
- if (experimentValue) {
2052
- trackApplePayExperimentExposure(
2053
- experimentValue,
2054
- getExperimentKeyFromNextData(APPLE_PAY_EXPRESS_EXPERIMENT_KEY)
2055
- );
2092
+ const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2093
+ if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2094
+ void isApplePayAvailable().then((available) => {
2095
+ if (available) {
2096
+ trackApplePayExperimentExposure(
2097
+ experimentValue,
2098
+ getExperimentKeyFromNextData(experimentFlagKey),
2099
+ experimentFlagKey
2100
+ );
2101
+ }
2102
+ });
2056
2103
  }
2057
2104
  const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2058
- const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
2059
- FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
2060
- );
2061
2105
  if (!isTreatment && !hasUrlParamFlag) {
2062
2106
  return null;
2063
2107
  }
@@ -2373,6 +2417,9 @@ function defineApplePayElements() {
2373
2417
  }
2374
2418
  export {
2375
2419
  APPLE_PAY_EXCLUDED_VARIANTS,
2420
+ APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
2421
+ APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY,
2422
+ APPLE_PAY_EXPRESS_VARIANTS,
2376
2423
  ApplePayButton,
2377
2424
  ApplePayEntryPoint,
2378
2425
  ApplePayModal,
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Host-side eligibility for Apple Pay Express Feature Experiment (SMA-3301).
3
+ *
4
+ * Gates createIfEnabled before getVariant / $exposure so only the intended
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.
8
+ */
9
+ export declare const isApplePayExpressHomepage: (pathname?: string) => boolean;
10
+ /**
11
+ * Dual-offer homepage banner: homepage + Safari/iPhone.
12
+ * Anonymous is assumed because the dual-offer banner is only mounted for
13
+ * anonymous visitors.
14
+ */
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;
@@ -0,0 +1,16 @@
1
+ // src/clients/payment-checkout/detects.ts
2
+ var isAppleDeviceOrSafari = () => {
3
+ const isIOSOrMacTouchDevice = /iPad|iPhone|iPod/.test(navigator.userAgent) || navigator.maxTouchPoints > 1 && /Macintosh/.test(navigator.userAgent);
4
+ const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
5
+ return isIOSOrMacTouchDevice || isSafariBrowser;
6
+ };
7
+
8
+ // src/utils/applePayExpressEligibility.ts
9
+ var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
10
+ var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
11
+ var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
12
+ export {
13
+ isApplePayExpressHomepage,
14
+ isEligibleForApplePayExpressExperiment,
15
+ isEligibleForApplePayExpressPaywallExperiment
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?: {
@@ -50,12 +51,16 @@ export type ImpressionMetadata = {
50
51
  /**
51
52
  * Amplitude Experiment exposure for Apple Pay Express (SMA-3301).
52
53
  *
53
- * Fired when createIfEnabled evaluates an assigned variant (control or
54
- * treatment). Deduped per pathname + variant so repeated banner renders on
55
- * the same page do not over-count. Includes experiment_key from Engagement
56
- * SSR (__NEXT_DATA__) when present for Feature Experiment run attribution.
54
+ * Fired from createIfEnabled only after isApplePayAvailable() succeeds
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}:${APPLE_PAY_EXPRESS_EXPERIMENT_KEY}:${variant}`;
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: APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
60
+ flag_key: flagKey,
61
61
  variant,
62
62
  ...experimentKey ? { experiment_key: experimentKey } : {}
63
63
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@economist/web-apple-pay",
3
3
  "description": "Web component package for Apple Pay checkout UI",
4
- "version": "1.9.4",
4
+ "version": "1.10.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",