@economist/web-apple-pay 0.1.3-beta.47 → 0.1.3-beta.48

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
@@ -605,7 +605,7 @@ var getRecaptchaToken = async (action) => {
605
605
  });
606
606
  });
607
607
  };
608
- var getPurchaseRecaptchaTokens = () => {
608
+ var getPurchaseRecaptchaToken = () => {
609
609
  return getRecaptchaToken("walletPurchase");
610
610
  };
611
611
 
@@ -834,7 +834,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
834
834
  #isClosed = false;
835
835
  /**
836
836
  * Callback invoked synchronously from the CTA click handler.
837
- * Receives a Promise of reCAPTCHA tokens — the promise is already in-flight
837
+ * Receives a Promise of a reCAPTCHA token — the promise is already in-flight
838
838
  * by the time this is called. The caller (ApplePayButton) must call
839
839
  * new ApplePaySession() synchronously inside this callback to stay within
840
840
  * Safari's user-gesture window. The token promise resolves before
@@ -946,12 +946,12 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
946
946
  this.querySelector('[role="alert"]:not(#apple-pay-modal-error)')?.remove();
947
947
  cta.disabled = true;
948
948
  cta.setAttribute("aria-busy", "true");
949
- const recaptchaTokensPromise = getPurchaseRecaptchaTokens();
949
+ const recaptchaTokenPromise = getPurchaseRecaptchaToken();
950
950
  if (!this.#isClosed && this.onConfirm) {
951
- this.onConfirm(recaptchaTokensPromise);
951
+ this.onConfirm(recaptchaTokenPromise);
952
952
  this.close();
953
953
  }
954
- recaptchaTokensPromise.catch(() => {
954
+ recaptchaTokenPromise.catch(() => {
955
955
  if (this.#isClosed) return;
956
956
  cta.disabled = false;
957
957
  cta.removeAttribute("aria-busy");
@@ -1006,7 +1006,10 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
1006
1006
 
1007
1007
  // src/templates/apple-pay-button.template.html
1008
1008
  var apple_pay_button_template_default = `<style>
1009
- /* Use CSS variables for layout so parent walls can easily override placement and sizing */
1009
+ /*
1010
+ * Entry CTA: \u201CSubscribe with\u201D + Apple Pay wordmark (Figma 1118:14088).
1011
+ * \u201CSubscribe with\u201D matches Continue to checkout typography (EconomistSans Regular / 17 / 24 / 400).
1012
+ */
1010
1013
  teg-apple-pay-button {
1011
1014
  display: block;
1012
1015
  margin: var(--apple-pay-margin, 0);
@@ -1026,25 +1029,50 @@ var apple_pay_button_template_default = `<style>
1026
1029
  display: flex;
1027
1030
  align-items: center;
1028
1031
  justify-content: center;
1029
- gap: 0.375rem;
1030
1032
  width: 100%;
1031
1033
  min-width: 0;
1032
1034
  height: 100%;
1033
- min-height: var(--apple-pay-height, 2.75rem);
1034
- background-color: var(--apple-pay-background-color, #000);
1035
+ min-height: var(--apple-pay-height, 2.5rem);
1036
+ padding: 0;
1037
+ box-sizing: border-box;
1038
+ background-color: var(--apple-pay-background-color, #1a1a1a);
1035
1039
  color: var(--apple-pay-foreground-color, #fff);
1036
1040
  border: none;
1037
- border-radius: var(--apple-pay-border-radius, 1.375rem);
1041
+ border-radius: var(--apple-pay-border-radius, 0.25rem);
1038
1042
  cursor: pointer;
1039
- font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
1040
- font-size: 1.0625rem;
1041
- font-weight: 500;
1043
+ /* Same as wall Continue to checkout / Marber button large */
1044
+ font-family: var(
1045
+ --mb-typeface-sans,
1046
+ var(--wall-type-system-sans, 'EconomistSans', system-ui, sans-serif)
1047
+ );
1048
+ font-size: var(--mb-button-font-size, 1.0625rem);
1049
+ font-weight: var(--mb-font-weight-regular, 400);
1050
+ line-height: 1;
1051
+ }
1052
+
1053
+ teg-apple-pay-button .apple-pay-btn__label {
1054
+ display: inline-flex;
1055
+ align-items: center;
1056
+ /* No flex gap \u2014 spacing after \u201Cwith\u201D uses the same word-space as \u201CSubscribe with\u201D */
1057
+ gap: 0;
1058
+ white-space: nowrap;
1042
1059
  }
1043
1060
 
1044
- teg-apple-pay-button .apple-pay-btn svg {
1061
+ teg-apple-pay-button .apple-pay-btn__caption {
1062
+ /* One typographic word space after \u201Cwith\u201D, matching Subscribe\u2194with */
1063
+ padding-right: 0.25em;
1064
+ }
1065
+
1066
+ teg-apple-pay-button .apple-pay-btn__logo {
1045
1067
  flex-shrink: 0;
1046
1068
  display: block;
1069
+ /* Match caption font-size so mark aligns with text metrics */
1070
+ height: 1.05em;
1071
+ width: auto;
1072
+ aspect-ratio: 51 / 22;
1047
1073
  color: currentColor;
1074
+ /* Optical nudge \u2014 SVG viewBox sits slightly high vs EconomistSans caps */
1075
+ transform: translateY(0.06em);
1048
1076
  }
1049
1077
 
1050
1078
  teg-apple-pay-button .apple-pay-btn.wap-loading {
@@ -1052,6 +1080,10 @@ var apple_pay_button_template_default = `<style>
1052
1080
  cursor: default;
1053
1081
  }
1054
1082
 
1083
+ teg-apple-pay-button .apple-pay-btn.wap-loading .apple-pay-btn__label {
1084
+ visibility: hidden;
1085
+ }
1086
+
1055
1087
  teg-apple-pay-button .apple-pay-btn.wap-loading::before {
1056
1088
  content: '';
1057
1089
  position: absolute;
@@ -1065,11 +1097,6 @@ var apple_pay_button_template_default = `<style>
1065
1097
  animation: wap-button-spinner 0.8s linear infinite;
1066
1098
  }
1067
1099
 
1068
- teg-apple-pay-button .apple-pay-btn__logo {
1069
- display: inline-flex;
1070
- align-items: center;
1071
- }
1072
-
1073
1100
  teg-apple-pay-button .apple-pay-btn__loading {
1074
1101
  display: none;
1075
1102
  }
@@ -1084,18 +1111,26 @@ var apple_pay_button_template_default = `<style>
1084
1111
  }
1085
1112
  </style>
1086
1113
 
1087
- <div class="apple-pay-container" aria-label="Express checkout with Apple Pay">
1114
+ <div class="apple-pay-container" aria-label="Subscribe with Apple Pay">
1088
1115
  <button
1089
1116
  class="apple-pay-btn"
1090
1117
  type="button"
1091
- aria-label="Pay with Apple Pay"
1118
+ aria-label="Subscribe with Apple Pay"
1092
1119
  data-analytics="paywall:apple-pay-checkout"
1093
1120
  >
1094
- <span class="apple-pay-btn__logo">
1095
- <svg width="51" height="22" aria-label="Apple Pay" role="img">
1121
+ <span class="apple-pay-btn__label"
1122
+ ><span class="apple-pay-btn__caption">Subscribe with</span
1123
+ ><svg
1124
+ class="apple-pay-btn__logo"
1125
+ width="42"
1126
+ height="18"
1127
+ viewBox="0 0 51 22"
1128
+ aria-hidden="true"
1129
+ role="img"
1130
+ >
1096
1131
  <use href="#apple-pay-logo" />
1097
- </svg>
1098
- </span>
1132
+ </svg
1133
+ ></span>
1099
1134
  <span class="apple-pay-btn__loading" aria-hidden="true">Loading...</span>
1100
1135
  </button>
1101
1136
  </div>
@@ -1902,6 +1937,19 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
1902
1937
  return [...zoneCountries];
1903
1938
  };
