@economist/web-apple-pay 1.10.1 → 1.10.2-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -54,6 +54,56 @@ container.appendChild(button);
54
54
 
55
55
  When clicked, the button creates and opens `teg-apple-pay-modal` automatically.
56
56
 
57
+ ### 3) Gated creation — `createIfEnabled`
58
+
59
+ Hosts that mount Apple Pay on a wall, banner, or popup should use
60
+ `ApplePayButton.createIfEnabled(offer, country, entryPoint)` instead of
61
+ `document.createElement`. It applies Amplitude experiment and placement rules
62
+ per entry point, then returns a configured button or `null`.
63
+
64
+ ```ts
65
+ import {
66
+ ApplePayButton,
67
+ ApplePayEntryPoint,
68
+ } from '@economist/web-apple-pay';
69
+
70
+ const button = ApplePayButton.createIfEnabled(
71
+ offer,
72
+ 'US',
73
+ ApplePayEntryPoint.FREE_TRIAL_POPUP,
74
+ );
75
+
76
+ if (button) {
77
+ container.appendChild(button);
78
+ await button.whenReady();
79
+ if (button.style.display === 'none') {
80
+ button.remove();
81
+ }
82
+ }
83
+ ```
84
+
85
+ #### Entry points
86
+
87
+ | `ApplePayEntryPoint` | Value | Amplitude flag | Placement eligibility |
88
+ | --- | --- | --- | --- |
89
+ | `PAYWALL` | `article_paywall` | `apple-pay-express-checkout-on-paywalls` | Safari / Apple device |
90
+ | `REGWALL` | `article_regwall` | `apple-pay-express-checkout-on-banners` | none |
91
+ | `DUAL_OFFER_BANNER` (default if omitted) | `dual_offer_banner` | `apple-pay-express-checkout-on-banners` | homepage + Safari / iPhone |
92
+ | `FREE_TRIAL_POPUP` | `free_trial_popup` | **none** — always shown | none |
93
+
94
+ `FREE_TRIAL_POPUP` does not read `window.experimentIntegration` and does not
95
+ emit `$exposure`. The button is created whenever the offer is valid (excluded
96
+ variants still suppress it). The component still hides itself after mount if
97
+ Apple Pay is unavailable on the device.
98
+
99
+ For every other entry point:
100
+
101
+ - Host must set `window.experimentIntegration.getVariant` before calling
102
+ `createIfEnabled`.
103
+ - `treatment` → button created; `control` / missing / anything else → `null`.
104
+ - QA override: `?FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` shows the button without
105
+ emitting `$exposure`.
106
+
57
107
  ## Runtime configuration
58
108
 
59
109
  ### `configureApplePay(config)`
@@ -120,7 +170,9 @@ Consumers should listen for this event and continue payment orchestration.
120
170
  - `defineApplePayElements()`: registers both custom elements.
121
171
  - `configureApplePay(config)`: sets required runtime config (merchant ID and wallet API base URL, with optional debug bypass).
122
172
  - `ApplePayButton`: button component class.
173
+ - `createIfEnabled(offer, country, entryPoint?)`: returns a configured button or `null` after applying Amplitude / placement rules for the entry point. `FREE_TRIAL_POPUP` is not experiment-gated.
123
174
  - `whenReady(): Promise<void>` — resolves when the current render lifecycle completes (available or hidden). Resolves immediately if called before the element is connected.
175
+ - `ApplePayEntryPoint`: where the button is mounted (`PAYWALL`, `REGWALL`, `DUAL_OFFER_BANNER`, `FREE_TRIAL_POPUP`).
124
176
  - `ApplePayModal`: modal component class.
125
177
  - `ensureApplePayLogoSymbol()`: logo symbol injection helper.
126
178
  - `Offer`: offer contract type used by component props.
@@ -133,7 +185,8 @@ Check:
133
185
 
134
186
  - `configureApplePay(...)` was called before rendering (with a valid `merchantId` and `walletApiBaseUrl`)
135
187
  - device/browser supports Apple Pay (Safari on Apple device required)
