Skip to main content
Apple Pay and Google Pay are payment options on your checkout. They work with both NMI and Stripe merchants. No separate merchant account is required. Card checkout remains available if a wallet is not shown or the customer cancels.

Overview

  • Apple Pay - Appears on Safari (macOS and iOS) when the customer has Apple Pay set up. Setup depends on your gateway (see below).
  • Google Pay - Appears on supported browsers when a Google Pay wallet is available. With NMI it appears on Android devices only. With Stripe it can also appear on desktop Chrome.
  • Both options appear on the checkout page only. By default they render inside <checkout-cc-panel>, or you can place them anywhere on the page with <checkout-wallet />.

How to configure / enable

Setup differs by gateway. Choose your gateway below.

Stripe

Google Pay (Stripe)

No configuration is required beyond domain registration (see Apple Pay step below). Google Pay appears automatically on checkout when the customer has a Google Pay wallet. With Stripe, Google Pay can appear on desktop Chrome in addition to Android devices.

Apple Pay (Stripe)

Stripe handles Apple’s merchant validation behind the scenes. You do not need to create an Apple Merchant ID, CSR, or host a .well-known verification file. Follow these steps: Step 1: Make sure your Stripe account is in live mode
Apple Pay only works with live Stripe API keys. If your Stripe merchant is using test-mode keys, Apple Pay will not appear - canMakePayment() returns null and the button is silently hidden. Switch to live mode in the Stripe Dashboard and use your live publishable key on the checkout domain.
Step 2: Register your checkout domain(s) with Stripe
  1. In the Stripe Dashboard, make sure you are in live mode (toggle at the top of the dashboard).
  2. Go to SettingsPayment method domains.
  3. Click Add a new domain.
  4. Enter the exact domain customers use at checkout (e.g. checkout.yourstore.com).
  5. Click Save and continue.
  6. Repeat for any additional domains or subdomains (including www).
Domains registered in live mode are automatically available in sandbox/test mode as well. For local testing, use a tool like ngrok to get an HTTPS domain and register that. However, Apple Pay itself still requires live keys to appear on supported devices.
After registering with live keys, Apple Pay appears on checkout when the customer uses Safari on macOS or iOS and has Apple Pay configured. No verification file is needed - Stripe takes care of it. For more details, see Stripe’s domain registration guide and Apple Pay on the web.

NMI

Google Pay (NMI)

No configuration is required.
  1. Ensure the domain uses an NMI merchant.
  2. Ensure that merchant uses tokenization (Collect.js): in the merchant settings, tokenization mode should be Collect.js and the public / tokenization key should be set.
  3. Assign that NMI merchant to your checkout domain under SettingsDomainsEdit DomainMerchant.
Google Pay appears automatically on checkout when the customer is on an Android device with a supported browser (Chrome). It does not appear on desktop browsers.

Apple Pay (NMI)

Prerequisites: NMI merchant with tokenization (Collect.js), and the checkout domain linked to that merchant (as above). Step 1: Enable Apple Pay in NMI
  1. Log in to the NMI Merchant Portal.
  2. Go to SettingsApple Pay.
  3. Enable Apple Pay for your account (if your processor supports it).
Step 2: Register your checkout domain(s) with NMI NMI must have a list of domains that are allowed to show Apple Pay. Use the same domain(s) that serve your checkout in ElasticFunnels (e.g. the domain you set under SettingsDomains).
  • In the NMI Merchant Portal, add your checkout domain(s) to the Apple Pay allowed list (see NMI’s Apple Pay / domain registration section).
  • If ElasticFunnels later adds an in-app “Register domains” action for your NMI merchant, you can use that to sync your linked domains; otherwise configure the list in NMI’s portal.
Step 3: Apple domain verification Apple requires a verification file on your checkout domain. NMI provides this file.
  1. Download the domain verification file from NMI (in the NMI Merchant Portal under the Apple Pay settings, or from Apple’s developer resources as NMI directs you).
  2. Host it at:
    https://<your-checkout-domain>/.well-known/apple-developer-merchantid-domain-association
    Replace <your-checkout-domain> with the exact domain customers use at checkout (e.g. checkout.yourstore.com).
  3. Ensure the file is publicly accessible over HTTPS. Recommended: In the app, go to Domains → edit the checkout domain → Apple Pay tab, and paste the exact contents of the verification file. The offer site will then serve it at /.well-known/apple-developer-merchantid-domain-association for that domain. Alternatively, you can set the env var APPLE_PAY_DOMAIN_VERIFICATION_CONTENT on the offer server as a fallback (same content for all domains on that server). If neither is set, the path returns 404 and you must host the file elsewhere.
After all three steps, Apple Pay can appear on checkout when the customer uses Safari on macOS or iOS and has Apple Pay configured.

Placement options

There are three ways to include Apple Pay / Google Pay on your checkout page:

Default - wallet tab inside the card panel