1904
1939
 
1940
+ // src/constants.ts
1941
+ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint3) => {
1942
+ ApplePayEntryPoint3["PAYWALL"] = "article_paywall";
1943
+ ApplePayEntryPoint3["REGWALL"] = "article_regwall";
1944
+ ApplePayEntryPoint3["DUAL_OFFER_BANNER"] = "dual_offer_banner";
1945
+ return ApplePayEntryPoint3;
1946
+ })(ApplePayEntryPoint || {});
1947
+ var APPLE_PAY_EXPRESS_BANNERS_EXPERIMENT_KEY = "subscribe-experiment-calibration";
1948
+ var APPLE_PAY_EXPRESS_BANNERS_VARIANTS = {
1949
+ CONTROL: "control",
1950
+ TREATMENT: "treatment"
1951
+ };
1952
+
1905
1953
  // src/apple-pay-button.ts
1906
1954
  var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
1907
1955
  var TOTAL_LABEL = "The Economist";
@@ -1919,7 +1967,23 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1919
1967
  define(_ApplePayButton.tag, _ApplePayButton);
1920
1968
  }
1921
1969
  /**
1922
- * Creates and configures an ApplePayButton if the feature flag is present.
1970
+ * Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
1971
+ *
1972
+ * Reads the experiment variant from `window.experimentIntegration.getVariant` using
1973
+ * {@link APPLE_PAY_EXPRESS_BANNERS_EXPERIMENT_KEY}. The host page is responsible
1974
+ * for setting up `window.experimentIntegration` before calling this method.
1975
+ *
1976
+ * - `treatment` → button created and returned
1977
+ * - `control` / missing / anything else → returns null (button suppressed)
1978
+ *
1979
+ * **Transition period:** the legacy `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param
1980
+ * gate is also evaluated as a fallback until all host apps have integrated
1981
+ * `window.experimentIntegration`. Once all consumers are migrated, the URL param
1982
+ * fallback will be removed.
1983
+ *
1984
+ * @param offer - The offer to display in the Apple Pay flow.
1985
+ * @param country - The user's country code.
1986
+ * @param entryPoint - Where the button is being rendered (e.g. paywall, banner).
1923
1987
  */
