Integrating Stripe Adaptive Pricing

Surface Stripe’s currency selector in a custom checkout built on checkout-sdk-js.

Stripe Adaptive Pricing lets shoppers pay in their local presentment currency while you continue to settle in your store’s default currency. Stripe detects the shopper’s currency, handles the FX conversion (24-hour rate guarantee), and renders a currency selector next to the payment methods. The shopper absorbs the FX spread; you pay 0% on conversion.

Stores using the BigCommerce reference checkout-js support Adaptive Pricing out of the box. If your storefront uses a custom checkout built on top of checkout-sdk-js, follow this guide to surface the feature to your shoppers.

Adaptive Pricing is available only on the Stripe OCS Checkout Session payment method (gateway: 'stripeocs', methodId: 'checkout_session'). The legacy Stripe optimized_checkout method does not support it.

How it works

When Adaptive Pricing is enabled for a store:

  1. The Stripe OCS payment method returns initializationData.adaptivePricingEnabled = true.
  2. The checkout-sdk passes adaptivePricing.allowed = true to Stripe Elements and mounts a CurrencySelectorElement into a host <div> that you render above your payment methods list.
  3. When the shopper picks a currency other than the store’s default, Stripe re-fetches the Payment Element in that currency, and the checkout-sdk flips paymentProviderCustomer.isCustomerCurrencySelected to true. The cart total is recalculated in the presentment currency.
  4. Your custom checkout listens for that flag and narrows the payment methods list to only the Stripe OCS Checkout Session method, because other gateways cannot settle in the presentment currency.
  5. On submit, the order is created in the presentment currency and Stripe settles the funds in your account’s default currency.

Requirements

  • Your store has the Stripe OCS Checkout Session payment method enabled.
  • A store administrator has enabled the Adaptive Pricing toggle for Stripe in the store control panel under Settings → Payments.
  • Your custom checkout uses @bigcommerce/checkout-sdk version 1.948.1 or later.
  • The Stripe OCS Checkout Session is already initialized in your payment step. See Getting started with Checkout SDK if you have not integrated Stripe OCS yet.

Check that Adaptive Pricing is enabled (Optional)

Adaptive Pricing is gated per store via the initializationData.adaptivePricingEnabled flag returned with the Stripe OCS payment method. You do not need to check this flag in your checkout code. The SDK reads it internally and only mounts the currency selector when the flag is true; if the flag is false, passing currencySelectorContainerId is a no-op and rendering the host container has no visible effect.

The BigCommerce reference checkout follows this pattern — it always renders the container and always passes currencySelectorContainerId, regardless of whether Adaptive Pricing is enabled for the store.

Read the flag explicitly only when you want to conditionally render surrounding UI (for example, a heading or helper text that only makes sense when the selector is visible):

Check whether Adaptive Pricing is enabled
const paymentMethod = checkoutService
.getState().data
.getPaymentMethod('checkout_session', 'stripeocs');
const isAdaptivePricingEnabled = Boolean(
paymentMethod?.initializationData?.adaptivePricingEnabled,
);

Integration steps

Step 1: Render the currency selector container

Add an empty container element above your payment methods list. Stripe will mount the currency selector into this <div>. The id is yours to choose, but it must be unique on the page and present in the DOM before you initialize the payment step.

Currency selector host container
<div id="stripe-currency-selector"></div>
<!-- your payment methods list renders below -->

Place the container above the payment methods list, so the shopper sees the currency selector before choosing a payment method.

See the Checkout JS repository for the reference implementation, introduced in PR #2944.

Step 2: Initialize the payment method with currencySelectorContainerId

Pass currencySelectorContainerId in the stripeocs options when you call checkoutService.initializePayment. The SDK uses this id to mount the Stripe CurrencySelectorElement.

Initialize Stripe OCS with the currency selector
await checkoutService.initializePayment({
gateway: 'stripeocs',
methodId: 'checkout_session',
stripeocs: {
containerId: 'stripe-payment-element',
currencySelectorContainerId: 'stripe-currency-selector',
appearance: {
// see Step 3
},
render: () => {
// your render callback
},
onError: (error) => {
// surface the error in your UI
},
},
});

You can always pass currencySelectorContainerId — when Adaptive Pricing is not enabled for the store, the SDK ignores it and the host container stays empty. The one constraint is that when the flag is enabled, currencySelectorContainerId must be set; otherwise the SDK throws a NotInitializedError. Always passing it (and always rendering the container) is the simplest correct pattern.