136
- - query string/feature flag gating for your page is satisfied
188
+ - for paywall / regwall / dual-offer banner: Amplitude variant is `treatment`, or the `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` QA param is present
189
+ - `FREE_TRIAL_POPUP` is not Amplitude-gated — if the button is missing, check offer variant and device support instead
137
190
  - offer variant is not excluded (`bundle`, `insider_print`)
138
191
 
139
192
  ### Logged-in checkbox copy looks wrong
@@ -184,3 +237,4 @@ Story coverage matrix:
184
237
  - `ApplePayButton` behavior and state variants are available as individual canvas stories in Storybook.
185
238
  - `ApplePayModal` docs page shows the stable default example.
186
239
  - `ApplePayModal` behavior and state variants are available as individual canvas stories in Storybook.
240
+
package/dist/index.js CHANGED
@@ -1308,6 +1308,7 @@ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
1308
1308
  ApplePayEntryPoint2["PAYWALL"] = "article_paywall";
1309
1309
  ApplePayEntryPoint2["REGWALL"] = "article_regwall";
1310
1310
  ApplePayEntryPoint2["DUAL_OFFER_BANNER"] = "dual_offer_banner";
1311
+ ApplePayEntryPoint2["FREE_TRIAL_POPUP"] = "free_trial_popup";
1311
1312
  return ApplePayEntryPoint2;
1312
1313
  })(ApplePayEntryPoint || {});
1313
1314
  var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
@@ -2022,6 +2023,9 @@ var ENTRY_POINT_CONFIG = {
2022
2023
  ["article_regwall" /* REGWALL */]: {
2023
2024
  isEligible: () => true,
2024
2025
  experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
2026
+ },
2027
+ ["free_trial_popup" /* FREE_TRIAL_POPUP */]: {
2028
+ isEligible: () => true
2025
2029
  }
2026
2030
  };
2027
2031
  var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
@@ -2045,9 +2049,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2045
2049
  * Reads the experiment variant from `window.experimentIntegration.getVariant`:
2046
2050
  * - {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY} for `PAYWALL`
2047
2051
  * - {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY} for `REGWALL` / `DUAL_OFFER_BANNER`
2052
+ * - no Amplitude gate for `FREE_TRIAL_POPUP` (always shown)
2048
2053
  *
2049
2054
  * The host page is responsible for setting up `window.experimentIntegration`
2050
- * before calling this method.
2055
+ * before calling this method (except `FREE_TRIAL_POPUP`).
2051
2056
  *
2052
2057
  * - `treatment` → button created and returned
2053
2058
  * - `control` / missing / anything else → returns null (button suppressed)
@@ -2060,7 +2065,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2060
2065
  * **Eligibility:**
2061
2066
  * - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone (SMA-3301)
2062
2067
  * - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
2063
- * - `REGWALL`: no host-side placement gate (pre-SMA-3301 article behaviour)
2068
+ * - `REGWALL` / `FREE_TRIAL_POPUP`: no host-side placement gate
2064
2069
  *
2065
2070
  * @param offer - The offer to display in the Apple Pay flow.
2066
2071
  * @param country - The user's country code.
@@ -2086,24 +2091,24 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2086
2091
  if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
2087
2092
  return null;
2088
2093
  }
2089
- const experimentValue = window.experimentIntegration?.getVariant?.(
2090
- experimentFlagKey
2091
- );
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
- });
2103
- }
2104
- const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2105
- if (!isTreatment && !hasUrlParamFlag) {
2106
- return null;
2094
+ if (experimentFlagKey) {
2095
+ const experimentValue = window.experimentIntegration?.getVariant?.(experimentFlagKey);
2096
+ const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2097
+ if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2098
+ void isApplePayAvailable().then((available) => {
2099
+ if (available) {
2100
+ trackApplePayExperimentExposure(
2101
+ experimentValue,
2102
+ getExperimentKeyFromNextData(experimentFlagKey),
2103
+ experimentFlagKey
2104
+ );
2105
+ }
2106
+ });
2107
+ }
2108
+ const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2109
+ if (!isTreatment && !hasUrlParamFlag) {
2110
+ return null;
2111
+ }
2107
2112
  }
2108
2113
  _ApplePayButton.define();
2109
2114
  const button = document.createElement(_ApplePayButton.tag);