1924
1988
  static createIfEnabled(offer, country, entryPoint) {
1925
1989
  if (!offer) {
@@ -1928,7 +1992,18 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1928
1992
  if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
1929
1993
  return null;
1930
1994
  }
1931
- if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
1995
+ const experimentValue = window.experimentIntegration?.getVariant?.(
1996
+ APPLE_PAY_EXPRESS_BANNERS_EXPERIMENT_KEY
1997
+ );
1998
+ const isTreatment = experimentValue === APPLE_PAY_EXPRESS_BANNERS_VARIANTS.TREATMENT;
1999
+ const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
2000
+ FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
2001
+ );
2002
+ console.log(`Apple Pay button experiment: variant="${experimentValue}`);
2003
+ if (!isTreatment && !hasUrlParamFlag) {
2004
+ console.log(
2005
+ `Apple Pay button suppressed: experiment variant is "${experimentValue}" and URL param "${FEATURE_APPLE_PAY_EXPRESS_CHECKOUT}" is not present.`
2006
+ );
1932
2007
  return null;
1933
2008
  }
1934
2009
  _ApplePayButton.define();
@@ -2161,8 +2236,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2161
2236
  }
2162
2237
  const skuId = this.#offer.sku_id;
2163
2238
  const country = this.#country;
2164
- modal.onConfirm = (recaptchaTokensPromise) => {
2165
- this.#initiateApplePay(skuId, country, recaptchaTokensPromise);
2239
+ modal.onConfirm = (recaptchaTokenPromise) => {
2240
+ this.#initiateApplePay(skuId, country, recaptchaTokenPromise);
2166
2241
  };
2167
2242
  modal.open();
2168
2243
  }
@@ -2185,7 +2260,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2185
2260
  return null;
2186
2261
  }
2187
2262
  }
2188
- #buildSessionParams(skuId, country, sessionData, paymentOptions, recaptchaTokensPromise) {
2263
+ #buildSessionParams(skuId, country, sessionData, paymentOptions, recaptchaTokenPromise) {
2189
2264
  const offer = this.#offer;
2190
2265
  const totalAmount = offer.price?.purchase ? `${offer.price.purchase}` : DEFAULT_TOTAL;
