Skip to main content
currencycheckoutconversion

Local-Currency Checkout, Explained

Volmeris Team ·

A shopper in Manchester lands on your store from an ad, likes a product, and sees $24.99. Nothing is wrong with that price. But they now have to do three things before they can decide: work out roughly what that is in pounds, wonder whether their card will add a foreign-transaction fee, and guess whether the amount that eventually appears on their statement will be the one they agreed to.

Some of them do that work. The rest close the tab. This post is about removing that moment, and about the parts of doing it properly that are less obvious than they look.

Two different features that get called the same thing

“Multi-currency” is used for two things that are not equivalent.

Currency display converts the price for the shopper’s benefit and then charges in your currency anyway. The shopper sees £19.99, and their statement later shows a dollar amount converted at their bank’s rate plus whatever fee that bank charges. The number they agreed to and the number they paid are different. That is a support ticket, and sometimes a chargeback.

Local-currency charging puts the same currency on the product page, in the cart, and on the payment. The statement matches the checkout page.

Volmeris does the second. Stores sell in USD, GBP, EUR, CAD, AUD, or NZD, and Stripe takes payment in the same currency the shopper was shown.

How the shopper’s currency gets chosen

Three inputs, in priority order:

  1. A manual choice. If the shopper picks a currency from the switcher, that wins over everything and persists across visits. Someone travelling, or using a VPN, or who simply prefers to think in dollars, gets to say so.
  2. Geolocation. Otherwise the storefront looks up the visitor’s country and maps it to a supported currency — GB to GBP, the eurozone countries to EUR, CA/AU/NZ to their dollars.
  3. USD. Every failure path — lookup blocked, network error, unmapped country — falls back to USD rather than breaking the page. A shopper in a country we don’t map still gets a working store.

The resolved currency and rate are cached in the browser for the session (up to an hour) so that every product card, the cart, and the checkout agree with each other rather than each re-resolving independently.

The FX buffer, and why prices aren’t raw conversions

Exchange rates move. A store priced in USD and charging in GBP is quoting a price today that settles at tomorrow’s rate, and if the rate moves against you, the margin you calculated when you sourced the product silently shrinks.

The FX buffer handles this. It pads the conversion rate by a small percentage — 3% by default — before the price is computed. It is not a hidden fee so much as an acknowledgement that a fixed price in a floating market needs a tolerance band, the same way any exporter quotes with one.

Then the converted amount is snapped to a psychological ending, .99 by default:

$24.99  ×  rate 0.79  ×  1.03 buffer  =  £20.34…  →  £20.99

Two details worth knowing, because they change the numbers:

  • The ending is applied per unit, not per line. Three units at £20.99 is £62.97, not an ending applied once to the multiplied total. This matters for how discounts land, and it matches how the payment lines are constructed.
  • Shipping gets the buffer but no ending. Shipping of £4.87 should read as a real freight cost, not as a .99 price you invented — endings are a merchandising device and belong on merchandise. The discount line you see is the difference between the ended pre-discount total and the ended discounted total, so it inherits endings indirectly rather than being computed as a bare buffered amount itself.

The honest part: alignment, not arithmetic identity

Here is where we will be more careful than the marketing convention.

Prices in Volmeris are shown and charged in the shopper’s currency, and the FX buffer keeps display and charge aligned. We will not tell you they are provably identical to the penny in every case, because there is a real mechanism by which they can differ.

The storefront caches its exchange rate for up to an hour. The Worker that creates the payment session reads its own cached rate at checkout time. A cart that sits open across a cache boundary can therefore be priced against a rate that has since refreshed. The two rates come from the same source and are close; the buffer is sized so that ordinary movement is absorbed rather than eating your margin — but “close, with a deliberate tolerance” is the accurate description, and “penny-perfect” is not.

Downstream of the rate, the cart and the checkout run the same pricing code, so the way lines, discounts, and shipping are assembled into a total cannot disagree between the two — but they can still start from different inputs. Checkout always re-reads the current product price from the database rather than trusting what the cart sent, because the alternative is letting a shopper submit their own price. So if you change a product’s price while a shopper’s cart is open, checkout charges the new price, not the one the cart displayed. That’s a second, separate window from the rate one above, and it’s deliberate: it’s the same “never trust the client” rule that keeps the rate itself honest.

We would rather write that paragraph than have you discover it.

What it’s worth

Local-currency checkout is not a feature shoppers praise. It is a feature they never notice, which is the point — the price on the product page tracks the price in the cart tracks the price on the card statement, kept aligned by the FX buffer, and no arithmetic is asked of anyone. What you observe is the absence of a class of abandoned cart and a class of support email.

You can see it working on a live store: open ToyDeal and switch the currency. The prices change, the endings stay tidy, and the checkout charges in the currency the page showed.

Volmeris is free during the public beta — six currencies included, no configuration required.