@@ -2227,7 +2232,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2227
2232
  button.removeAttribute("aria-busy");
2228
2233
  button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
2229
2234
  }
2230
- this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
2235
+ this.getAnimations?.({ subtree: true }).forEach(
2236
+ (animation) => animation.cancel()
2237
+ );
2231
2238
  void this.offsetHeight;
2232
2239
  this.style.display = "none";
2233
2240
  this.querySelector(SEL_CONTAINER)?.remove();
@@ -11,9 +11,10 @@ export declare class ApplePayButton extends HTMLElement {
11
11
  * Reads the experiment variant from `window.experimentIntegration.getVariant`:
12
12
  * - {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY} for `PAYWALL`
13
13
  * - {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY} for `REGWALL` / `DUAL_OFFER_BANNER`
14
+ * - no Amplitude gate for `FREE_TRIAL_POPUP` (always shown)
14
15
  *
15
16
  * The host page is responsible for setting up `window.experimentIntegration`
16
- * before calling this method.
17
+ * before calling this method (except `FREE_TRIAL_POPUP`).
17
18
  *
18
19
  * - `treatment` → button created and returned
19
20
  * - `control` / missing / anything else → returns null (button suppressed)
@@ -26,7 +27,7 @@ export declare class ApplePayButton extends HTMLElement {
26
27
  * **Eligibility:**
27
28
  * - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone (SMA-3301)
28
29
  * - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
29
- * - `REGWALL`: no host-side placement gate (pre-SMA-3301 article behaviour)
30
+ * - `REGWALL` / `FREE_TRIAL_POPUP`: no host-side placement gate
30
31
  *
31
32
  * @param offer - The offer to display in the Apple Pay flow.
32
33
  * @param country - The user's country code.
@@ -2011,6 +2011,9 @@ var ENTRY_POINT_CONFIG = {
2011
2011
  ["article_regwall" /* REGWALL */]: {
2012
2012
  isEligible: () => true,
2013
2013
  experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
2014
+ },
2015
+ ["free_trial_popup" /* FREE_TRIAL_POPUP */]: {
2016
+ isEligible: () => true
2014
2017
  }
2015
2018
  };
2016
2019
  var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
@@ -2034,9 +2037,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2034
2037
  * Reads the experiment variant from `window.experimentIntegration.getVariant`:
2035
2038
  * - {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY} for `PAYWALL`
2036
2039
  * - {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY} for `REGWALL` / `DUAL_OFFER_BANNER`
2040
+ * - no Amplitude gate for `FREE_TRIAL_POPUP` (always shown)
2037
2041
  *
2038
2042
  * The host page is responsible for setting up `window.experimentIntegration`
2039
- * before calling this method.
2043
+ * before calling this method (except `FREE_TRIAL_POPUP`).
2040
2044
  *
2041
2045
  * - `treatment` → button created and returned
2042
2046
  * - `control` / missing / anything else → returns null (button suppressed)
@@ -2049,7 +2053,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2049
2053
  * **Eligibility:**
2050
2054
  * - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone (SMA-3301)
2051
2055
  * - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
2052
- * - `REGWALL`: no host-side placement gate (pre-SMA-3301 article behaviour)
2056
+ * - `REGWALL` / `FREE_TRIAL_POPUP`: no host-side placement gate
2053
2057
  *
2054
2058
  * @param offer - The offer to display in the Apple Pay flow.
2055
2059
  * @param country - The user's country code.
@@ -2075,24 +2079,24 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2075
2079
  if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
2076
2080
  return null;
2077
2081
  }
2078
- const experimentValue = window.experimentIntegration?.getVariant?.(
2079
- experimentFlagKey
2080
- );
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
- });
2092
- }
2093
- const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2094
- if (!isTreatment && !hasUrlParamFlag) {
2095
- return null;
2082
+ if (experimentFlagKey) {
2083
+ const experimentValue = window.experimentIntegration?.getVariant?.(experimentFlagKey);
2084
+ const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2085
+ if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2086
+ void isApplePayAvailable().then((available) => {
2087
+ if (available) {
2088
+ trackApplePayExperimentExposure(
2089
+ experimentValue,
2090
+ getExperimentKeyFromNextData(experimentFlagKey),
2091
+ experimentFlagKey
2092
+ );
2093
+ }
2094
+ });
2095
+ }
2096
+ const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2097
+ if (!isTreatment && !hasUrlParamFlag) {
2098
+ return null;
2099
+ }
2096
2100
  }