2191
2266
  return {
@@ -2198,7 +2273,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2198
2273
  returnUrl: this.#returnUrl,
2199
2274
  userLoggedIn: sessionData.loggedIn,
2200
2275
  onPaymentAuthorized: async (event, session) => {
2201
- const recaptchaToken = await recaptchaTokensPromise;
2276
+ const recaptchaToken = await recaptchaTokenPromise;
2202
2277
  return handlePaymentAuthorized(event, session, sessionData, {
2203
2278
  skuId,
2204
2279
  country,
@@ -2210,7 +2285,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2210
2285
  }
2211
2286
  };
2212
2287
  }
2213
- #initiateApplePay(skuId, country, recaptchaTokensPromise) {
2288
+ #initiateApplePay(skuId, country, recaptchaTokenPromise) {
2214
2289
  try {
2215
2290
  const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
2216
2291
  const paymentOptions = this.#paymentOptions;
@@ -2223,7 +2298,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2223
2298
  country,
2224
2299
  sessionData,
2225
2300
  paymentOptions,
2226
- recaptchaTokensPromise
2301
+ recaptchaTokenPromise
2227
2302
  )
2228
2303
  );
2229
2304
  } catch {
@@ -2236,14 +2311,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2236
2311
  }
2237
2312
  };
2238
2313
 
2239
- // src/constants.ts
2240
- var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
2241
- ApplePayEntryPoint2["PAYWALL"] = "article_paywall";
2242
- ApplePayEntryPoint2["REGWALL"] = "article_regwall";
2243
- ApplePayEntryPoint2["DUAL_OFFER_BANNER"] = "dual_offer_banner";
2244
- return ApplePayEntryPoint2;
2245
- })(ApplePayEntryPoint || {});
2246
-
2247
2314
  // src/index.ts
2248
2315
  function defineApplePayElements() {
2249
2316
  ApplePayButton.define();
@@ -1,12 +1,40 @@
1
1
  import type { Offer, ProductVariant } from './types/offer.types';
2
2
  import { ApplePayEntryPoint } from './constants';
3
+ /**
4
+ * The host page is responsible for setting up `window.experimentIntegration`
5
+ * with a `getVariant` method that returns the variant value for a given flag key.
6
+ * web-apple-pay reads the experiment variant from here to decide whether to show or hide the button.
7
+ */
8
+ declare global {
9
+ interface Window {
10
+ experimentIntegration?: {
11
+ getVariant: (flagKey: string) => string | undefined;
12
+ };
13
+ }
14
+ }
3
15
  export declare const APPLE_PAY_EXCLUDED_VARIANTS: readonly ProductVariant[];
4
16
  export declare class ApplePayButton extends HTMLElement {
5
17
  #private;
6
18
  static readonly tag = "teg-apple-pay-button";
7
19
  static define(): void;
8
20
  /**
9
- * Creates and configures an ApplePayButton if the feature flag is present.
21
+ * Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
22
+ *
23
+ * Reads the experiment variant from `window.experimentIntegration.getVariant` using
24
+ * {@link APPLE_PAY_EXPRESS_BANNERS_EXPERIMENT_KEY}. The host page is responsible
25
+ * for setting up `window.experimentIntegration` before calling this method.
26
+ *
27
+ * - `treatment` → button created and returned
28
+ * - `control` / missing / anything else → returns null (button suppressed)
29
+ *
30
+ * **Transition period:** the legacy `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param
31
+ * gate is also evaluated as a fallback until all host apps have integrated
32
+ * `window.experimentIntegration`. Once all consumers are migrated, the URL param
33
+ * fallback will be removed.
34
+ *
35
+ * @param offer - The offer to display in the Apple Pay flow.
36
+ * @param country - The user's country code.
37
+ * @param entryPoint - Where the button is being rendered (e.g. paywall, banner).
10
38
  */
11
39
  static createIfEnabled(offer: Offer | undefined, country: string, entryPoint?: ApplePayEntryPoint): ApplePayButton | null;
12
40
  get offer(): Offer | null;
@@ -600,7 +600,7 @@ var getRecaptchaToken = async (action) => {
600
600
  });
601
601
  });
602
602
  };