On an HTTPS page with an NMI or Stripe merchant, the panel renders Apple Pay as a radio tab alongside Card (and PayPal / Klarna when configured). The tab relabels itself to Google Pay if Google Pay is detected instead. The older inline layout - wallet buttons above the card fields with an or pay with card divider - is only used as a fallback when the tab layout is unavailable (non-HTTPS page, an unsupported gateway, or an #applePay container already on the page from <checkout-wallet>).

Standalone - wallet buttons anywhere on the page

Use <checkout-wallet /> to place the wallet buttons wherever you want, and disable them inside the card panel with data-applepay="false":
This renders <div class="ef-wallet-standalone"> containing both the #applePay and #googlePay containers. Because the panel skips its own wallet tab whenever an #applePay element already exists, adding <checkout-wallet> is enough on its own - but data-applepay="false" keeps the intent explicit. Both attributes are plain attributes, not data- prefixed. The tag may be written self-closing (<checkout-wallet />) or with an explicit closing tag.
<checkout-apple-pay /> is the legacy single-wallet version of this tag. It still works and accepts force="true", but it only ever renders the Apple Pay container. Prefer <checkout-wallet /> for new pages.

Disable wallet buttons in the card panel

Apple Pay is not rendered inside the panel.
data-applepay="false" does not always suppress Google Pay. On NMI merchants, a #googlePay container is still injected into the panel when the visitor is on an Android device, so a Google Pay button can still appear. On Stripe merchants both wallets share the same mount point, so data-applepay="false" disables both.
data-applepay-layout is read by the client-side panel, but the server-side tag expander does not forward it: <checkout-cc-panel> is rewritten into a <div class="checkout-cc-panel"> carrying only data-gateway, data-accepted-cards, data-applepay and data-applepay-force. Writing data-applepay-layout="separated" on the tag therefore has no effect - use <checkout-wallet /> for an above-the-panel wallet instead.

Conditional display

Two scope variables drive wallet-aware layouts: Use them to show or hide parts of your checkout layout:
<checkout-personal-details> generates its name / email / phone inputs from data-fields - you do not write them yourself. Any HTML you place inside the tag is preserved, but it is appended after the generated fields, not used in place of them. The same applies to <checkout-details> for shipping and billing. <checkout-cc-panel> discards its children entirely.
checkout.wallet_available starts as { applePay: false, googlePay: false } and is only updated after the payment library loads and detects wallet support (NMI Collect.js or Stripe.js). This can take 1-2 seconds after page load, so a template-if on it will briefly evaluate false on first paint. Prefer checkout.wallet_visible (or <checkout-wallet force="true">) when you need the layout stable immediately.

Example: wallet-first checkout

This layout shows the wallet buttons prominently at the top, with the card form below:

How wallet payment works

When a customer taps the Apple Pay or Google Pay button:
  1. The native wallet sheet appears (Face ID / Touch ID for Apple Pay, or Google Pay authentication).
  2. The wallet provides the payment token and contact data (name, address, email, phone).
  3. The system automatically fills the checkout form fields with the wallet data.
  4. The form auto-submits. No further action from the customer.
This means the customer can skip filling out the checkout form entirely. The wallet provides everything needed for the payment. Personal, shipping and billing form fields are only filled when they are currently empty - the one exception is shipping_country / billing_country, which are always overwritten with the wallet’s value.

Wallet contact field auto-detection

This auto-detection applies to NMI / Collect.js checkouts only. On Stripe, the payment request is created with requestPayerName, requestPayerEmail and requestShipping always enabled and no phone request, regardless of which fields are on the page.
On NMI, the wallet detects which contact fields to request based on which checkout fields are on the page. No explicit configuration is needed. Only the first-name variants are checked. A page carrying last_name without any *_first_name field does not trigger the name request. Digital product example: A checkout page with only email and a payment panel (no name or address fields) causes Apple Pay to request only the customer’s email. This is ideal for digital goods where shipping details are unnecessary.

Subscriptions and recurring payments

When a customer purchases a subscription using Apple Pay or Google Pay, the system stores the payment method for future use:
  • NMI: A customer vault entry is created during the initial charge. All subsequent subscription charges (renewals, rebills) use this vault entry server-to-server. Requires Customer Token Vault — see below.
  • Stripe: The PaymentMethod is saved to the Stripe customer with setup_future_usage: 'off_session'. All subsequent charges use this stored payment method server-to-server.
No additional customer interaction is needed for renewals. The subscription billing schedule is managed entirely on the server. The wallet token is consumed on the first charge, and the stored method handles everything after that.
NMI wallet subscriptions need Customer Token Vault switched on before they will renew.Apple Pay hands the gateway a single-use device token (DPAN). That token is bound to the cryptogram issued for that one transaction — it cannot be charged again on its own. The initial payment therefore succeeds while every renewal declines, which usually shows up weeks later as a cohort of failed rebills rather than an obvious error at checkout.For renewals to work, the merchant account needs Customer Token Vault / network tokenisation enabled at NMI so the gateway can store a reusable merchant token (MPAN) instead of the device token. This is an opt-in feature — ask your NMI representative or ISO to activate it. ElasticFunnels then declares the transaction as recurring on the initial authorization so Apple issues a reusable credential.Verify with one real renewal before you scale spend on a wallet subscription offer. Take a live Apple Pay subscription and force a rebill. A green toggle in the merchant settings is not sufficient proof on its own — the check degrades open, so it can report success on an account that has not had network tokenisation activated.

Checking whether a wallet subscription will renew

If the first charge succeeds but no customer_vault_id is recorded, the subscription will not renew. Fix the vault configuration before sending traffic rather than after.

One-click upsells

When a customer pays with Apple Pay or Google Pay on the main checkout, the payment method is stored for reuse. Subsequent one-click upsell charges on the same funnel use this stored method server-to-server. No additional customer interaction is needed. The customer sees upsell pages and clicks “Yes, add this” as usual; the charge happens instantly. This works the same as card-based one-click upsells for both NMI and Stripe.

Billing address handling

When a customer pays with Apple Pay or Google Pay, the wallet provides the correct billing address associated with the card. The wallet’s billing values always overwrite the internal checkout.customer.billing_* scope object, so the address used for verification (AVS) comes from the wallet rather than from anything typed earlier. This prevents address verification mismatches and declined payments. No configuration is needed. This is handled automatically.
The scope object and the form inputs behave differently. checkout.customer.billing_* is always replaced with the wallet address, but the corresponding form fields are only overwritten when they were empty (billing_country and shipping_country excepted - those are always replaced). On a page that shows editable billing address inputs above the wallet button, a value the customer already typed is what gets submitted.
For non-US addresses, Apple Pay may not return a state/region value (many countries don’t use states in their address format). The checkout validation automatically skips state validation for wallet payments, so this does not cause errors.

Troubleshooting

Apple Pay button does not show

Stripe:
  • Confirm you are using live API keys. Apple Pay does not appear when the Stripe merchant is in test mode. This is the most common cause of Apple Pay not showing with Stripe. Switch to live mode in the Stripe Dashboard and ensure your checkout domain is using the live publishable key.
  • Confirm the domain is registered in the Stripe Dashboard under Payment method domains and shows as Enabled. Make sure you registered the domain in live mode.
  • Check that the customer is on Safari (macOS or iOS) and the page is served over HTTPS.
  • No .well-known verification file is needed for Stripe. Stripe handles merchant validation. If you previously used NMI and have a verification file on the domain, it does not interfere.
  • If using <checkout-wallet /> or <checkout-apple-pay />, make sure the tag is on the page.
NMI:
  • Confirm the domain uses an NMI merchant with Collect.js (tokenization) and a public/tokenization key.
  • Check that the customer is on Safari (macOS or iOS) and the page is served over HTTPS.
  • Confirm the domain is registered with NMI for Apple Pay and that the Apple verification file is reachable at https://<your-checkout-domain>/.well-known/apple-developer-merchantid-domain-association.
  • If using <checkout-wallet /> (or legacy <checkout-apple-pay />), make sure the tag is on the page (it renders a container; the button appears inside it when supported).
  • If you set data-applepay-layout on <checkout-cc-panel> and nothing changed, that is expected - the attribute is dropped during server-side expansion. Use <checkout-wallet /> instead.

Google Pay button does not show

  • NMI: Google Pay only appears on Android devices. It does not show on desktop Chrome or other desktop browsers. Confirm the domain uses an NMI merchant with Collect.js (tokenization) and a public/tokenization key.
  • Stripe: Google Pay can appear on desktop Chrome as well as Android. Confirm the domain is registered under Payment method domains.

Verification file not found (NMI / Apple Pay)

  • Ensure the file is at the exact .well-known path and that the domain matches the one used at checkout.
  • If you use a subdomain for checkout, that subdomain must be the one registered with NMI and Apple and must serve the verification file.
  • This does not apply to Stripe - Stripe handles verification without a hosted file.

Other issues

  • Wallet payment cancelled or failed - The customer can pay with card instead; the card form remains available. No page reload is required.
  • State/region error on wallet payment - This should be handled automatically. If you see state validation errors after a wallet payment, ensure you are on the latest version of the checkout plugin.
  • Subscription charges fail after initial wallet purchase - Verify the payment created a stored payment method. For NMI, check the transaction record for a customer_vault_id. For Stripe, check for a stored payment_method on the customer.
  • One-click upsell charges fail after wallet payment - Same as above - ensure the payment method was stored during the initial charge.
For more on NMI and Apple Pay, see NMI’s documentation and Digital Wallet Setup. For Stripe, see Stripe’s Apple Pay guide and domain registration.