2097
2101
  _ApplePayButton.define();
2098
2102
  const button = document.createElement(_ApplePayButton.tag);
@@ -2216,7 +2220,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2216
2220
  button.removeAttribute("aria-busy");
2217
2221
  button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
2218
2222
  }
2219
- this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
2223
+ this.getAnimations?.({ subtree: true }).forEach(
2224
+ (animation) => animation.cancel()
2225
+ );
2220
2226
  void this.offsetHeight;
2221
2227
  this.style.display = "none";
2222
2228
  this.querySelector(SEL_CONTAINER)?.remove();
@@ -2019,6 +2019,9 @@ var ENTRY_POINT_CONFIG = {
2019
2019
  ["article_regwall" /* REGWALL */]: {
2020
2020
  isEligible: () => true,
2021
2021
  experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
2022
+ },
2023
+ ["free_trial_popup" /* FREE_TRIAL_POPUP */]: {
2024
+ isEligible: () => true
2022
2025
  }
2023
2026
  };
2024
2027
  var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
@@ -2042,9 +2045,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2042
2045
  * Reads the experiment variant from `window.experimentIntegration.getVariant`:
2043
2046
  * - {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY} for `PAYWALL`
2044
2047
  * - {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY} for `REGWALL` / `DUAL_OFFER_BANNER`
2048
+ * - no Amplitude gate for `FREE_TRIAL_POPUP` (always shown)
2045
2049
  *
2046
2050
  * The host page is responsible for setting up `window.experimentIntegration`
2047
- * before calling this method.
2051
+ * before calling this method (except `FREE_TRIAL_POPUP`).
2048
2052
  *
2049
2053
  * - `treatment` → button created and returned
2050
2054
  * - `control` / missing / anything else → returns null (button suppressed)
@@ -2057,7 +2061,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2057
2061
  * **Eligibility:**
2058
2062
  * - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone (SMA-3301)
2059
2063
  * - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
2060
- * - `REGWALL`: no host-side placement gate (pre-SMA-3301 article behaviour)
2064
+ * - `REGWALL` / `FREE_TRIAL_POPUP`: no host-side placement gate
2061
2065
  *
2062
2066
  * @param offer - The offer to display in the Apple Pay flow.
2063
2067
  * @param country - The user's country code.
@@ -2083,24 +2087,24 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2083
2087
  if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
2084
2088
  return null;
2085
2089
  }
2086
- const experimentValue = window.experimentIntegration?.getVariant?.(
2087
- experimentFlagKey
2088
- );
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
- });
2100
- }
2101
- const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2102
- if (!isTreatment && !hasUrlParamFlag) {
2103
- return null;
2090
+ if (experimentFlagKey) {
2091
+ const experimentValue = window.experimentIntegration?.getVariant?.(experimentFlagKey);
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
+ });
2103
+ }
2104
+ const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2105
+ if (!isTreatment && !hasUrlParamFlag) {
2106
+ return null;
2107
+ }
2104
2108
  }
2105
2109
  _ApplePayButton.define();
2106
2110
  const button = document.createElement(_ApplePayButton.tag);
@@ -2224,7 +2228,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2224
2228
  button.removeAttribute("aria-busy");
2225
2229
  button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
2226
2230
  }
2227
- this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
2231
+ this.getAnimations?.({ subtree: true }).forEach(
2232
+ (animation) => animation.cancel()
2233
+ );
2228
2234
  void this.offsetHeight;
2229
2235
  this.style.display = "none";
2230
2236
  this.querySelector(SEL_CONTAINER)?.remove();
@@ -2011,6 +2011,9 @@ var ENTRY_POINT_CONFIG = {
2011
2011
  ["article_regwall" /* REGWALL */]: {
2012
2012
  isEligible: () => true,
2013
2013
  experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
2014
+ },
2015
+ ["free_trial_popup" /* FREE_TRIAL_POPUP */]: {
2016
+ isEligible: () => true
2014
2017
  }
2015
2018
  };