603
- var getPurchaseRecaptchaTokens = () => {
603
+ var getPurchaseRecaptchaToken = () => {
604
604
  return getRecaptchaToken("walletPurchase");
605
605
  };
606
606
 
@@ -829,7 +829,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
829
829
  #isClosed = false;
830
830
  /**
831
831
  * Callback invoked synchronously from the CTA click handler.
832
- * Receives a Promise of reCAPTCHA tokens — the promise is already in-flight
832
+ * Receives a Promise of a reCAPTCHA token — the promise is already in-flight
833
833
  * by the time this is called. The caller (ApplePayButton) must call
834
834
  * new ApplePaySession() synchronously inside this callback to stay within
835
835
  * Safari's user-gesture window. The token promise resolves before
@@ -941,12 +941,12 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
941
941
  this.querySelector('[role="alert"]:not(#apple-pay-modal-error)')?.remove();
942
942
  cta.disabled = true;
943
943
  cta.setAttribute("aria-busy", "true");
944
- const recaptchaTokensPromise = getPurchaseRecaptchaTokens();
944
+ const recaptchaTokenPromise = getPurchaseRecaptchaToken();
945
945
  if (!this.#isClosed && this.onConfirm) {
946
- this.onConfirm(recaptchaTokensPromise);
946
+ this.onConfirm(recaptchaTokenPromise);
947
947
  this.close();
948
948
  }
949
- recaptchaTokensPromise.catch(() => {
949
+ recaptchaTokenPromise.catch(() => {
950
950
  if (this.#isClosed) return;
951
951
  cta.disabled = false;
952
952
  cta.removeAttribute("aria-busy");
@@ -1001,7 +1001,10 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
1001
1001
 
1002
1002
  // src/templates/apple-pay-button.template.html
1003
1003
  var apple_pay_button_template_default = `<style>
1004
- /* Use CSS variables for layout so parent walls can easily override placement and sizing */
1004
+ /*
1005
+ * Entry CTA: \u201CSubscribe with\u201D + Apple Pay wordmark (Figma 1118:14088).
1006
+ * \u201CSubscribe with\u201D matches Continue to checkout typography (EconomistSans Regular / 17 / 24 / 400).
1007
+ */
1005
1008
  teg-apple-pay-button {
1006
1009
  display: block;
1007
1010
  margin: var(--apple-pay-margin, 0);
@@ -1021,25 +1024,50 @@ var apple_pay_button_template_default = `<style>
1021
1024
  display: flex;
1022
1025
  align-items: center;
1023
1026
  justify-content: center;
1024
- gap: 0.375rem;
1025
1027
  width: 100%;
1026
1028
  min-width: 0;
1027
1029
  height: 100%;
1028
- min-height: var(--apple-pay-height, 2.75rem);
1029
- background-color: var(--apple-pay-background-color, #000);
1030
+ min-height: var(--apple-pay-height, 2.5rem);
1031
+ padding: 0;
1032
+ box-sizing: border-box;
1033
+ background-color: var(--apple-pay-background-color, #1a1a1a);
1030
1034
  color: var(--apple-pay-foreground-color, #fff);
1031
1035
  border: none;
1032
- border-radius: var(--apple-pay-border-radius, 1.375rem);
1036
+ border-radius: var(--apple-pay-border-radius, 0.25rem);
1033
1037
  cursor: pointer;
1034
- font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
1035
- font-size: 1.0625rem;
1036
- font-weight: 500;
1038
+ /* Same as wall Continue to checkout / Marber button large */
1039
+ font-family: var(
1040
+ --mb-typeface-sans,
1041
+ var(--wall-type-system-sans, 'EconomistSans', system-ui, sans-serif)
1042
+ );
1043
+ font-size: var(--mb-button-font-size, 1.0625rem);
1044
+ font-weight: var(--mb-font-weight-regular, 400);
1045
+ line-height: 1;
1037
1046
  }
1038
1047
 
1039
- teg-apple-pay-button .apple-pay-btn svg {
1048
+ teg-apple-pay-button .apple-pay-btn__label {
1049
+ display: inline-flex;
1050
+ align-items: center;
1051
+ /* No flex gap \u2014 spacing after \u201Cwith\u201D uses the same word-space as \u201CSubscribe with\u201D */
1052
+ gap: 0;
1053
+ white-space: nowrap;
1054
+ }
1055
+
1056
+ teg-apple-pay-button .apple-pay-btn__caption {
1057
+ /* One typographic word space after \u201Cwith\u201D, matching Subscribe\u2194with */
1058
+ padding-right: 0.25em;
1059
+ }
1060
+
1061
+ teg-apple-pay-button .apple-pay-btn__logo {
1040
1062
  flex-shrink: 0;
1041
1063
  display: block;
1064
+ /* Match caption font-size so mark aligns with text metrics */
1065
+ height: 1.05em;
1066
+ width: auto;
1067
+ aspect-ratio: 51 / 22;
1042
1068
  color: currentColor;
1069
+ /* Optical nudge \u2014 SVG viewBox sits slightly high vs EconomistSans caps */
1070
+ transform: translateY(0.06em);
1043
1071
  }
1044
1072
 
1045
1073
  teg-apple-pay-button .apple-pay-btn.wap-loading {
@@ -1047,6 +1075,10 @@ var apple_pay_button_template_default = `<style>
1047
1075
  cursor: default;
1048
1076
  }
1049
1077
 
1078
+ teg-apple-pay-button .apple-pay-btn.wap-loading .apple-pay-btn__label {
1079
+ visibility: hidden;
1080
+ }
1081
+
1050
1082
  teg-apple-pay-button .apple-pay-btn.wap-loading::before {
1051
1083
  content: '';
1052
1084
  position: absolute;
@@ -1060,11 +1092,6 @@ var apple_pay_button_template_default = `<style>
1060
1092
  animation: wap-button-spinner 0.8s linear infinite;
1061
1093
  }
1062
1094
 
1063
- teg-apple-pay-button .apple-pay-btn__logo {
1064
- display: inline-flex;
1065
- align-items: center;
1066
- }
1067
-
1068
1095
  teg-apple-pay-button .apple-pay-btn__loading {
1069
1096
  display: none;
1070
1097
  }
@@ -1079,18 +1106,26 @@ var apple_pay_button_template_default = `<style>
1079
1106
  }
1080
1107
  </style>
1081
1108
 
1082
- <div class="apple-pay-container" aria-label="Express checkout with Apple Pay">
1109
+ <div class="apple-pay-container" aria-label="Subscribe with Apple Pay">
1083
1110
  <button
1084
1111
  class="apple-pay-btn"
1085
1112
  type="button"
1086
- aria-label="Pay with Apple Pay"
1113
+ aria-label="Subscribe with Apple Pay"
1087
1114
  data-analytics="paywall:apple-pay-checkout"
1088
1115
  >
1089
- <span class="apple-pay-btn__logo">
1090
- <svg width="51" height="22" aria-label="Apple Pay" role="img">
1116
+ <span class="apple-pay-btn__label"
1117
+ ><span class="apple-pay-btn__caption">Subscribe with</span
1118
+ ><svg
1119
+ class="apple-pay-btn__logo"
1120
+ width="42"
1121
+ height="18"
1122
+ viewBox="0 0 51 22"
1123
+ aria-hidden="true"
1124
+ role="img"
1125
+ >
1091
1126
  <use href="#apple-pay-logo" />
1092
- </svg>
1093
- </span>
1127
+ </svg
1128
+ ></span>
1094
1129
  <span class="apple-pay-btn__loading" aria-hidden="true">Loading...</span>
1095
1130
  </button>
1096
1131
  </div>
@@ -1897,6 +1932,13 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
1897
1932
  return [...zoneCountries];
1898
1933
  };
