@economist/web-apple-pay 2.0.0-beta.1 → 2.0.0-beta.2

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
@@ -27,7 +27,10 @@ npm install --save @economist/web-apple-pay
27
27
  Call `configureApplePay(...)` once during app startup, before rendering Apple Pay UI:
28
28
 
29
29
  ```ts
30
- import { configureApplePay, defineApplePayElements } from '@economist/web-apple-pay';
30
+ import {
31
+ configureApplePay,
32
+ defineApplePayElements,
33
+ } from '@economist/web-apple-pay';
31
34
 
32
35
  configureApplePay({
33
36
  merchantId: 'merchant.com.economist.your-app',
@@ -85,8 +88,8 @@ to the DOM. This is the supported, stable way to know whether Apple Pay is
85
88
  available without touching lifecycle internals.
86
89
 
87
90
  ```ts
88
- container.appendChild(btn); // spec-compliant — browser fires connectedCallback naturally
89
- await btn.whenReady(); // resolves when rendering is complete
91
+ container.appendChild(btn); // spec-compliant — browser fires connectedCallback naturally
92
+ await btn.whenReady(); // resolves when rendering is complete
90
93
  if (btn.style.display !== 'none') {
91
94
  // Apple Pay rendered successfully
92
95
  } else {
@@ -122,7 +125,8 @@ Consumers should listen for this event and continue payment orchestration.
122
125
  - `ApplePayButton`: button component class.
123
126
  - `whenReady(): Promise<void>` — resolves when the current render lifecycle completes (available or hidden). Resolves immediately if called before the element is connected.
124
127
  - `createIfEnabled(offer, country, entryPoint?)`: returns a configured button or `null`.
125
- - `DUAL_OFFER_BANNER` (or omitted): always-on after homepage + Safari/Apple eligibility and offer exclusions — no banners Amplitude experiment / `$exposure`.
128
+ - `DUAL_OFFER_BANNER` (or omitted): always-on after offer exclusions — no homepage/Safari gate at `createIfEnabled` (device gating via `isApplePayAvailable` on mount); no banners Amplitude experiment / `$exposure`.
129
+ - `FREE_TRIAL_BANNER`: same always-on-after-exclusions gate as Dual; wallet impression `entry_point` is `free_trial_banner`.
126
130
  - `PAYWALL`: experiment-gated via `apple-pay-express-checkout-on-paywalls` (`treatment` or QA URL).
127
131
  - `REGWALL`: inert — always returns `null`.
128
132
  - `ApplePayModal`: modal component class.
@@ -141,9 +145,9 @@ Consumers should listen for this event and continue payment orchestration.
141
145
  Check:
142
146
 
143
147
  - `configureApplePay(...)` was called before rendering (with a valid `merchantId` and `walletApiBaseUrl`)
144
- - device/browser supports Apple Pay (Safari on Apple device required)
145
- - for paywalls: Amplitude treatment (or `?FEATURE_APPLE_PAY_EXPRESS_CHECKOUT`) is satisfied
146
- - for banners: homepage + Safari/Apple eligibility (and consumer kill switch off)
148
+ - device/browser supports Apple Pay (Safari on Apple device required — enforced by `isApplePayAvailable` on mount)
149
+ - for paywalls: Amplitude treatment (or `?FEATURE_APPLE_PAY_EXPRESS_CHECKOUT`) is satisfied, plus Safari/Apple placement eligibility
150
+ - for banners: consumer kill switch off (no homepage/Safari gate at `createIfEnabled`)
147
151
  - offer variant is not excluded (`bundle`, `insider_print`)
148
152
 
149
153
  ### Logged-in checkbox copy looks wrong
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_BANNER"] = "free_trial_banner";
1311
1312
  return ApplePayEntryPoint2;
1312
1313
  })(ApplePayEntryPoint || {});
1313
1314
  var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
@@ -1382,8 +1383,11 @@ var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
1382
1383
  device: getDevice()
1383
1384
  });
1384
1385
  };
1385
- var trackExpressWalletClick = (skuId) => {
1386
- track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, { sku_id: skuId });
1386
+ var trackExpressWalletClick = (skuId, { entryPoint } = {}) => {
1387
+ track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
1388
+ sku_id: skuId,
1389
+ ...entryPoint ? { entry_point: entryPoint } : {}
1390
+ });
1387
1391
  };