See StripeOCSPaymentMethod.tsx in the Checkout JS repository for the reference implementation (PR #2949). The corresponding SDK changes landed in checkout-sdk-js PR #3218.

Step 3: Style the currency selector to match your storefront

The currency selector is a Stripe Element, so it is styled through the Stripe Appearance API. Pass the same appearance object you use for the Payment Element; Stripe applies it to the selector too.

Pass an appearance object
stripeocs: {
containerId: 'stripe-payment-element',
currencySelectorContainerId: 'stripe-currency-selector',
appearance: {
variables: {
colorPrimary: '#0066ff',
colorText: '#1a1a1a',
colorBackground: '#ffffff',
borderRadius: '4px',
fontFamily: 'Inter, system-ui, sans-serif',
},
rules: {
'.ToggleItem': {
border: '1px solid #d4d4d8',
},
'.ToggleItem--selected': {
borderColor: '#0066ff',
color: '#0066ff',
},
},
},
// ...
}

The .ToggleItem and .ToggleItem--selected rules above target the currency selector specifically. See Stripe’s supported CSS selectors for the full list.

For an example of how to derive the appearance object from the active BigCommerce storefront theme, see getStripeOCSStyles.ts in the Checkout JS repository (PR #3009).

Step 4: React to currency changes

When the shopper picks a currency other than the store’s default, the SDK calls updatePaymentProviderCustomer with isCustomerCurrencySelected: true and the selected currency code. Subscribe to checkout state to react to that change.

Subscribe to currency selection changes
const unsubscribe = checkoutService.subscribe((state) => {
const providerCustomer = state.data.getPaymentProviderCustomer();
const isPresentmentCurrencyActive = Boolean(
providerCustomer?.isCustomerCurrencySelected,
);
const presentmentCurrency = providerCustomer?.customerCurrency;
// Re-render your payment methods list when this changes.
updatePaymentMethodsUi({ isPresentmentCurrencyActive, presentmentCurrency });
});

Remember to call the returned unsubscribe function when your component unmounts.

Step 5: Filter the payment methods list when a non-store-default currency is active

While isCustomerCurrencySelected is true, your checkout must hide every payment method other than Stripe OCS Checkout Session. No other gateway in the BigCommerce checkout can settle a transaction in the shopper’s presentment currency, and letting the shopper pick one would cause the payment to fail at submit time.

Filter payment methods by Adaptive Pricing state
const visiblePaymentMethods = paymentMethods.filter((method) => {
if (!isPresentmentCurrencyActive) {
return true;
}
return method.gateway === 'stripeocs' && method.id === 'checkout_session';
});

When the shopper switches back to the store’s default currency, the SDK sets isCustomerCurrencySelected to false and your full payment methods list should reappear.

The reference checkout implements this filter as a dedicated stripeMethodsFiltering function — see stripeMethodsFiltering.ts in the Checkout JS repository (PR #2948).

Step 6: De-initialize on unmount

Call checkoutService.deinitializePayment when the payment step is closed or your component unmounts. The SDK unmounts and destroys the currency selector along with the Payment Element.

De-initialize Stripe OCS
await checkoutService.deinitializePayment({
gateway: 'stripeocs',
methodId: 'checkout_session',
});

Testing your integration

  • Use one of Stripe’s test currencies to confirm that the selector renders and the totals recalculate.
  • In a sandbox store, toggle Adaptive Pricing off in the control panel and reload the checkout. The selector should disappear and your normal payment methods list should render.
  • Switch to a currency other than the store’s default in the selector and confirm that only the Stripe OCS Checkout Session method remains in your UI, then switch back and confirm that other methods reappear.
  • Place a test order in a currency other than the store’s default and confirm that the order in the BigCommerce control panel shows the presentment currency, while your Stripe dashboard shows the settled amount in your account currency.

Troubleshooting

The currency selector does not appear. Check that all three preconditions are met: the store has the Adaptive Pricing toggle on, initializationData.adaptivePricingEnabled is true for the checkout_session method, and the host <div> referenced by currencySelectorContainerId exists in the DOM before initializePayment is called.

NotInitializedError is thrown during initializePayment. This usually means adaptivePricingEnabled is true but you did not pass currencySelectorContainerId. Set the option whenever you call initializePayment for stripeocs / checkout_session.

Other payment methods stay visible after the shopper switches to a currency other than the store’s default, or do not come back after switching to the store’s default currency. Your payment methods list is not reacting to currency changes. Confirm that you have subscribed to checkoutService.subscribe and that your filter reads paymentProviderCustomer.isCustomerCurrencySelected on every render (see Steps 4 and 5). When the flag is true, your UI must show only the Stripe OCS Checkout Session method; when it flips back to false, your full payment methods list must be restored.