1899
1934
 
1935
+ // src/constants.ts
1936
+ var APPLE_PAY_EXPRESS_BANNERS_EXPERIMENT_KEY = "subscribe-experiment-calibration";
1937
+ var APPLE_PAY_EXPRESS_BANNERS_VARIANTS = {
1938
+ CONTROL: "control",
1939
+ TREATMENT: "treatment"
1940
+ };
1941
+
1900
1942
  // src/apple-pay-button.ts
1901
1943
  var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
1902
1944
  var TOTAL_LABEL = "The Economist";
@@ -1914,7 +1956,23 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1914
1956
  define(_ApplePayButton.tag, _ApplePayButton);
1915
1957
  }
1916
1958
  /**
1917
- * Creates and configures an ApplePayButton if the feature flag is present.
1959
+ * Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
1960
+ *
1961
+ * Reads the experiment variant from `window.experimentIntegration.getVariant` using
1962
+ * {@link APPLE_PAY_EXPRESS_BANNERS_EXPERIMENT_KEY}. The host page is responsible
1963
+ * for setting up `window.experimentIntegration` before calling this method.
1964
+ *
1965
+ * - `treatment` → button created and returned
1966
+ * - `control` / missing / anything else → returns null (button suppressed)
1967
+ *
1968
+ * **Transition period:** the legacy `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param
1969
+ * gate is also evaluated as a fallback until all host apps have integrated
1970
+ * `window.experimentIntegration`. Once all consumers are migrated, the URL param
1971
+ * fallback will be removed.
1972
+ *
1973
+ * @param offer - The offer to display in the Apple Pay flow.
1974
+ * @param country - The user's country code.
1975
+ * @param entryPoint - Where the button is being rendered (e.g. paywall, banner).
1918
1976
  */
