@economist/web-apple-pay 1.10.2-beta.1 → 1.11.1-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 +19 -59
- package/dist/index.js +43 -36
- package/dist/src/apple-pay-button.d.ts +18 -17
- package/dist/src/apple-pay-button.js +42 -34
- package/dist/src/apple-pay-button.stories.js +42 -34
- package/dist/src/apple-pay-modal.js +3 -1
- package/dist/src/apple-pay-modal.stories.js +42 -34
- package/dist/src/constants.d.ts +7 -19
- package/dist/src/constants.js +1 -3
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +43 -36
- package/dist/src/utils/applePayExpressEligibility.d.ts +10 -9
- package/dist/src/utils/applePayExpressEligibility.js +2 -2
- package/dist/src/utils/expressCheckoutTracking.d.ts +13 -4
- package/dist/src/utils/expressCheckoutTracking.js +6 -4
- package/package.json +1 -1
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 {
|
|
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',
|
|
@@ -54,56 +57,6 @@ container.appendChild(button);
|
|
|
54
57
|
|
|
55
58
|
When clicked, the button creates and opens `teg-apple-pay-modal` automatically.
|
|
56
59
|
|
|
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
|
-
|
|
107
60
|
## Runtime configuration
|
|
108
61
|
|
|
109
62
|
### `configureApplePay(config)`
|
|
@@ -135,8 +88,8 @@ to the DOM. This is the supported, stable way to know whether Apple Pay is
|
|
|
135
88
|
available without touching lifecycle internals.
|
|
136
89
|
|
|
137
90
|
```ts
|
|
138
|
-
container.appendChild(btn);
|
|
139
|
-
await btn.whenReady();
|
|
91
|
+
container.appendChild(btn); // spec-compliant — browser fires connectedCallback naturally
|
|
92
|
+
await btn.whenReady(); // resolves when rendering is complete
|
|
140
93
|
if (btn.style.display !== 'none') {
|
|
141
94
|
// Apple Pay rendered successfully
|
|
142
95
|
} else {
|
|
@@ -170,13 +123,21 @@ Consumers should listen for this event and continue payment orchestration.
|
|
|
170
123
|
- `defineApplePayElements()`: registers both custom elements.
|
|
171
124
|
- `configureApplePay(config)`: sets required runtime config (merchant ID and wallet API base URL, with optional debug bypass).
|
|
172
125
|
- `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.
|
|
174
126
|
- `whenReady(): Promise<void>` — resolves when the current render lifecycle completes (available or hidden). Resolves immediately if called before the element is connected.
|
|
175
|
-
- `
|
|
127
|
+
- `createIfEnabled(offer, country, entryPoint?)`: returns a configured button or `null`.
|
|
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`.
|
|
130
|
+
- `PAYWALL`: experiment-gated via `apple-pay-express-checkout-on-paywalls` (`treatment` or QA URL).
|
|
131
|
+
- `REGWALL`: inert — always returns `null`.
|
|
176
132
|
- `ApplePayModal`: modal component class.
|
|
177
133
|
- `ensureApplePayLogoSymbol()`: logo symbol injection helper.
|
|
134
|
+
- `APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY`: Amplitude flag key for paywalls experiment gating / `$exposure`.
|
|
178
135
|
- `Offer`: offer contract type used by component props.
|
|
179
136
|
|
|
137
|
+
### Breaking changes
|
|
138
|
+
|
|
139
|
+
- `APPLE_PAY_EXPRESS_EXPERIMENT_KEY` (banners experiment flag) is no longer exported. Use `APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY` for paywalls, or drop the import if you only needed the retired banners key.
|
|
140
|
+
|
|
180
141
|
## Troubleshooting
|
|
181
142
|
|
|
182
143
|
### Button does not appear
|
|
@@ -184,9 +145,9 @@ Consumers should listen for this event and continue payment orchestration.
|
|
|
184
145
|
Check:
|
|
185
146
|
|
|
186
147
|
- `configureApplePay(...)` was called before rendering (with a valid `merchantId` and `walletApiBaseUrl`)
|
|
187
|
-
- device/browser supports Apple Pay (Safari on Apple device required)
|
|
188
|
-
- for
|
|
189
|
-
-
|
|
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`)
|
|
190
151
|
- offer variant is not excluded (`bundle`, `insider_print`)
|
|
191
152
|
|
|
192
153
|
### Logged-in checkbox copy looks wrong
|
|
@@ -237,4 +198,3 @@ Story coverage matrix:
|
|
|
237
198
|
- `ApplePayButton` behavior and state variants are available as individual canvas stories in Storybook.
|
|
238
199
|
- `ApplePayModal` docs page shows the stable default example.
|
|
239
200
|
- `ApplePayModal` behavior and state variants are available as individual canvas stories in Storybook.
|
|
240
|
-
|
package/dist/index.js
CHANGED
|
@@ -83,7 +83,9 @@ var apple_pay_modal_template_default = `<style>
|
|
|
83
83
|
left: 0;
|
|
84
84
|
width: 100%;
|
|
85
85
|
height: 100%;
|
|
86
|
-
|
|
86
|
+
/* Above acquisition DualOfferBanner (1000) and Engagement ribbon (96).
|
|
87
|
+
Was 97 for wall/ribbon hosts only; hosts without a ribbon clamp need this. */
|
|
88
|
+
z-index: 1100;
|
|
87
89
|
background: rgba(13, 13, 13, 0.7);
|
|
88
90
|
display: flex;
|
|
89
91
|
align-items: center;
|
|
@@ -1308,10 +1310,9 @@ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
|
|
|
1308
1310
|
ApplePayEntryPoint2["PAYWALL"] = "article_paywall";
|
|
1309
1311
|
ApplePayEntryPoint2["REGWALL"] = "article_regwall";
|
|
1310
1312
|
ApplePayEntryPoint2["DUAL_OFFER_BANNER"] = "dual_offer_banner";
|
|
1311
|
-
ApplePayEntryPoint2["
|
|
1313
|
+
ApplePayEntryPoint2["FREE_TRIAL_BANNER"] = "free_trial_banner";
|
|
1312
1314
|
return ApplePayEntryPoint2;
|
|
1313
1315
|
})(ApplePayEntryPoint || {});
|
|
1314
|
-
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
1315
1316
|
var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
1316
1317
|
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
1317
1318
|
CONTROL: "control",
|
|
@@ -1355,7 +1356,7 @@ var track = (action, extra) => {
|
|
|
1355
1356
|
...extra
|
|
1356
1357
|
});
|
|
1357
1358
|
};
|
|
1358
|
-
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey
|
|
1359
|
+
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey) => {
|
|
1359
1360
|
const isActiveVariant = variant === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || variant === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
1360
1361
|
if (!isActiveVariant) {
|
|
1361
1362
|
return;
|
|
@@ -1384,8 +1385,11 @@ var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
|
1384
1385
|
device: getDevice()
|
|
1385
1386
|
});
|
|
1386
1387
|
};
|
|
1387
|
-
var trackExpressWalletClick = (skuId) => {
|
|
1388
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1388
|
+
var trackExpressWalletClick = (skuId, { entryPoint } = {}) => {
|
|
1389
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1390
|
+
sku_id: skuId,
|
|
1391
|
+
...entryPoint ? { entry_point: entryPoint } : {}
|
|
1392
|
+
});
|
|
1389
1393
|
};
|
|
1390
1394
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1391
1395
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -2006,15 +2010,17 @@ var getExperimentKeyFromNextData = (flagKey) => {
|
|
|
2006
2010
|
};
|
|
2007
2011
|
|
|
2008
2012
|
// src/utils/applePayExpressEligibility.ts
|
|
2009
|
-
var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
|
|
2010
|
-
var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
|
|
2011
2013
|
var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
|
|
2012
2014
|
|
|
2013
2015
|
// src/apple-pay-button.ts
|
|
2014
2016
|
var ENTRY_POINT_CONFIG = {
|
|
2015
2017
|
["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
|
|
2016
|
-
isEligible:
|
|
2017
|
-
experimentFlagKey
|
|
2018
|
+
isEligible: () => true
|
|
2019
|
+
// no experimentFlagKey → always-on after offer exclusions
|
|
2020
|
+
},
|
|
2021
|
+
["free_trial_banner" /* FREE_TRIAL_BANNER */]: {
|
|
2022
|
+
isEligible: () => true
|
|
2023
|
+
// Dual parity — no experimentFlagKey, no homepage gate here
|
|
2018
2024
|
},
|
|
2019
2025
|
["article_paywall" /* PAYWALL */]: {
|
|
2020
2026
|
isEligible: isEligibleForApplePayExpressPaywallExperiment,
|
|
@@ -2022,10 +2028,7 @@ var ENTRY_POINT_CONFIG = {
|
|
|
2022
2028
|
},
|
|
2023
2029
|
["article_regwall" /* REGWALL */]: {
|
|
2024
2030
|
isEligible: () => true,
|
|
2025
|
-
|
|
2026
|
-
},
|
|
2027
|
-
["free_trial_popup" /* FREE_TRIAL_POPUP */]: {
|
|
2028
|
-
isEligible: () => true
|
|
2031
|
+
enabled: false
|
|
2029
2032
|
}
|
|
2030
2033
|
};
|
|
2031
2034
|
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
@@ -2044,28 +2047,29 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2044
2047
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
2045
2048
|
}
|
|
2046
2049
|
/**
|
|
2047
|
-
* Creates and configures an ApplePayButton when the
|
|
2050
|
+
* Creates and configures an ApplePayButton when the entry point allows it.
|
|
2048
2051
|
*
|
|
2049
|
-
*
|
|
2050
|
-
*
|
|
2051
|
-
*
|
|
2052
|
-
* -
|
|
2052
|
+
* - `DUAL_OFFER_BANNER` (or omitted): always-on after offer exclusions —
|
|
2053
|
+
* no homepage/Safari gate here, no banners experiment read, and no banners
|
|
2054
|
+
* `$exposure`.
|
|
2055
|
+
* - `FREE_TRIAL_BANNER`: same always-on-after-exclusions gate as Dual; distinct
|
|
2056
|
+
* TEDL `entry_point` string (`free_trial_banner`) for wallet impression attribution.
|
|
2057
|
+
* - `PAYWALL`: experiment-gated via {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}
|
|
2058
|
+
* (`treatment` or QA URL param). The host must set up
|
|
2059
|
+
* `window.experimentIntegration` before calling for this entry point.
|
|
2060
|
+
* - `REGWALL`: inert — always returns null.
|
|
2053
2061
|
*
|
|
2054
|
-
*
|
|
2055
|
-
*
|
|
2056
|
-
*
|
|
2057
|
-
*
|
|
2058
|
-
*
|
|
2059
|
-
*
|
|
2060
|
-
* **Transition period:** the legacy `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param
|
|
2061
|
-
* gate is also evaluated as a fallback until all host apps have integrated
|
|
2062
|
-
* `window.experimentIntegration`. Once all consumers are migrated, the URL param
|
|
2063
|
-
* fallback will be removed.
|
|
2062
|
+
* **PAYWALL only — transition period:** the legacy
|
|
2063
|
+
* `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param can show the button without
|
|
2064
|
+
* treatment (and without inflating `$exposure`). For banners there is no
|
|
2065
|
+
* experiment gate; `BYPASS_APPLE_PAY_CHECKS` only skips device checks in
|
|
2066
|
+
* `isApplePayAvailable()` on mount.
|
|
2064
2067
|
*
|
|
2065
2068
|
* **Eligibility:**
|
|
2066
|
-
* - `DUAL_OFFER_BANNER` (or omitted):
|
|
2069
|
+
* - `DUAL_OFFER_BANNER` / `FREE_TRIAL_BANNER` (or omitted): always eligible at
|
|
2070
|
+
* this gate (homepage placement is host-owned; Safari/Apple is enforced
|
|
2071
|
+
* later by `isApplePayAvailable()` on mount)
|
|
2067
2072
|
* - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
|
|
2068
|
-
* - `REGWALL` / `FREE_TRIAL_POPUP`: no host-side placement gate
|
|
2069
2073
|
*
|
|
2070
2074
|
* @param offer - The offer to display in the Apple Pay flow.
|
|
2071
2075
|
* @param country - The user's country code.
|
|
@@ -2088,6 +2092,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2088
2092
|
}
|
|
2089
2093
|
const { isEligible: eligibilityCheck, experimentFlagKey } = config;
|
|
2090
2094
|
const isEligible = eligibilityCheck();
|
|
2095
|
+
if (config.enabled === false) {
|
|
2096
|
+
return null;
|
|
2097
|
+
}
|
|
2091
2098
|
if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
|
|
2092
2099
|
return null;
|
|
2093
2100
|
}
|
|
@@ -2232,9 +2239,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2232
2239
|
button.removeAttribute("aria-busy");
|
|
2233
2240
|
button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2234
2241
|
}
|
|
2235
|
-
this.getAnimations?.({ subtree: true }).forEach(
|
|
2236
|
-
(animation) => animation.cancel()
|
|
2237
|
-
);
|
|
2242
|
+
this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2238
2243
|
void this.offsetHeight;
|
|
2239
2244
|
this.style.display = "none";
|
|
2240
2245
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
@@ -2343,7 +2348,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2343
2348
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2344
2349
|
return;
|
|
2345
2350
|
}
|
|
2346
|
-
trackExpressWalletClick(
|
|
2351
|
+
trackExpressWalletClick(
|
|
2352
|
+
this.#offer.sku_id,
|
|
2353
|
+
this.#entryPoint ? { entryPoint: this.#entryPoint } : void 0
|
|
2354
|
+
);
|
|
2347
2355
|
ApplePayModal.define();
|
|
2348
2356
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2349
2357
|
modal.offer = this.#offer;
|
|
@@ -2435,7 +2443,6 @@ function defineApplePayElements() {
|
|
|
2435
2443
|
}
|
|
2436
2444
|
export {
|
|
2437
2445
|
APPLE_PAY_EXCLUDED_VARIANTS,
|
|
2438
|
-
APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
|
|
2439
2446
|
APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY,
|
|
2440
2447
|
APPLE_PAY_EXPRESS_VARIANTS,
|
|
2441
2448
|
ApplePayButton,
|
|
@@ -6,28 +6,29 @@ export declare class ApplePayButton extends HTMLElement {
|
|
|
6
6
|
static readonly tag = "teg-apple-pay-button";
|
|
7
7
|
static define(): void;
|
|
8
8
|
/**
|
|
9
|
-
* Creates and configures an ApplePayButton when the
|
|
9
|
+
* Creates and configures an ApplePayButton when the entry point allows it.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* -
|
|
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.
|
|
16
|
+
* - `PAYWALL`: experiment-gated via {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}
|
|
17
|
+
* (`treatment` or QA URL param). The host must set up
|
|
18
|
+
* `window.experimentIntegration` before calling for this entry point.
|
|
19
|
+
* - `REGWALL`: inert — always returns null.
|
|
15
20
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* **Transition period:** the legacy `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param
|
|
23
|
-
* gate is also evaluated as a fallback until all host apps have integrated
|
|
24
|
-
* `window.experimentIntegration`. Once all consumers are migrated, the URL param
|
|
25
|
-
* fallback will be removed.
|
|
21
|
+
* **PAYWALL only — transition period:** the legacy
|
|
22
|
+
* `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param can show the button without
|
|
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.
|
|
26
26
|
*
|
|
27
27
|
* **Eligibility:**
|
|
28
|
-
* - `DUAL_OFFER_BANNER` (or omitted):
|
|
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)
|
|
29
31
|
* - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
|
|
30
|
-
* - `REGWALL` / `FREE_TRIAL_POPUP`: no host-side placement gate
|
|
31
32
|
*
|
|
32
33
|
* @param offer - The offer to display in the Apple Pay flow.
|
|
33
34
|
* @param country - The user's country code.
|
|
@@ -83,7 +83,9 @@ var apple_pay_modal_template_default = `<style>
|
|
|
83
83
|
left: 0;
|
|
84
84
|
width: 100%;
|
|
85
85
|
height: 100%;
|
|
86
|
-
|
|
86
|
+
/* Above acquisition DualOfferBanner (1000) and Engagement ribbon (96).
|
|
87
|
+
Was 97 for wall/ribbon hosts only; hosts without a ribbon clamp need this. */
|
|
88
|
+
z-index: 1100;
|
|
87
89
|
background: rgba(13, 13, 13, 0.7);
|
|
88
90
|
display: flex;
|
|
89
91
|
align-items: center;
|
|
@@ -1299,7 +1301,6 @@ var redirectToCheckoutFallback = (params) => {
|
|
|
1299
1301
|
};
|
|
1300
1302
|
|
|
1301
1303
|
// src/constants.ts
|
|
1302
|
-
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
1303
1304
|
var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
1304
1305
|
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
1305
1306
|
CONTROL: "control",
|
|
@@ -1343,7 +1344,7 @@ var track = (action, extra) => {
|
|
|
1343
1344
|
...extra
|
|
1344
1345
|
});
|
|
1345
1346
|
};
|
|
1346
|
-
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey
|
|
1347
|
+
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey) => {
|
|
1347
1348
|
const isActiveVariant = variant === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || variant === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
1348
1349
|
if (!isActiveVariant) {
|
|
1349
1350
|
return;
|
|
@@ -1372,8 +1373,11 @@ var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
|
1372
1373
|
device: getDevice()
|
|
1373
1374
|
});
|
|
1374
1375
|
};
|
|
1375
|
-
var trackExpressWalletClick = (skuId) => {
|
|
1376
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1376
|
+
var trackExpressWalletClick = (skuId, { entryPoint } = {}) => {
|
|
1377
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1378
|
+
sku_id: skuId,
|
|
1379
|
+
...entryPoint ? { entry_point: entryPoint } : {}
|
|
1380
|
+
});
|
|
1377
1381
|
};
|
|
1378
1382
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1379
1383
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -1994,15 +1998,17 @@ var getExperimentKeyFromNextData = (flagKey) => {
|
|
|
1994
1998
|
};
|
|
1995
1999
|
|
|
1996
2000
|
// src/utils/applePayExpressEligibility.ts
|
|
1997
|
-
var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
|
|
1998
|
-
var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
|
|
1999
2001
|
var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
|
|
2000
2002
|
|
|
2001
2003
|
// src/apple-pay-button.ts
|
|
2002
2004
|
var ENTRY_POINT_CONFIG = {
|
|
2003
2005
|
["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
|
|
2004
|
-
isEligible:
|
|
2005
|
-
experimentFlagKey
|
|
2006
|
+
isEligible: () => true
|
|
2007
|
+
// no experimentFlagKey → always-on after offer exclusions
|
|
2008
|
+
},
|
|
2009
|
+
["free_trial_banner" /* FREE_TRIAL_BANNER */]: {
|
|
2010
|
+
isEligible: () => true
|
|
2011
|
+
// Dual parity — no experimentFlagKey, no homepage gate here
|
|
2006
2012
|
},
|
|
2007
2013
|
["article_paywall" /* PAYWALL */]: {
|
|
2008
2014
|
isEligible: isEligibleForApplePayExpressPaywallExperiment,
|
|
@@ -2010,10 +2016,7 @@ var ENTRY_POINT_CONFIG = {
|
|
|
2010
2016
|
},
|
|
2011
2017
|
["article_regwall" /* REGWALL */]: {
|
|
2012
2018
|
isEligible: () => true,
|
|
2013
|
-
|
|
2014
|
-
},
|
|
2015
|
-
["free_trial_popup" /* FREE_TRIAL_POPUP */]: {
|
|
2016
|
-
isEligible: () => true
|
|
2019
|
+
enabled: false
|
|
2017
2020
|
}
|
|
2018
2021
|
};
|
|
2019
2022
|
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
@@ -2032,28 +2035,29 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2032
2035
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
2033
2036
|
}
|
|
2034
2037
|
/**
|
|
2035
|
-
* Creates and configures an ApplePayButton when the
|
|
2038
|
+
* Creates and configures an ApplePayButton when the entry point allows it.
|
|
2036
2039
|
*
|
|
2037
|
-
*
|
|
2038
|
-
*
|
|
2039
|
-
*
|
|
2040
|
-
* -
|
|
2040
|
+
* - `DUAL_OFFER_BANNER` (or omitted): always-on after offer exclusions —
|
|
2041
|
+
* no homepage/Safari gate here, no banners experiment read, and no banners
|
|
2042
|
+
* `$exposure`.
|
|
2043
|
+
* - `FREE_TRIAL_BANNER`: same always-on-after-exclusions gate as Dual; distinct
|
|
2044
|
+
* TEDL `entry_point` string (`free_trial_banner`) for wallet impression attribution.
|
|
2045
|
+
* - `PAYWALL`: experiment-gated via {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}
|
|
2046
|
+
* (`treatment` or QA URL param). The host must set up
|
|
2047
|
+
* `window.experimentIntegration` before calling for this entry point.
|
|
2048
|
+
* - `REGWALL`: inert — always returns null.
|
|
2041
2049
|
*
|
|
2042
|
-
*
|
|
2043
|
-
*
|
|
2044
|
-
*
|
|
2045
|
-
*
|
|
2046
|
-
*
|
|
2047
|
-
*
|
|
2048
|
-
* **Transition period:** the legacy `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param
|
|
2049
|
-
* gate is also evaluated as a fallback until all host apps have integrated
|
|
2050
|
-
* `window.experimentIntegration`. Once all consumers are migrated, the URL param
|
|
2051
|
-
* fallback will be removed.
|
|
2050
|
+
* **PAYWALL only — transition period:** the legacy
|
|
2051
|
+
* `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param can show the button without
|
|
2052
|
+
* treatment (and without inflating `$exposure`). For banners there is no
|
|
2053
|
+
* experiment gate; `BYPASS_APPLE_PAY_CHECKS` only skips device checks in
|
|
2054
|
+
* `isApplePayAvailable()` on mount.
|
|
2052
2055
|
*
|
|
2053
2056
|
* **Eligibility:**
|
|
2054
|
-
* - `DUAL_OFFER_BANNER` (or omitted):
|
|
2057
|
+
* - `DUAL_OFFER_BANNER` / `FREE_TRIAL_BANNER` (or omitted): always eligible at
|
|
2058
|
+
* this gate (homepage placement is host-owned; Safari/Apple is enforced
|
|
2059
|
+
* later by `isApplePayAvailable()` on mount)
|
|
2055
2060
|
* - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
|
|
2056
|
-
* - `REGWALL` / `FREE_TRIAL_POPUP`: no host-side placement gate
|
|
2057
2061
|
*
|
|
2058
2062
|
* @param offer - The offer to display in the Apple Pay flow.
|
|
2059
2063
|
* @param country - The user's country code.
|
|
@@ -2076,6 +2080,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2076
2080
|
}
|
|
2077
2081
|
const { isEligible: eligibilityCheck, experimentFlagKey } = config;
|
|
2078
2082
|
const isEligible = eligibilityCheck();
|
|
2083
|
+
if (config.enabled === false) {
|
|
2084
|
+
return null;
|
|
2085
|
+
}
|
|
2079
2086
|
if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
|
|
2080
2087
|
return null;
|
|
2081
2088
|
}
|
|
@@ -2220,9 +2227,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2220
2227
|
button.removeAttribute("aria-busy");
|
|
2221
2228
|
button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2222
2229
|
}
|
|
2223
|
-
this.getAnimations?.({ subtree: true }).forEach(
|
|
2224
|
-
(animation) => animation.cancel()
|
|
2225
|
-
);
|
|
2230
|
+
this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2226
2231
|
void this.offsetHeight;
|
|
2227
2232
|
this.style.display = "none";
|
|
2228
2233
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
@@ -2331,7 +2336,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2331
2336
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2332
2337
|
return;
|
|
2333
2338
|
}
|
|
2334
|
-
trackExpressWalletClick(
|
|
2339
|
+
trackExpressWalletClick(
|
|
2340
|
+
this.#offer.sku_id,
|
|
2341
|
+
this.#entryPoint ? { entryPoint: this.#entryPoint } : void 0
|
|
2342
|
+
);
|
|
2335
2343
|
ApplePayModal.define();
|
|
2336
2344
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2337
2345
|
modal.offer = this.#offer;
|
|
@@ -83,7 +83,9 @@ var apple_pay_modal_template_default = `<style>
|
|
|
83
83
|
left: 0;
|
|
84
84
|
width: 100%;
|
|
85
85
|
height: 100%;
|
|
86
|
-
|
|
86
|
+
/* Above acquisition DualOfferBanner (1000) and Engagement ribbon (96).
|
|
87
|
+
Was 97 for wall/ribbon hosts only; hosts without a ribbon clamp need this. */
|
|
88
|
+
z-index: 1100;
|
|
87
89
|
background: rgba(13, 13, 13, 0.7);
|
|
88
90
|
display: flex;
|
|
89
91
|
align-items: center;
|
|
@@ -1307,7 +1309,6 @@ var redirectToCheckoutFallback = (params) => {
|
|
|
1307
1309
|
};
|
|
1308
1310
|
|
|
1309
1311
|
// src/constants.ts
|
|
1310
|
-
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
1311
1312
|
var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
1312
1313
|
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
1313
1314
|
CONTROL: "control",
|
|
@@ -1351,7 +1352,7 @@ var track = (action, extra) => {
|
|
|
1351
1352
|
...extra
|
|
1352
1353
|
});
|
|
1353
1354
|
};
|
|
1354
|
-
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey
|
|
1355
|
+
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey) => {
|
|
1355
1356
|
const isActiveVariant = variant === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || variant === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
1356
1357
|
if (!isActiveVariant) {
|
|
1357
1358
|
return;
|
|
@@ -1380,8 +1381,11 @@ var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
|
1380
1381
|
device: getDevice()
|
|
1381
1382
|
});
|
|
1382
1383
|
};
|
|
1383
|
-
var trackExpressWalletClick = (skuId) => {
|
|
1384
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1384
|
+
var trackExpressWalletClick = (skuId, { entryPoint } = {}) => {
|
|
1385
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1386
|
+
sku_id: skuId,
|
|
1387
|
+
...entryPoint ? { entry_point: entryPoint } : {}
|
|
1388
|
+
});
|
|
1385
1389
|
};
|
|
1386
1390
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1387
1391
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -2002,15 +2006,17 @@ var getExperimentKeyFromNextData = (flagKey) => {
|
|
|
2002
2006
|
};
|
|
2003
2007
|
|
|
2004
2008
|
// src/utils/applePayExpressEligibility.ts
|
|
2005
|
-
var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
|
|
2006
|
-
var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
|
|
2007
2009
|
var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
|
|
2008
2010
|
|
|
2009
2011
|
// src/apple-pay-button.ts
|
|
2010
2012
|
var ENTRY_POINT_CONFIG = {
|
|
2011
2013
|
["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
|
|
2012
|
-
isEligible:
|
|
2013
|
-
experimentFlagKey
|
|
2014
|
+
isEligible: () => true
|
|
2015
|
+
// no experimentFlagKey → always-on after offer exclusions
|
|
2016
|
+
},
|
|
2017
|
+
["free_trial_banner" /* FREE_TRIAL_BANNER */]: {
|
|
2018
|
+
isEligible: () => true
|
|
2019
|
+
// Dual parity — no experimentFlagKey, no homepage gate here
|
|
2014
2020
|
},
|
|
2015
2021
|
["article_paywall" /* PAYWALL */]: {
|
|
2016
2022
|
isEligible: isEligibleForApplePayExpressPaywallExperiment,
|
|
@@ -2018,10 +2024,7 @@ var ENTRY_POINT_CONFIG = {
|
|
|
2018
2024
|
},
|
|
2019
2025
|
["article_regwall" /* REGWALL */]: {
|
|
2020
2026
|
isEligible: () => true,
|
|
2021
|
-
|
|
2022
|
-
},
|
|
2023
|
-
["free_trial_popup" /* FREE_TRIAL_POPUP */]: {
|
|
2024
|
-
isEligible: () => true
|
|
2027
|
+
enabled: false
|
|
2025
2028
|
}
|
|
2026
2029
|
};
|
|
2027
2030
|
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
@@ -2040,28 +2043,29 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2040
2043
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
2041
2044
|
}
|
|
2042
2045
|
/**
|
|
2043
|
-
* Creates and configures an ApplePayButton when the
|
|
2046
|
+
* Creates and configures an ApplePayButton when the entry point allows it.
|
|
2044
2047
|
*
|
|
2045
|
-
*
|
|
2046
|
-
*
|
|
2047
|
-
*
|
|
2048
|
-
* -
|
|
2048
|
+
* - `DUAL_OFFER_BANNER` (or omitted): always-on after offer exclusions —
|
|
2049
|
+
* no homepage/Safari gate here, no banners experiment read, and no banners
|
|
2050
|
+
* `$exposure`.
|
|
2051
|
+
* - `FREE_TRIAL_BANNER`: same always-on-after-exclusions gate as Dual; distinct
|
|
2052
|
+
* TEDL `entry_point` string (`free_trial_banner`) for wallet impression attribution.
|
|
2053
|
+
* - `PAYWALL`: experiment-gated via {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}
|
|
2054
|
+
* (`treatment` or QA URL param). The host must set up
|
|
2055
|
+
* `window.experimentIntegration` before calling for this entry point.
|
|
2056
|
+
* - `REGWALL`: inert — always returns null.
|
|
2049
2057
|
*
|
|
2050
|
-
*
|
|
2051
|
-
*
|
|
2052
|
-
*
|
|
2053
|
-
*
|
|
2054
|
-
*
|
|
2055
|
-
*
|
|
2056
|
-
* **Transition period:** the legacy `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param
|
|
2057
|
-
* gate is also evaluated as a fallback until all host apps have integrated
|
|
2058
|
-
* `window.experimentIntegration`. Once all consumers are migrated, the URL param
|
|
2059
|
-
* fallback will be removed.
|
|
2058
|
+
* **PAYWALL only — transition period:** the legacy
|
|
2059
|
+
* `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param can show the button without
|
|
2060
|
+
* treatment (and without inflating `$exposure`). For banners there is no
|
|
2061
|
+
* experiment gate; `BYPASS_APPLE_PAY_CHECKS` only skips device checks in
|
|
2062
|
+
* `isApplePayAvailable()` on mount.
|
|
2060
2063
|
*
|
|
2061
2064
|
* **Eligibility:**
|
|
2062
|
-
* - `DUAL_OFFER_BANNER` (or omitted):
|
|
2065
|
+
* - `DUAL_OFFER_BANNER` / `FREE_TRIAL_BANNER` (or omitted): always eligible at
|
|
2066
|
+
* this gate (homepage placement is host-owned; Safari/Apple is enforced
|
|
2067
|
+
* later by `isApplePayAvailable()` on mount)
|
|
2063
2068
|
* - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
|
|
2064
|
-
* - `REGWALL` / `FREE_TRIAL_POPUP`: no host-side placement gate
|
|
2065
2069
|
*
|
|
2066
2070
|
* @param offer - The offer to display in the Apple Pay flow.
|
|
2067
2071
|
* @param country - The user's country code.
|
|
@@ -2084,6 +2088,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2084
2088
|
}
|
|
2085
2089
|
const { isEligible: eligibilityCheck, experimentFlagKey } = config;
|
|
2086
2090
|
const isEligible = eligibilityCheck();
|
|
2091
|
+
if (config.enabled === false) {
|
|
2092
|
+
return null;
|
|
2093
|
+
}
|
|
2087
2094
|
if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
|
|
2088
2095
|
return null;
|
|
2089
2096
|
}
|
|
@@ -2228,9 +2235,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2228
2235
|
button.removeAttribute("aria-busy");
|
|
2229
2236
|
button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2230
2237
|
}
|
|
2231
|
-
this.getAnimations?.({ subtree: true }).forEach(
|
|
2232
|
-
(animation) => animation.cancel()
|
|
2233
|
-
);
|
|
2238
|
+
this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2234
2239
|
void this.offsetHeight;
|
|
2235
2240
|
this.style.display = "none";
|
|
2236
2241
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
@@ -2339,7 +2344,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2339
2344
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2340
2345
|
return;
|
|
2341
2346
|
}
|
|
2342
|
-
trackExpressWalletClick(
|
|
2347
|
+
trackExpressWalletClick(
|
|
2348
|
+
this.#offer.sku_id,
|
|
2349
|
+
this.#entryPoint ? { entryPoint: this.#entryPoint } : void 0
|
|
2350
|
+
);
|
|
2343
2351
|
ApplePayModal.define();
|
|
2344
2352
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2345
2353
|
modal.offer = this.#offer;
|
|
@@ -83,7 +83,9 @@ var apple_pay_modal_template_default = `<style>
|
|
|
83
83
|
left: 0;
|
|
84
84
|
width: 100%;
|
|
85
85
|
height: 100%;
|
|
86
|
-
|
|
86
|
+
/* Above acquisition DualOfferBanner (1000) and Engagement ribbon (96).
|
|
87
|
+
Was 97 for wall/ribbon hosts only; hosts without a ribbon clamp need this. */
|
|
88
|
+
z-index: 1100;
|
|
87
89
|
background: rgba(13, 13, 13, 0.7);
|
|
88
90
|
display: flex;
|
|
89
91
|
align-items: center;
|
|
@@ -83,7 +83,9 @@ var apple_pay_modal_template_default = `<style>
|
|
|
83
83
|
left: 0;
|
|
84
84
|
width: 100%;
|
|
85
85
|
height: 100%;
|
|
86
|
-
|
|
86
|
+
/* Above acquisition DualOfferBanner (1000) and Engagement ribbon (96).
|
|
87
|
+
Was 97 for wall/ribbon hosts only; hosts without a ribbon clamp need this. */
|
|
88
|
+
z-index: 1100;
|
|
87
89
|
background: rgba(13, 13, 13, 0.7);
|
|
88
90
|
display: flex;
|
|
89
91
|
align-items: center;
|
|
@@ -1299,7 +1301,6 @@ var redirectToCheckoutFallback = (params) => {
|
|
|
1299
1301
|
};
|
|
1300
1302
|
|
|
1301
1303
|
// src/constants.ts
|
|
1302
|
-
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
1303
1304
|
var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
1304
1305
|
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
1305
1306
|
CONTROL: "control",
|
|
@@ -1343,7 +1344,7 @@ var track = (action, extra) => {
|
|
|
1343
1344
|
...extra
|
|
1344
1345
|
});
|
|
1345
1346
|
};
|
|
1346
|
-
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey
|
|
1347
|
+
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey) => {
|
|
1347
1348
|
const isActiveVariant = variant === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || variant === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
1348
1349
|
if (!isActiveVariant) {
|
|
1349
1350
|
return;
|
|
@@ -1372,8 +1373,11 @@ var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
|
1372
1373
|
device: getDevice()
|
|
1373
1374
|
});
|
|
1374
1375
|
};
|
|
1375
|
-
var trackExpressWalletClick = (skuId) => {
|
|
1376
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1376
|
+
var trackExpressWalletClick = (skuId, { entryPoint } = {}) => {
|
|
1377
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1378
|
+
sku_id: skuId,
|
|
1379
|
+
...entryPoint ? { entry_point: entryPoint } : {}
|
|
1380
|
+
});
|
|
1377
1381
|
};
|
|
1378
1382
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1379
1383
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -1994,15 +1998,17 @@ var getExperimentKeyFromNextData = (flagKey) => {
|
|
|
1994
1998
|
};
|
|
1995
1999
|
|
|
1996
2000
|
// src/utils/applePayExpressEligibility.ts
|
|
1997
|
-
var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
|
|
1998
|
-
var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
|
|
1999
2001
|
var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
|
|
2000
2002
|
|
|
2001
2003
|
// src/apple-pay-button.ts
|
|
2002
2004
|
var ENTRY_POINT_CONFIG = {
|
|
2003
2005
|
["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
|
|
2004
|
-
isEligible:
|
|
2005
|
-
experimentFlagKey
|
|
2006
|
+
isEligible: () => true
|
|
2007
|
+
// no experimentFlagKey → always-on after offer exclusions
|
|
2008
|
+
},
|
|
2009
|
+
["free_trial_banner" /* FREE_TRIAL_BANNER */]: {
|
|
2010
|
+
isEligible: () => true
|
|
2011
|
+
// Dual parity — no experimentFlagKey, no homepage gate here
|
|
2006
2012
|
},
|
|
2007
2013
|
["article_paywall" /* PAYWALL */]: {
|
|
2008
2014
|
isEligible: isEligibleForApplePayExpressPaywallExperiment,
|
|
@@ -2010,10 +2016,7 @@ var ENTRY_POINT_CONFIG = {
|
|
|
2010
2016
|
},
|
|
2011
2017
|
["article_regwall" /* REGWALL */]: {
|
|
2012
2018
|
isEligible: () => true,
|
|
2013
|
-
|
|
2014
|
-
},
|
|
2015
|
-
["free_trial_popup" /* FREE_TRIAL_POPUP */]: {
|
|
2016
|
-
isEligible: () => true
|
|
2019
|
+
enabled: false
|
|
2017
2020
|
}
|
|
2018
2021
|
};
|
|
2019
2022
|
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
@@ -2032,28 +2035,29 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2032
2035
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
2033
2036
|
}
|
|
2034
2037
|
/**
|
|
2035
|
-
* Creates and configures an ApplePayButton when the
|
|
2038
|
+
* Creates and configures an ApplePayButton when the entry point allows it.
|
|
2036
2039
|
*
|
|
2037
|
-
*
|
|
2038
|
-
*
|
|
2039
|
-
*
|
|
2040
|
-
* -
|
|
2040
|
+
* - `DUAL_OFFER_BANNER` (or omitted): always-on after offer exclusions —
|
|
2041
|
+
* no homepage/Safari gate here, no banners experiment read, and no banners
|
|
2042
|
+
* `$exposure`.
|
|
2043
|
+
* - `FREE_TRIAL_BANNER`: same always-on-after-exclusions gate as Dual; distinct
|
|
2044
|
+
* TEDL `entry_point` string (`free_trial_banner`) for wallet impression attribution.
|
|
2045
|
+
* - `PAYWALL`: experiment-gated via {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}
|
|
2046
|
+
* (`treatment` or QA URL param). The host must set up
|
|
2047
|
+
* `window.experimentIntegration` before calling for this entry point.
|
|
2048
|
+
* - `REGWALL`: inert — always returns null.
|
|
2041
2049
|
*
|
|
2042
|
-
*
|
|
2043
|
-
*
|
|
2044
|
-
*
|
|
2045
|
-
*
|
|
2046
|
-
*
|
|
2047
|
-
*
|
|
2048
|
-
* **Transition period:** the legacy `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param
|
|
2049
|
-
* gate is also evaluated as a fallback until all host apps have integrated
|
|
2050
|
-
* `window.experimentIntegration`. Once all consumers are migrated, the URL param
|
|
2051
|
-
* fallback will be removed.
|
|
2050
|
+
* **PAYWALL only — transition period:** the legacy
|
|
2051
|
+
* `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param can show the button without
|
|
2052
|
+
* treatment (and without inflating `$exposure`). For banners there is no
|
|
2053
|
+
* experiment gate; `BYPASS_APPLE_PAY_CHECKS` only skips device checks in
|
|
2054
|
+
* `isApplePayAvailable()` on mount.
|
|
2052
2055
|
*
|
|
2053
2056
|
* **Eligibility:**
|
|
2054
|
-
* - `DUAL_OFFER_BANNER` (or omitted):
|
|
2057
|
+
* - `DUAL_OFFER_BANNER` / `FREE_TRIAL_BANNER` (or omitted): always eligible at
|
|
2058
|
+
* this gate (homepage placement is host-owned; Safari/Apple is enforced
|
|
2059
|
+
* later by `isApplePayAvailable()` on mount)
|
|
2055
2060
|
* - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
|
|
2056
|
-
* - `REGWALL` / `FREE_TRIAL_POPUP`: no host-side placement gate
|
|
2057
2061
|
*
|
|
2058
2062
|
* @param offer - The offer to display in the Apple Pay flow.
|
|
2059
2063
|
* @param country - The user's country code.
|
|
@@ -2076,6 +2080,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2076
2080
|
}
|
|
2077
2081
|
const { isEligible: eligibilityCheck, experimentFlagKey } = config;
|
|
2078
2082
|
const isEligible = eligibilityCheck();
|
|
2083
|
+
if (config.enabled === false) {
|
|
2084
|
+
return null;
|
|
2085
|
+
}
|
|
2079
2086
|
if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
|
|
2080
2087
|
return null;
|
|
2081
2088
|
}
|
|
@@ -2220,9 +2227,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2220
2227
|
button.removeAttribute("aria-busy");
|
|
2221
2228
|
button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2222
2229
|
}
|
|
2223
|
-
this.getAnimations?.({ subtree: true }).forEach(
|
|
2224
|
-
(animation) => animation.cancel()
|
|
2225
|
-
);
|
|
2230
|
+
this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2226
2231
|
void this.offsetHeight;
|
|
2227
2232
|
this.style.display = "none";
|
|
2228
2233
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
@@ -2331,7 +2336,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2331
2336
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2332
2337
|
return;
|
|
2333
2338
|
}
|
|
2334
|
-
trackExpressWalletClick(
|
|
2339
|
+
trackExpressWalletClick(
|
|
2340
|
+
this.#offer.sku_id,
|
|
2341
|
+
this.#entryPoint ? { entryPoint: this.#entryPoint } : void 0
|
|
2342
|
+
);
|
|
2335
2343
|
ApplePayModal.define();
|
|
2336
2344
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2337
2345
|
modal.offer = this.#offer;
|
package/dist/src/constants.d.ts
CHANGED
|
@@ -2,38 +2,26 @@ export declare enum ApplePayEntryPoint {
|
|
|
2
2
|
PAYWALL = "article_paywall",
|
|
3
3
|
REGWALL = "article_regwall",
|
|
4
4
|
DUAL_OFFER_BANNER = "dual_offer_banner",
|
|
5
|
-
|
|
6
|
-
FREE_TRIAL_POPUP = "free_trial_popup"
|
|
5
|
+
FREE_TRIAL_BANNER = "free_trial_banner"
|
|
7
6
|
}
|
|
8
|
-
/**
|
|
9
|
-
* Amplitude experiment key for Apple Pay Express Checkout on homepage banners
|
|
10
|
-
* (dual-offer banner) and article banner regwalls.
|
|
11
|
-
*
|
|
12
|
-
* This package reads the variant for this key internally via
|
|
13
|
-
* `window.experimentIntegration.getVariant()` — set up by the host page
|
|
14
|
-
* before `createIfEnabled` is called.
|
|
15
|
-
*
|
|
16
|
-
* Fail-closed: missing integration, missing key, `control`, or Amplitude fetch
|
|
17
|
-
* failure on the host → button is hidden (unless QA URL param is present).
|
|
18
|
-
*
|
|
19
|
-
* Must match the Feature experiment key in Amplitude and host app constants
|
|
20
|
-
* (Engagement / Insider / Podcasts).
|
|
21
|
-
*/
|
|
22
|
-
export declare const APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
23
7
|
/**
|
|
24
8
|
* Amplitude experiment key for Apple Pay Express Checkout on article paywalls
|
|
25
9
|
* (`ApplePayEntryPoint.PAYWALL`, e.g. single-offer-paywall / multi-offer paywall).
|
|
26
10
|
*
|
|
27
|
-
*
|
|
11
|
+
* Fail-closed when the variant is missing or not `treatment`; the QA URL param
|
|
12
|
+
* `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` can show the button without treatment.
|
|
28
13
|
* Eligibility for this flag ignores homepage and requires Safari/Apple device
|
|
29
14
|
* (plus `isApplePayAvailable` before `$exposure`).
|
|
15
|
+
*
|
|
16
|
+
* Must match the Feature experiment key in Amplitude and host app constants
|
|
17
|
+
* (Engagement / Insider / Podcasts) while those still bridge the experiment.
|
|
30
18
|
*/
|
|
31
19
|
export declare const APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
32
20
|
/**
|
|
33
21
|
* Known Amplitude experiment flag keys for Apple Pay Express Checkout.
|
|
34
22
|
* Narrowed so callers cannot pass an arbitrary typo'd string.
|
|
35
23
|
*/
|
|
36
|
-
export type ApplePayExperimentFlagKey = typeof
|
|
24
|
+
export type ApplePayExperimentFlagKey = typeof APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY;
|
|
37
25
|
/**
|
|
38
26
|
* Amplitude variant values for the Apple Pay Express Checkout experiment.
|
|
39
27
|
* CONTROL → button hidden (baseline)
|
package/dist/src/constants.js
CHANGED
|
@@ -3,17 +3,15 @@ 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["
|
|
6
|
+
ApplePayEntryPoint2["FREE_TRIAL_BANNER"] = "free_trial_banner";
|
|
7
7
|
return ApplePayEntryPoint2;
|
|
8
8
|
})(ApplePayEntryPoint || {});
|
|
9
|
-
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
10
9
|
var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
11
10
|
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
12
11
|
CONTROL: "control",
|
|
13
12
|
TREATMENT: "treatment"
|
|
14
13
|
};
|
|
15
14
|
export {
|
|
16
|
-
APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
|
|
17
15
|
APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY,
|
|
18
16
|
APPLE_PAY_EXPRESS_VARIANTS,
|
|
19
17
|
ApplePayEntryPoint
|
package/dist/src/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { ApplePayButton, APPLE_PAY_EXCLUDED_VARIANTS, } from './apple-pay-button
|
|
|
2
2
|
export { ApplePayModal } from './apple-pay-modal';
|
|
3
3
|
export { ensureApplePayLogoSymbol } from './apple-pay-logo';
|
|
4
4
|
export { configureApplePay } from './clients/payment-checkout/config';
|
|
5
|
-
export { ApplePayEntryPoint,
|
|
5
|
+
export { ApplePayEntryPoint, APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY, APPLE_PAY_EXPRESS_VARIANTS, } from './constants';
|
|
6
6
|
export type { ApplePayExperimentFlagKey } from './constants';
|
|
7
7
|
export type { ApplePayRuntimeConfig } from './clients/payment-checkout/config';
|
|
8
8
|
export type { Offer } from './types/offer.types';
|
package/dist/src/index.js
CHANGED
|
@@ -83,7 +83,9 @@ var apple_pay_modal_template_default = `<style>
|
|
|
83
83
|
left: 0;
|
|
84
84
|
width: 100%;
|
|
85
85
|
height: 100%;
|
|
86
|
-
|
|
86
|
+
/* Above acquisition DualOfferBanner (1000) and Engagement ribbon (96).
|
|
87
|
+
Was 97 for wall/ribbon hosts only; hosts without a ribbon clamp need this. */
|
|
88
|
+
z-index: 1100;
|
|
87
89
|
background: rgba(13, 13, 13, 0.7);
|
|
88
90
|
display: flex;
|
|
89
91
|
align-items: center;
|
|
@@ -1308,10 +1310,9 @@ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
|
|
|
1308
1310
|
ApplePayEntryPoint2["PAYWALL"] = "article_paywall";
|
|
1309
1311
|
ApplePayEntryPoint2["REGWALL"] = "article_regwall";
|
|
1310
1312
|
ApplePayEntryPoint2["DUAL_OFFER_BANNER"] = "dual_offer_banner";
|
|
1311
|
-
ApplePayEntryPoint2["
|
|
1313
|
+
ApplePayEntryPoint2["FREE_TRIAL_BANNER"] = "free_trial_banner";
|
|
1312
1314
|
return ApplePayEntryPoint2;
|
|
1313
1315
|
})(ApplePayEntryPoint || {});
|
|
1314
|
-
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
1315
1316
|
var APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-paywalls";
|
|
1316
1317
|
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
1317
1318
|
CONTROL: "control",
|
|
@@ -1355,7 +1356,7 @@ var track = (action, extra) => {
|
|
|
1355
1356
|
...extra
|
|
1356
1357
|
});
|
|
1357
1358
|
};
|
|
1358
|
-
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey
|
|
1359
|
+
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey) => {
|
|
1359
1360
|
const isActiveVariant = variant === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || variant === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
1360
1361
|
if (!isActiveVariant) {
|
|
1361
1362
|
return;
|
|
@@ -1384,8 +1385,11 @@ var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
|
1384
1385
|
device: getDevice()
|
|
1385
1386
|
});
|
|
1386
1387
|
};
|
|
1387
|
-
var trackExpressWalletClick = (skuId) => {
|
|
1388
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1388
|
+
var trackExpressWalletClick = (skuId, { entryPoint } = {}) => {
|
|
1389
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1390
|
+
sku_id: skuId,
|
|
1391
|
+
...entryPoint ? { entry_point: entryPoint } : {}
|
|
1392
|
+
});
|
|
1389
1393
|
};
|
|
1390
1394
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1391
1395
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -2006,15 +2010,17 @@ var getExperimentKeyFromNextData = (flagKey) => {
|
|
|
2006
2010
|
};
|
|
2007
2011
|
|
|
2008
2012
|
// src/utils/applePayExpressEligibility.ts
|
|
2009
|
-
var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
|
|
2010
|
-
var isEligibleForApplePayExpressExperiment = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
|
|
2011
2013
|
var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
|
|
2012
2014
|
|
|
2013
2015
|
// src/apple-pay-button.ts
|
|
2014
2016
|
var ENTRY_POINT_CONFIG = {
|
|
2015
2017
|
["dual_offer_banner" /* DUAL_OFFER_BANNER */]: {
|
|
2016
|
-
isEligible:
|
|
2017
|
-
experimentFlagKey
|
|
2018
|
+
isEligible: () => true
|
|
2019
|
+
// no experimentFlagKey → always-on after offer exclusions
|
|
2020
|
+
},
|
|
2021
|
+
["free_trial_banner" /* FREE_TRIAL_BANNER */]: {
|
|
2022
|
+
isEligible: () => true
|
|
2023
|
+
// Dual parity — no experimentFlagKey, no homepage gate here
|
|
2018
2024
|
},
|
|
2019
2025
|
["article_paywall" /* PAYWALL */]: {
|
|
2020
2026
|
isEligible: isEligibleForApplePayExpressPaywallExperiment,
|
|
@@ -2022,10 +2028,7 @@ var ENTRY_POINT_CONFIG = {
|
|
|
2022
2028
|
},
|
|
2023
2029
|
["article_regwall" /* REGWALL */]: {
|
|
2024
2030
|
isEligible: () => true,
|
|
2025
|
-
|
|
2026
|
-
},
|
|
2027
|
-
["free_trial_popup" /* FREE_TRIAL_POPUP */]: {
|
|
2028
|
-
isEligible: () => true
|
|
2031
|
+
enabled: false
|
|
2029
2032
|
}
|
|
2030
2033
|
};
|
|
2031
2034
|
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
@@ -2044,28 +2047,29 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2044
2047
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
2045
2048
|
}
|
|
2046
2049
|
/**
|
|
2047
|
-
* Creates and configures an ApplePayButton when the
|
|
2050
|
+
* Creates and configures an ApplePayButton when the entry point allows it.
|
|
2048
2051
|
*
|
|
2049
|
-
*
|
|
2050
|
-
*
|
|
2051
|
-
*
|
|
2052
|
-
* -
|
|
2052
|
+
* - `DUAL_OFFER_BANNER` (or omitted): always-on after offer exclusions —
|
|
2053
|
+
* no homepage/Safari gate here, no banners experiment read, and no banners
|
|
2054
|
+
* `$exposure`.
|
|
2055
|
+
* - `FREE_TRIAL_BANNER`: same always-on-after-exclusions gate as Dual; distinct
|
|
2056
|
+
* TEDL `entry_point` string (`free_trial_banner`) for wallet impression attribution.
|
|
2057
|
+
* - `PAYWALL`: experiment-gated via {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}
|
|
2058
|
+
* (`treatment` or QA URL param). The host must set up
|
|
2059
|
+
* `window.experimentIntegration` before calling for this entry point.
|
|
2060
|
+
* - `REGWALL`: inert — always returns null.
|
|
2053
2061
|
*
|
|
2054
|
-
*
|
|
2055
|
-
*
|
|
2056
|
-
*
|
|
2057
|
-
*
|
|
2058
|
-
*
|
|
2059
|
-
*
|
|
2060
|
-
* **Transition period:** the legacy `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param
|
|
2061
|
-
* gate is also evaluated as a fallback until all host apps have integrated
|
|
2062
|
-
* `window.experimentIntegration`. Once all consumers are migrated, the URL param
|
|
2063
|
-
* fallback will be removed.
|
|
2062
|
+
* **PAYWALL only — transition period:** the legacy
|
|
2063
|
+
* `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param can show the button without
|
|
2064
|
+
* treatment (and without inflating `$exposure`). For banners there is no
|
|
2065
|
+
* experiment gate; `BYPASS_APPLE_PAY_CHECKS` only skips device checks in
|
|
2066
|
+
* `isApplePayAvailable()` on mount.
|
|
2064
2067
|
*
|
|
2065
2068
|
* **Eligibility:**
|
|
2066
|
-
* - `DUAL_OFFER_BANNER` (or omitted):
|
|
2069
|
+
* - `DUAL_OFFER_BANNER` / `FREE_TRIAL_BANNER` (or omitted): always eligible at
|
|
2070
|
+
* this gate (homepage placement is host-owned; Safari/Apple is enforced
|
|
2071
|
+
* later by `isApplePayAvailable()` on mount)
|
|
2067
2072
|
* - `PAYWALL`: Safari/Apple device only (no homepage) — article paywalls
|
|
2068
|
-
* - `REGWALL` / `FREE_TRIAL_POPUP`: no host-side placement gate
|
|
2069
2073
|
*
|
|
2070
2074
|
* @param offer - The offer to display in the Apple Pay flow.
|
|
2071
2075
|
* @param country - The user's country code.
|
|
@@ -2088,6 +2092,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2088
2092
|
}
|
|
2089
2093
|
const { isEligible: eligibilityCheck, experimentFlagKey } = config;
|
|
2090
2094
|
const isEligible = eligibilityCheck();
|
|
2095
|
+
if (config.enabled === false) {
|
|
2096
|
+
return null;
|
|
2097
|
+
}
|
|
2091
2098
|
if (!hasUrlParamFlag && !bypassApplePayChecks() && !isEligible) {
|
|
2092
2099
|
return null;
|
|
2093
2100
|
}
|
|
@@ -2232,9 +2239,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2232
2239
|
button.removeAttribute("aria-busy");
|
|
2233
2240
|
button.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2234
2241
|
}
|
|
2235
|
-
this.getAnimations?.({ subtree: true }).forEach(
|
|
2236
|
-
(animation) => animation.cancel()
|
|
2237
|
-
);
|
|
2242
|
+
this.getAnimations?.({ subtree: true }).forEach((animation) => animation.cancel());
|
|
2238
2243
|
void this.offsetHeight;
|
|
2239
2244
|
this.style.display = "none";
|
|
2240
2245
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
@@ -2343,7 +2348,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2343
2348
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2344
2349
|
return;
|
|
2345
2350
|
}
|
|
2346
|
-
trackExpressWalletClick(
|
|
2351
|
+
trackExpressWalletClick(
|
|
2352
|
+
this.#offer.sku_id,
|
|
2353
|
+
this.#entryPoint ? { entryPoint: this.#entryPoint } : void 0
|
|
2354
|
+
);
|
|
2347
2355
|
ApplePayModal.define();
|
|
2348
2356
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2349
2357
|
modal.offer = this.#offer;
|
|
@@ -2435,7 +2443,6 @@ function defineApplePayElements() {
|
|
|
2435
2443
|
}
|
|
2436
2444
|
export {
|
|
2437
2445
|
APPLE_PAY_EXCLUDED_VARIANTS,
|
|
2438
|
-
APPLE_PAY_EXPRESS_EXPERIMENT_KEY,
|
|
2439
2446
|
APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY,
|
|
2440
2447
|
APPLE_PAY_EXPRESS_VARIANTS,
|
|
2441
2448
|
ApplePayButton,
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Host-side eligibility for Apple Pay Express
|
|
2
|
+
* Host-side placement eligibility helpers for Apple Pay Express.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* (
|
|
7
|
-
*
|
|
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).
|
|
8
9
|
*/
|
|
9
10
|
export declare const isApplePayExpressHomepage: (pathname?: string) => boolean;
|
|
10
11
|
/**
|
|
11
|
-
* Dual-offer homepage
|
|
12
|
-
* Anonymous is assumed because
|
|
13
|
-
* anonymous visitors.
|
|
12
|
+
* Dual-offer / Free Trial homepage banners: homepage + Safari/iPhone.
|
|
13
|
+
* Anonymous is assumed because these banners are only mounted for
|
|
14
|
+
* anonymous visitors. Not wired into createIfEnabled ENTRY_POINT_CONFIG.
|
|
14
15
|
*/
|
|
15
|
-
export declare const
|
|
16
|
+
export declare const isEligibleForApplePayExpressBanner: () => boolean;
|
|
16
17
|
/**
|
|
17
18
|
* Article paywalls (`ApplePayEntryPoint.PAYWALL`): Safari/Apple device only.
|
|
18
19
|
* Homepage targeting does not apply — paywalls render on article pages.
|
|
@@ -7,10 +7,10 @@ var isAppleDeviceOrSafari = () => {
|
|
|
7
7
|
|
|
8
8
|
// src/utils/applePayExpressEligibility.ts
|
|
9
9
|
var isApplePayExpressHomepage = (pathname = window.location.pathname) => pathname === "/";
|
|
10
|
-
var
|
|
10
|
+
var isEligibleForApplePayExpressBanner = () => isApplePayExpressHomepage() && isAppleDeviceOrSafari();
|
|
11
11
|
var isEligibleForApplePayExpressPaywallExperiment = () => isAppleDeviceOrSafari();
|
|
12
12
|
export {
|
|
13
13
|
isApplePayExpressHomepage,
|
|
14
|
-
|
|
14
|
+
isEligibleForApplePayExpressBanner,
|
|
15
15
|
isEligibleForApplePayExpressPaywallExperiment
|
|
16
16
|
};
|
|
@@ -57,14 +57,23 @@ export type ImpressionMetadata = {
|
|
|
57
57
|
* experiment_key from Engagement SSR (__NEXT_DATA__) when present for run
|
|
58
58
|
* attribution.
|
|
59
59
|
*
|
|
60
|
-
* @param flagKey - Amplitude flag_key.
|
|
61
|
-
*
|
|
60
|
+
* @param flagKey - Amplitude flag_key (required). Callers must pass an
|
|
61
|
+
* explicit key such as {@link APPLE_PAY_EXPRESS_PAYWALLS_EXPERIMENT_KEY}.
|
|
62
62
|
*/
|
|
63
|
-
export declare const trackApplePayExperimentExposure: (variant: string, experimentKey
|
|
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 */
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// src/constants.ts
|
|
2
|
-
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
|
|
3
2
|
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
4
3
|
CONTROL: "control",
|
|
5
4
|
TREATMENT: "treatment"
|
|
@@ -42,7 +41,7 @@ var track = (action, extra) => {
|
|
|
42
41
|
...extra
|
|
43
42
|
});
|
|
44
43
|
};
|
|
45
|
-
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey
|
|
44
|
+
var trackApplePayExperimentExposure = (variant, experimentKey, flagKey) => {
|
|
46
45
|
const isActiveVariant = variant === APPLE_PAY_EXPRESS_VARIANTS.CONTROL || variant === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
47
46
|
if (!isActiveVariant) {
|
|
48
47
|
return;
|
|
@@ -71,8 +70,11 @@ var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
|
71
70
|
device: getDevice()
|
|
72
71
|
});
|
|
73
72
|
};
|
|
74
|
-
var trackExpressWalletClick = (skuId) => {
|
|
75
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
73
|
+
var trackExpressWalletClick = (skuId, { entryPoint } = {}) => {
|
|
74
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
75
|
+
sku_id: skuId,
|
|
76
|
+
...entryPoint ? { entry_point: entryPoint } : {}
|
|
77
|
+
});
|
|
76
78
|
};
|
|
77
79
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
78
80
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
package/package.json
CHANGED