2016
2019
  var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
@@ -2034,9 +2037,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2034
2037
  * Reads the experiment variant from `window.experimentIntegration.getVariant`:
2035
2038
  * - {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY} for `PAYWALL`
2036
2039
  * - {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY} for `REGWALL` / `DUAL_OFFER_BANNER`
2040
+ * - no Amplitude gate for `FREE_TRIAL_POPUP` (always shown)
2037
2041
  *
2038
2042
  * The host page is responsible for setting up `window.experimentIntegration`
2039
- * before calling this method.
2043
+ * before calling this method (except `FREE_TRIAL_POPUP`).
2040
2044
  *
2041
2045
  * - `treatment` → button created and returned
2042
2046
  * - `control` / missing / anything else → returns null (button suppressed)
@@ -2049,7 +2053,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2049
2053
  * **Eligibility:**
2050
2054
  * - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone (SMA-3301)
2051
2055
  * - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
2052
- * - `REGWALL`: no host-side placement gate (pre-SMA-3301 article behaviour)
2056
+ * - `REGWALL` / `FREE_TRIAL_POPUP`: no host-side placement gate
2053
2057
  *
2054
2058
  * @param offer - The offer to display in the Apple Pay flow.
2055
2059
  * @param country - The user's country code.
@@ -2075,24 +2079,24 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2075
2079
  if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
2076
2080
  return null;
2077
2081
  }
2078
- const experimentValue = window.experimentIntegration?.getVariant?.(
2079
- experimentFlagKey
2080
- );
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
- });
2092
- }
2093
- const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2094
- if (!isTreatment && !hasUrlParamFlag) {
2095
- return null;
2082
+ if (experimentFlagKey) {
2083
+ const experimentValue = window.experimentIntegration?.getVariant?.(experimentFlagKey);
2084
+ const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2085
+ if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2086
+ void isApplePayAvailable().then((available) => {
2087
+ if (available) {
2088
+ trackApplePayExperimentExposure(
2089
+ experimentValue,
2090
+ getExperimentKeyFromNextData(experimentFlagKey),
2091
+ experimentFlagKey
2092
+ );
2093
+ }
2094
+ });
2095
+ }
2096
+ const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2097
+ if (!isTreatment && !hasUrlParamFlag) {
2098
+ return null;
2099
+ }
2096
2100
  }
2097
2101
  _ApplePayButton.define();
2098
2102
  const button = document.createElement(_ApplePayButton.tag);
@@ -2216,7 +2220,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2216
2220
  button.removeAttribute("aria-busy");
2217
2221
  button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
2218
2222
  }
2219
- this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
2223
+ this.getAnimations?.({ subtree: true }).forEach(
2224
+ (animation) => animation.cancel()
2225
+ );
2220
2226
  void this.offsetHeight;
2221
2227
  this.style.display = "none";
2222
2228
  this.querySelector(SEL_CONTAINER)?.remove();
@@ -1,7 +1,9 @@
1
1
  export declare enum ApplePayEntryPoint {
2
2
  PAYWALL = "article_paywall",
3
3
  REGWALL = "article_regwall",
4
- DUAL_OFFER_BANNER = "dual_offer_banner"
4
+ DUAL_OFFER_BANNER = "dual_offer_banner",
5
+ /** Post-registration free-trial popup. Not Amplitude-gated. */
6
+ FREE_TRIAL_POPUP = "free_trial_popup"
5
7
  }