1919
1977
  static createIfEnabled(offer, country, entryPoint) {
1920
1978
  if (!offer) {
@@ -1923,7 +1981,18 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1923
1981
  if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
1924
1982
  return null;
1925
1983
  }
1926
- if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
1984
+ const experimentValue = window.experimentIntegration?.getVariant?.(
1985
+ APPLE_PAY_EXPRESS_BANNERS_EXPERIMENT_KEY
1986
+ );
1987
+ const isTreatment = experimentValue === APPLE_PAY_EXPRESS_BANNERS_VARIANTS.TREATMENT;
1988
+ const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
1989
+ FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
1990
+ );
1991
+ console.log(`Apple Pay button experiment: variant="${experimentValue}`);
1992
+ if (!isTreatment && !hasUrlParamFlag) {
1993
+ console.log(
1994
+ `Apple Pay button suppressed: experiment variant is "${experimentValue}" and URL param "${FEATURE_APPLE_PAY_EXPRESS_CHECKOUT}" is not present.`
1995
+ );
1927
1996
  return null;
1928
1997
  }
1929
1998
  _ApplePayButton.define();
@@ -2156,8 +2225,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2156
2225
  }
2157
2226
  const skuId = this.#offer.sku_id;
2158
2227
  const country = this.#country;
2159
- modal.onConfirm = (recaptchaTokensPromise) => {
2160
- this.#initiateApplePay(skuId, country, recaptchaTokensPromise);
2228
+ modal.onConfirm = (recaptchaTokenPromise) => {
2229
+ this.#initiateApplePay(skuId, country, recaptchaTokenPromise);
2161
2230
  };
2162
2231
  modal.open();
2163
2232
  }
@@ -2180,7 +2249,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2180
2249
  return null;
2181
2250
  }
2182
2251
  }
2183
- #buildSessionParams(skuId, country, sessionData, paymentOptions, recaptchaTokensPromise) {
2252
+ #buildSessionParams(skuId, country, sessionData, paymentOptions, recaptchaTokenPromise) {
2184
2253
  const offer = this.#offer;
2185
2254
  const totalAmount = offer.price?.purchase ? `${offer.price.purchase}` : DEFAULT_TOTAL;
2186
2255
  return {
@@ -2193,7 +2262,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2193
2262
  returnUrl: this.#returnUrl,
2194
2263
  userLoggedIn: sessionData.loggedIn,
2195
2264
  onPaymentAuthorized: async (event, session) => {
2196
- const recaptchaToken = await recaptchaTokensPromise;
2265
+ const recaptchaToken = await recaptchaTokenPromise;
2197
2266
  return handlePaymentAuthorized(event, session, sessionData, {
2198
2267
  skuId,
2199
2268
  country,
@@ -2205,7 +2274,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2205
2274
  }
2206
2275
  };
2207
2276
  }
2208
- #initiateApplePay(skuId, country, recaptchaTokensPromise) {
2277
+ #initiateApplePay(skuId, country, recaptchaTokenPromise) {
2209
2278
  try {
2210
2279
  const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
2211
2280
  const paymentOptions = this.#paymentOptions;
@@ -2218,7 +2287,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2218
2287
  country,
2219
2288
  sessionData,
2220
2289
  paymentOptions,
2221
- recaptchaTokensPromise
2290
+ recaptchaTokenPromise
2222
2291
  )
2223
2292
  );
2224
2293
  } catch {