1388
1392
  var trackWalletPaymentSheetOpen = (skuId) => {
1389
1393
  track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
@@ -2004,15 +2008,17 @@ var getExperimentKeyFromNextData = (flagKey) => {
2004
2008
  };
2005
2009
 
2006
2010
  // src/utils/applePayExpressEligibility.ts
2007
- var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
2008
- var isEligibleForApplePayExpressBanner = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
2009
2011
  var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
2010
2012
 
2011
2013
  // src/apple-pay-button.ts
2012
2014
  var ENTRY_POINT_CONFIG = {
2013
2015
  ["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
2014
- isEligible: isEligibleForApplePayExpressBanner
2015
- // no experimentFlagKey → always-on after eligibility / exclusions
2016
+ isEligible: () => true
2017
+ // no experimentFlagKey → always-on after offer exclusions
2018
+ },
2019
+ ["free_trial_banner" /* FREE_TRIAL_BANNER */]: {
2020
+ isEligible: () => true
2021
+ // Dual parity — no experimentFlagKey, no homepage gate here
2016
2022
  },
2017
2023
  ["article_paywall" /* PAYWALL */]: {
2018
2024
  isEligible: isEligibleForApplePayExpressPaywallExperiment,
@@ -2041,8 +2047,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2041
2047
  /**
2042
2048
  * Creates and configures an ApplePayButton when the entry point allows it.
2043
2049
  *
2044
- * - `DUAL_OFFER_BANNER` (or omitted): always-on after eligibility / exclusions —
2045
- * no banners experiment read and no banners `$exposure`.
2050
+ * - `DUAL_OFFER_BANNER` (or omitted): always-on after offer exclusions —
2051
+ * no homepage/Safari gate here, no banners experiment read, and no banners
2052
+ * `$exposure`.
2053
+ * - `FREE_TRIAL_BANNER`: same always-on-after-exclusions gate as Dual; distinct
2054
+ * TEDL `entry_point` string (`free_trial_banner`) for wallet impression attribution.
2046
2055
  * - `PAYWALL`: experiment-gated via {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}
2047
2056
  * (`treatment` or QA URL param). The host must set up
2048
2057
  * `window.experimentIntegration` before calling for this entry point.
@@ -2050,12 +2059,14 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2050
2059
  *
2051
2060
  * **PAYWALL only — transition period:** the legacy
2052
2061
  * `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param can show the button without
2053
- * treatment (and without inflating `$exposure`). For banners, the same URL
2054
- * param / `BYPASS_APPLE_PAY_CHECKS` only bypass **eligibility**, not an
2055
- * experiment gate.
2062
+ * treatment (and without inflating `$exposure`). For banners there is no
2063
+ * experiment gate; `BYPASS_APPLE_PAY_CHECKS` only skips device checks in
2064
+ * `isApplePayAvailable()` on mount.
2056
2065
  *
2057
2066
  * **Eligibility:**
2058
- * - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone
2067
+ * - `DUAL_OFFER_BANNER` / `FREE_TRIAL_BANNER` (or omitted): always eligible at
2068
+ * this gate (homepage placement is host-owned; Safari/Apple is enforced
2069
+ * later by `isApplePayAvailable()` on mount)
2059
2070
  * - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
2060
2071
  *
2061
2072
  * @param offer - The offer to display in the Apple Pay flow.
@@ -2086,9 +2097,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2086
2097
  return null;
2087
2098
  }
2088
2099
  if (experimentFlagKey) {
2089
- const experimentValue = window.experimentIntegration?.getVariant?.(
2090
- experimentFlagKey
2091
- );
2100
+ const experimentValue = window.experimentIntegration?.getVariant?.(experimentFlagKey);
2092
2101
  const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2093
2102
  if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2094
2103
  void isApplePayAvailable().then((available) => {
@@ -2326,7 +2335,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2326
2335
  if (document.querySelector(ApplePayModal.tag)) {
2327
2336
  return;
2328
2337
  }
2329
- trackExpressWalletClick(this.#offer.sku_id);
2338
+ trackExpressWalletClick(
2339
+ this.#offer.sku_id,
2340
+ this.#entryPoint ? { entryPoint: this.#entryPoint } : void 0
2341
+ );
2330
2342
  ApplePayModal.define();
2331
2343
  const modal = document.createElement(ApplePayModal.tag);
2332
2344
  modal.offer = this.#offer;
@@ -8,8 +8,11 @@ export declare class ApplePayButton extends HTMLElement {
8
8
  /**
9
9
  * Creates and configures an ApplePayButton when the entry point allows it.
10
10
  *
11
- * - `DUAL_OFFER_BANNER` (or omitted): always-on after eligibility / exclusions —
12
- * no banners experiment read and no banners `$exposure`.
11
+ * - `DUAL_OFFER_BANNER` (or omitted): always-on after offer exclusions —
12
+ * no homepage/Safari gate here, no banners experiment read, and no banners
13
+ * `$exposure`.
14
+ * - `FREE_TRIAL_BANNER`: same always-on-after-exclusions gate as Dual; distinct
15
+ * TEDL `entry_point` string (`free_trial_banner`) for wallet impression attribution.
13
16
  * - `PAYWALL`: experiment-gated via {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}
14
17
  * (`treatment` or QA URL param). The host must set up
15
18
  * `window.experimentIntegration` before calling for this entry point.
@@ -17,12 +20,14 @@ export declare class ApplePayButton extends HTMLElement {
17
20
  *
18
21
  * **PAYWALL only — transition period:** the legacy
19
22
  * `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param can show the button without
20
- * treatment (and without inflating `$exposure`). For banners, the same URL
21
- * param / `BYPASS_APPLE_PAY_CHECKS` only bypass **eligibility**, not an
22
- * experiment gate.
23
+ * treatment (and without inflating `$exposure`). For banners there is no
24
+ * experiment gate; `BYPASS_APPLE_PAY_CHECKS` only skips device checks in
25
+ * `isApplePayAvailable()` on mount.
23
26
  *
24
27
  * **Eligibility:**
25
- * - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone
28
+ * - `DUAL_OFFER_BANNER` / `FREE_TRIAL_BANNER` (or omitted): always eligible at
29
+ * this gate (homepage placement is host-owned; Safari/Apple is enforced
30
+ * later by `isApplePayAvailable()` on mount)
26
31
  * - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
27
32
  *
28
33
  * @param offer - The offer to display in the Apple Pay flow.
@@ -1371,8 +1371,11 @@ var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
1371
1371
  device: getDevice()
1372
1372
  });
1373
1373
  };
1374
- var trackExpressWalletClick = (skuId) => {
1375
- track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, { sku_id: skuId });
1374
+ var trackExpressWalletClick = (skuId, { entryPoint } = {}) => {
1375
+ track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
1376
+ sku_id: skuId,
1377
+ ...entryPoint ? { entry_point: entryPoint } : {}
1378
+ });
1376
1379
  };
1377
1380
  var trackWalletPaymentSheetOpen = (skuId) => {
1378
1381
  track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
@@ -1993,15 +1996,17 @@ var getExperimentKeyFromNextData = (flagKey) => {
1993
1996
  };
1994
1997
 
1995
1998
  // src/utils/applePayExpressEligibility.ts
1996
- var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
1997
- var isEligibleForApplePayExpressBanner = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
1998
1999
  var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
1999
2000
 
2000
2001
  // src/apple-pay-button.ts
2001
2002
  var ENTRY_POINT_CONFIG = {
2002
2003
  ["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
2003
- isEligible: isEligibleForApplePayExpressBanner
2004
- // no experimentFlagKey → always-on after eligibility / exclusions
2004
+ isEligible: () => true
2005
+ // no experimentFlagKey → always-on after offer exclusions
2006
+ },
2007
+ ["free_trial_banner" /* FREE_TRIAL_BANNER */]: {
2008
+ isEligible: () => true
2009
+ // Dual parity — no experimentFlagKey, no homepage gate here
2005
2010
  },
2006
2011
  ["article_paywall" /* PAYWALL */]: {
2007
2012
  isEligible: isEligibleForApplePayExpressPaywallExperiment,
@@ -2030,8 +2035,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2030
2035
  /**
2031
2036
  * Creates and configures an ApplePayButton when the entry point allows it.
2032
2037
  *
2033
- * - `DUAL_OFFER_BANNER` (or omitted): always-on after eligibility / exclusions —
2034
- * no banners experiment read and no banners `$exposure`.
2038
+ * - `DUAL_OFFER_BANNER` (or omitted): always-on after offer exclusions —
2039
+ * no homepage/Safari gate here, no banners experiment read, and no banners
2040
+ * `$exposure`.
2041
+ * - `FREE_TRIAL_BANNER`: same always-on-after-exclusions gate as Dual; distinct
2042
+ * TEDL `entry_point` string (`free_trial_banner`) for wallet impression attribution.
2035
2043
  * - `PAYWALL`: experiment-gated via {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}
2036
2044
  * (`treatment` or QA URL param). The host must set up
2037
2045
  * `window.experimentIntegration` before calling for this entry point.
@@ -2039,12 +2047,14 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2039
2047
  *
2040
2048
  * **PAYWALL only — transition period:** the legacy
2041
2049
  * `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param can show the button without
2042
- * treatment (and without inflating `$exposure`). For banners, the same URL
2043
- * param / `BYPASS_APPLE_PAY_CHECKS` only bypass **eligibility**, not an
2044
- * experiment gate.
2050
+ * treatment (and without inflating `$exposure`). For banners there is no
2051
+ * experiment gate; `BYPASS_APPLE_PAY_CHECKS` only skips device checks in
2052
+ * `isApplePayAvailable()` on mount.
2045
2053
  *
2046
2054
  * **Eligibility:**
2047
- * - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone
2055
+ * - `DUAL_OFFER_BANNER` / `FREE_TRIAL_BANNER` (or omitted): always eligible at
2056
+ * this gate (homepage placement is host-owned; Safari/Apple is enforced
2057
+ * later by `isApplePayAvailable()` on mount)
2048
2058
  * - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
2049
2059
  *
2050
2060
  * @param offer - The offer to display in the Apple Pay flow.
@@ -2075,9 +2085,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2075
2085
  return null;
2076
2086
  }
2077
2087
  if (experimentFlagKey) {
2078
- const experimentValue = window.experimentIntegration?.getVariant?.(
2079
- experimentFlagKey
2080
- );
2088
+ const experimentValue = window.experimentIntegration?.getVariant?.(experimentFlagKey);
2081
2089
  const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2082
2090
  if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2083
2091
  void isApplePayAvailable().then((available) => {
@@ -2315,7 +2323,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2315
2323
  if (document.querySelector(ApplePayModal.tag)) {
2316
2324
  return;
2317
2325
  }
2318
- trackExpressWalletClick(this.#offer.sku_id);
2326
+ trackExpressWalletClick(
2327
+ this.#offer.sku_id,
2328
+ this.#entryPoint ? { entryPoint: this.#entryPoint } : void 0
2329
+ );
2319
2330
  ApplePayModal.define();
2320
2331
  const modal = document.createElement(ApplePayModal.tag);
2321
2332
  modal.offer = this.#offer;
@@ -1379,8 +1379,11 @@ var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
1379
1379
  device: getDevice()
1380
1380
  });
1381
1381
  };
1382
- var trackExpressWalletClick = (skuId) => {
1383
- track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, { sku_id: skuId });
1382
+ var trackExpressWalletClick = (skuId, { entryPoint } = {}) => {
1383
+ track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
1384
+ sku_id: skuId,
1385
+ ...entryPoint ? { entry_point: entryPoint } : {}
1386
+ });
1384
1387
  };
1385
1388
  var trackWalletPaymentSheetOpen = (skuId) => {
1386
1389
  track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
@@ -2001,15 +2004,17 @@ var getExperimentKeyFromNextData = (flagKey) => {
2001
2004
  };
2002
2005
 
2003
2006
  // src/utils/applePayExpressEligibility.ts
2004
- var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
2005
- var isEligibleForApplePayExpressBanner = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
2006
2007
  var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
2007
2008
 
2008
2009
  // src/apple-pay-button.ts
2009
2010
  var ENTRY_POINT_CONFIG = {
2010
2011
  ["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
2011
- isEligible: isEligibleForApplePayExpressBanner
2012
- // no experimentFlagKey → always-on after eligibility / exclusions
2012
+ isEligible: () => true
2013
+ // no experimentFlagKey → always-on after offer exclusions
2014
+ },
2015
+ ["free_trial_banner" /* FREE_TRIAL_BANNER */]: {
2016
+ isEligible: () => true
2017
+ // Dual parity — no experimentFlagKey, no homepage gate here
2013
2018
  },
2014
2019
  ["article_paywall" /* PAYWALL */]: {
2015
2020
  isEligible: isEligibleForApplePayExpressPaywallExperiment,
@@ -2038,8 +2043,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2038
2043
  /**
2039
2044
  * Creates and configures an ApplePayButton when the entry point allows it.
2040
2045
  *
2041
- * - `DUAL_OFFER_BANNER` (or omitted): always-on after eligibility / exclusions —
2042
- * no banners experiment read and no banners `$exposure`.
2046
+ * - `DUAL_OFFER_BANNER` (or omitted): always-on after offer exclusions —
2047
+ * no homepage/Safari gate here, no banners experiment read, and no banners
2048
+ * `$exposure`.
2049
+ * - `FREE_TRIAL_BANNER`: same always-on-after-exclusions gate as Dual; distinct
2050
+ * TEDL `entry_point` string (`free_trial_banner`) for wallet impression attribution.
2043
2051
  * - `PAYWALL`: experiment-gated via {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}
2044
2052
  * (`treatment` or QA URL param). The host must set up
2045
2053
  * `window.experimentIntegration` before calling for this entry point.
@@ -2047,12 +2055,14 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2047
2055
  *
2048
2056
  * **PAYWALL only — transition period:** the legacy
2049
2057
  * `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param can show the button without
2050
- * treatment (and without inflating `$exposure`). For banners, the same URL
2051
- * param / `BYPASS_APPLE_PAY_CHECKS` only bypass **eligibility**, not an
2052
- * experiment gate.
2058
+ * treatment (and without inflating `$exposure`). For banners there is no
2059
+ * experiment gate; `BYPASS_APPLE_PAY_CHECKS` only skips device checks in
2060
+ * `isApplePayAvailable()` on mount.
2053
2061
  *
2054
2062
  * **Eligibility:**
2055
- * - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone
2063
+ * - `DUAL_OFFER_BANNER` / `FREE_TRIAL_BANNER` (or omitted): always eligible at
2064
+ * this gate (homepage placement is host-owned; Safari/Apple is enforced
2065
+ * later by `isApplePayAvailable()` on mount)
2056
2066
  * - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
2057
2067
  *
2058
2068
  * @param offer - The offer to display in the Apple Pay flow.
@@ -2083,9 +2093,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2083
2093
  return null;
2084
2094
  }
2085
2095
  if (experimentFlagKey) {
2086
- const experimentValue = window.experimentIntegration?.getVariant?.(
2087
- experimentFlagKey
2088
- );
2096
+ const experimentValue = window.experimentIntegration?.getVariant?.(experimentFlagKey);
2089
2097
  const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2090
2098
  if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2091
2099
  void isApplePayAvailable().then((available) => {
@@ -2323,7 +2331,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2323
2331
  if (document.querySelector(ApplePayModal.tag)) {
2324
2332
  return;
2325
2333
  }
2326
- trackExpressWalletClick(this.#offer.sku_id);
2334
+ trackExpressWalletClick(
2335
+ this.#offer.sku_id,
2336
+ this.#entryPoint ? { entryPoint: this.#entryPoint } : void 0
2337
+ );
2327
2338
  ApplePayModal.define();
2328
2339
  const modal = document.createElement(ApplePayModal.tag);
2329
2340
  modal.offer = this.#offer;
@@ -1371,8 +1371,11 @@ var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
1371
1371
  device: getDevice()
1372
1372
  });
1373
1373
  };
1374
- var trackExpressWalletClick = (skuId) => {
1375
- track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, { sku_id: skuId });
1374
+ var trackExpressWalletClick = (skuId, { entryPoint } = {}) => {
1375
+ track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
1376
+ sku_id: skuId,
1377
+ ...entryPoint ? { entry_point: entryPoint } : {}
1378
+ });
1376
1379
  };
1377
1380
  var trackWalletPaymentSheetOpen = (skuId) => {
1378
1381
  track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
@@ -1993,15 +1996,17 @@ var getExperimentKeyFromNextData = (flagKey) => {
1993
1996
  };
1994
1997
 
1995
1998
  // src/utils/applePayExpressEligibility.ts
1996
- var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
1997
- var isEligibleForApplePayExpressBanner = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
1998
1999
  var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
1999
2000
 
2000
2001
  // src/apple-pay-button.ts
2001
2002
  var ENTRY_POINT_CONFIG = {
2002
2003
  ["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
2003
- isEligible: isEligibleForApplePayExpressBanner
2004
- // no experimentFlagKey → always-on after eligibility / exclusions
2004
+ isEligible: () => true
2005
+ // no experimentFlagKey → always-on after offer exclusions
2006
+ },
2007
+ ["free_trial_banner" /* FREE_TRIAL_BANNER */]: {
2008
+ isEligible: () => true
2009
+ // Dual parity — no experimentFlagKey, no homepage gate here
2005
2010
  },
2006
2011
  ["article_paywall" /* PAYWALL */]: {
2007
2012
  isEligible: isEligibleForApplePayExpressPaywallExperiment,
@@ -2030,8 +2035,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2030
2035
  /**
2031
2036
  * Creates and configures an ApplePayButton when the entry point allows it.
2032
2037
  *
2033
- * - `DUAL_OFFER_BANNER` (or omitted): always-on after eligibility / exclusions —
2034
- * no banners experiment read and no banners `$exposure`.
2038
+ * - `DUAL_OFFER_BANNER` (or omitted): always-on after offer exclusions —
2039
+ * no homepage/Safari gate here, no banners experiment read, and no banners
2040
+ * `$exposure`.
2041
+ * - `FREE_TRIAL_BANNER`: same always-on-after-exclusions gate as Dual; distinct
2042
+ * TEDL `entry_point` string (`free_trial_banner`) for wallet impression attribution.
2035
2043
  * - `PAYWALL`: experiment-gated via {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}
2036
2044
  * (`treatment` or QA URL param). The host must set up
2037
2045
  * `window.experimentIntegration` before calling for this entry point.
@@ -2039,12 +2047,14 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2039
2047
  *
2040
2048
  * **PAYWALL only — transition period:** the legacy
2041
2049
  * `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param can show the button without
2042
- * treatment (and without inflating `$exposure`). For banners, the same URL
2043
- * param / `BYPASS_APPLE_PAY_CHECKS` only bypass **eligibility**, not an
2044
- * experiment gate.
2050
+ * treatment (and without inflating `$exposure`). For banners there is no
2051
+ * experiment gate; `BYPASS_APPLE_PAY_CHECKS` only skips device checks in
2052
+ * `isApplePayAvailable()` on mount.
2045
2053
  *
2046
2054
  * **Eligibility:**
2047
- * - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone
2055
+ * - `DUAL_OFFER_BANNER` / `FREE_TRIAL_BANNER` (or omitted): always eligible at
2056
+ * this gate (homepage placement is host-owned; Safari/Apple is enforced
2057
+ * later by `isApplePayAvailable()` on mount)
2048
2058
  * - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
2049
2059
  *
2050
2060
  * @param offer - The offer to display in the Apple Pay flow.
@@ -2075,9 +2085,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2075
2085
  return null;
2076
2086
  }
2077
2087
  if (experimentFlagKey) {
2078
- const experimentValue = window.experimentIntegration?.getVariant?.(
2079
- experimentFlagKey
2080
- );
2088
+ const experimentValue = window.experimentIntegration?.getVariant?.(experimentFlagKey);
2081
2089
  const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2082
2090
  if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2083
2091
  void isApplePayAvailable().then((available) => {
@@ -2315,7 +2323,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2315
2323
  if (document.querySelector(ApplePayModal.tag)) {
2316
2324
  return;
2317
2325
  }
2318
- trackExpressWalletClick(this.#offer.sku_id);
2326
+ trackExpressWalletClick(
2327
+ this.#offer.sku_id,
2328
+ this.#entryPoint ? { entryPoint: this.#entryPoint } : void 0
2329
+ );
2319
2330
  ApplePayModal.define();
2320
2331
  const modal = document.createElement(ApplePayModal.tag);
2321
2332
  modal.offer = this.#offer;
@@ -1,7 +1,8 @@
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
+ FREE_TRIAL_BANNER = "free_trial_banner"
5
6
  }
6
7
  /**
7
8
  * Amplitude experiment key for Apple Pay Express Checkout on article paywalls
@@ -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_BANNER"] = "free_trial_banner";
6
7
  return ApplePayEntryPoint2;
7
8
  })(ApplePayEntryPoint || {});
8
9
  var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
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_BANNER"] = "free_trial_banner";
1311
1312
  return ApplePayEntryPoint2;
1312
1313
  })(ApplePayEntryPoint || {});
1313
1314
  var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
@@ -1382,8 +1383,11 @@ var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
1382
1383
  device: getDevice()
1383
1384
  });
1384
1385
  };
1385
- var trackExpressWalletClick = (skuId) => {
1386
- track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, { sku_id: skuId });
1386
+ var trackExpressWalletClick = (skuId, { entryPoint } = {}) => {
1387
+ track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
1388
+ sku_id: skuId,
1389
+ ...entryPoint ? { entry_point: entryPoint } : {}
1390
+ });
1387
1391
  };
1388
1392
  var trackWalletPaymentSheetOpen = (skuId) => {
1389
1393
  track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
@@ -2004,15 +2008,17 @@ var getExperimentKeyFromNextData = (flagKey) => {
2004
2008
  };
2005
2009
 
2006
2010
  // src/utils/applePayExpressEligibility.ts
2007
- var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
2008
- var isEligibleForApplePayExpressBanner = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
2009
2011
  var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
2010
2012
 
2011
2013
  // src/apple-pay-button.ts
2012
2014
  var ENTRY_POINT_CONFIG = {
2013
2015
  ["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
2014
- isEligible: isEligibleForApplePayExpressBanner
2015
- // no experimentFlagKey → always-on after eligibility / exclusions
2016
+ isEligible: () => true
2017
+ // no experimentFlagKey → always-on after offer exclusions
2018
+ },
2019
+ ["free_trial_banner" /* FREE_TRIAL_BANNER */]: {
2020
+ isEligible: () => true
2021
+ // Dual parity — no experimentFlagKey, no homepage gate here
2016
2022
  },
2017
2023
  ["article_paywall" /* PAYWALL */]: {
2018
2024
  isEligible: isEligibleForApplePayExpressPaywallExperiment,
@@ -2041,8 +2047,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2041
2047
  /**
2042
2048
  * Creates and configures an ApplePayButton when the entry point allows it.
2043
2049
  *
2044
- * - `DUAL_OFFER_BANNER` (or omitted): always-on after eligibility / exclusions —
2045
- * no banners experiment read and no banners `$exposure`.
2050
+ * - `DUAL_OFFER_BANNER` (or omitted): always-on after offer exclusions —
2051
+ * no homepage/Safari gate here, no banners experiment read, and no banners
2052
+ * `$exposure`.
2053
+ * - `FREE_TRIAL_BANNER`: same always-on-after-exclusions gate as Dual; distinct
2054
+ * TEDL `entry_point` string (`free_trial_banner`) for wallet impression attribution.
2046
2055
  * - `PAYWALL`: experiment-gated via {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}
2047
2056
  * (`treatment` or QA URL param). The host must set up
2048
2057
  * `window.experimentIntegration` before calling for this entry point.
@@ -2050,12 +2059,14 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2050
2059
  *
2051
2060
  * **PAYWALL only — transition period:** the legacy
2052
2061
  * `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param can show the button without
2053
- * treatment (and without inflating `$exposure`). For banners, the same URL
2054
- * param / `BYPASS_APPLE_PAY_CHECKS` only bypass **eligibility**, not an
2055
- * experiment gate.
2062
+ * treatment (and without inflating `$exposure`). For banners there is no
2063
+ * experiment gate; `BYPASS_APPLE_PAY_CHECKS` only skips device checks in
2064
+ * `isApplePayAvailable()` on mount.
2056
2065
  *
2057
2066
  * **Eligibility:**
2058
- * - `DUAL_OFFER_BANNER` (or omitted): homepage + Safari/iPhone
2067
+ * - `DUAL_OFFER_BANNER` / `FREE_TRIAL_BANNER` (or omitted): always eligible at
2068
+ * this gate (homepage placement is host-owned; Safari/Apple is enforced
2069
+ * later by `isApplePayAvailable()` on mount)
2059
2070
  * - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
2060
2071
  *
2061
2072
  * @param offer - The offer to display in the Apple Pay flow.
@@ -2086,9 +2097,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2086
2097
  return null;
2087
2098
  }
2088
2099
  if (experimentFlagKey) {
2089
- const experimentValue = window.experimentIntegration?.getVariant?.(
2090
- experimentFlagKey
2091
- );
2100
+ const experimentValue = window.experimentIntegration?.getVariant?.(experimentFlagKey);
2092
2101
  const isExperimentVariant = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
2093
2102
  if (isExperimentVariant && isEligible && !bypassApplePayChecks() && !hasUrlParamFlag) {
2094
2103
  void isApplePayAvailable().then((available) => {
@@ -2326,7 +2335,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2326
2335
  if (document.querySelector(ApplePayModal.tag)) {
2327
2336
  return;
2328
2337
  }
2329
- trackExpressWalletClick(this.#offer.sku_id);
2338
+ trackExpressWalletClick(
2339
+ this.#offer.sku_id,
2340
+ this.#entryPoint ? { entryPoint: this.#entryPoint } : void 0
2341
+ );
2330
2342
  ApplePayModal.define();
2331
2343
  const modal = document.createElement(ApplePayModal.tag);
2332
2344
  modal.offer = this.#offer;
@@ -1,18 +1,17 @@
1
1
  /**
2
- * Host-side placement eligibility for Apple Pay Express.
2
+ * Host-side placement eligibility helpers for Apple Pay Express.
3
3
  *
4
- * Used by createIfEnabled after offer exclusions. Enforces placement and
5
- * device/browser eligibility (homepage + Safari/Apple for banners;
6
- * Safari/Apple only for paywalls). Banner surfaces are always-on after
7
- * eligibility; paywalls remain experiment-gated separately. Exposure
8
- * (paywalls) is further gated on isApplePayAvailable()
9
- * (BYPASS_APPLE_PAY_CHECKS respected).
4
+ * Paywalls: used by createIfEnabled after offer exclusions so experiment
5
+ * $exposure is Safari/Apple-gated. Banners: createIfEnabled does not call
6
+ * the banner helper (always-on after offer exclusions); Safari/Apple still
7
+ * runs later via isApplePayAvailable() on mount. Exposure (paywalls) is
8
+ * further gated on isApplePayAvailable() (BYPASS_APPLE_PAY_CHECKS respected).
10
9
  */
11
10
  export declare const isApplePayExpressHomepage: (pathname?: string) => boolean;
12
11
  /**
13
12
  * Dual-offer / Free Trial homepage banners: homepage + Safari/iPhone.
14
13
  * Anonymous is assumed because these banners are only mounted for
15
- * anonymous visitors.
14
+ * anonymous visitors. Not wired into createIfEnabled ENTRY_POINT_CONFIG.
16
15
  */
17
16
  export declare const isEligibleForApplePayExpressBanner: () => boolean;
18
17
  /**
@@ -63,8 +63,17 @@ export type ImpressionMetadata = {
63
63
  export declare const trackApplePayExperimentExposure: (variant: string, experimentKey: string | undefined, flagKey: ApplePayExperimentFlagKey) => void;
64
64
  /** Wallet button displayed — emits all 5 required analytics dimensions. */
65
65
  export declare const trackExpressWalletImpression: (skuId: string, { entryPoint, country }: ImpressionMetadata) => void;
66
+ /**
67
+ * Optional metadata for the wallet click event.
68
+ * `entry_point` is included only when provided so existing one-arg callers stay
69
+ * payload-compatible.
70
+ */
71
+ export type ClickMetadata = {
72
+ /** Entry point where the Apple Pay button was clicked — e.g. 'free_trial_banner'. */
73
+ entryPoint?: string;
74
+ };
66
75
  /** Wallet button clicked */
67
- export declare const trackExpressWalletClick: (skuId: string) => void;
76
+ export declare const trackExpressWalletClick: (skuId: string, { entryPoint }?: ClickMetadata) => void;
68
77
  /** Apple Pay sheet opened (session.begin() called) */
69
78
  export declare const trackWalletPaymentSheetOpen: (skuId: string) => void;
70
79
  /** Payment authorised by the user in the Apple Pay sheet */
@@ -70,8 +70,11 @@ var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
70
70
  device: getDevice()
71
71
  });
72
72
  };
73
- var trackExpressWalletClick = (skuId) => {
74
- track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, { sku_id: skuId });
73
+ var trackExpressWalletClick = (skuId, { entryPoint } = {}) => {
74
+ track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
75
+ sku_id: skuId,
76
+ ...entryPoint ? { entry_point: entryPoint } : {}
77
+ });
75
78
  };
76
79
  var trackWalletPaymentSheetOpen = (skuId) => {
77
80
  track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
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": "2.0.0-beta.1",
4
+ "version": "2.0.0-beta.2",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",