6
8
  /**
7
9
  * Amplitude experiment key for Apple Pay Express Checkout on homepage banners
@@ -3,6 +3,7 @@ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
3
3
  ApplePayEntryPoint2["PAYWALL"] = "article_paywall";
4
4
  ApplePayEntryPoint2["REGWALL"] = "article_regwall";
5
5
  ApplePayEntryPoint2["DUAL_OFFER_BANNER"] = "dual_offer_banner";
6
+ ApplePayEntryPoint2["FREE_TRIAL_POPUP"] = "free_trial_popup";
6
7
  return ApplePayEntryPoint2;
7
8
  })(ApplePayEntryPoint || {});
8
9
  var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
package/dist/src/index.js CHANGED
@@ -1308,6 +1308,7 @@ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
1308
1308
  ApplePayEntryPoint2["PAYWALL"] = "article_paywall";
1309
1309
  ApplePayEntryPoint2["REGWALL"] = "article_regwall";
1310
1310
  ApplePayEntryPoint2["DUAL_OFFER_BANNER"] = "dual_offer_banner";
1311
+ ApplePayEntryPoint2["FREE_TRIAL_POPUP"] = "free_trial_popup";
1311
1312
  return ApplePayEntryPoint2;
1312
1313
  })(ApplePayEntryPoint || {});
1313
1314
  var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
@@ -2022,6 +2023,9 @@ var ENTRY_POINT_CONFIG = {
2022
2023
  ["article_regwall" /* REGWALL */]: {
2023
2024
  isEligible: () => true,
2024
2025
  experimentFlagKey: APPLE_PAY_EXPRESS_EXPERIMENT_KEY
2026
+ },
2027
+ ["free_trial_popup" /* FREE_TRIAL_POPUP */]: {
2028
+ isEligible: () => true
2025
2029
  }
2026
2030
  };
2027
2031
  var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
@@ -2045,9 +2049,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2045
2049
  * Reads the experiment variant from `window.experimentIntegration.getVariant`:
2046
2050
  * - {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY} for `PAYWALL`
2047
2051
  * - {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY} for `REGWALL` / `DUAL_OFFER_BANNER`
2052
+ * - no Amplitude gate for `FREE_TRIAL_POPUP` (always shown)
2048
2053
  *
2049
2054
  * The host page is responsible for setting up `window.experimentIntegration`
2050
- * before calling this method.
2055
+ * before calling this method (except `FREE_TRIAL_POPUP`).
2051
2056
  *
2052
2057
  * - `treatment` → button created and returned
2053
2058
  * - `control` / missing / anything else → returns null (button suppressed)
@@ -2060,7 +2065,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2060
2065
  * **Eligibility:**
2061
2066
  * - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone (SMA-3301)
2062
2067
  * - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
2063
- * - `REGWALL`: no host-side placement gate (pre-SMA-3301 article behaviour)
2068
+ * - `REGWALL` / `FREE_TRIAL_POPUP`: no host-side placement gate
2064
2069
  *
2065
2070
  * @param offer - The offer to display in the Apple Pay flow.
2066
2071
  * @param country - The user's country code.
@@ -2086,24 +2091,24 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2086
2091
  if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
2087
2092
  return null;
2088
2093
  }
2089
- const experimentValue = window.experimentIntegration?.getVariant?.(
2090
- experimentFlagKey
2091
- );
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
- });
2103
- }
2104
- const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2105
- if (!isTreatment && !hasUrlParamFlag) {
2106
- return null;
2094
+ if (experimentFlagKey) {
2095
+ const experimentValue = window.experimentIntegration?.getVariant?.(experimentFlagKey);
2096
+ const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2097
+ if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2098
+ void isApplePayAvailable().then((available) => {
2099
+ if (available) {
2100
+ trackApplePayExperimentExposure(
2101
+ experimentValue,
2102
+ getExperimentKeyFromNextData(experimentFlagKey),
2103
+ experimentFlagKey
2104
+ );
2105
+ }
2106
+ });
2107
+ }
2108
+ const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2109
+ if (!isTreatment && !hasUrlParamFlag) {
2110
+ return null;
2111
+ }
2107
2112
  }
2108
2113
  _ApplePayButton.define();
2109
2114
  const button = document.createElement(_ApplePayButton.tag);
@@ -2227,7 +2232,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2227
2232
  button.removeAttribute("aria-busy");
2228
2233
  button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
2229
2234
  }
2230
- this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
2235
+ this.getAnimations?.({ subtree: true }).forEach(
2236
+ (animation) => animation.cancel()
2237
+ );
2231
2238
  void this.offsetHeight;
2232
2239
  this.style.display = "none";
2233
2240
  this.querySelector(SEL_CONTAINER)?.remove();
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.10.1",
4
+ "version": "1.10.2-beta.1",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",