If your online store only shows prices in one currency, you are leaving money on the table. International shoppers who cannot see prices in their own currency are far more likely to abandon their cart.

Why Multi-Currency Pricing Matters

How Multi-Currency Pricing Works

  1. Detect the customer's location or preferred currency.
  2. Fetch current exchange rates from a reliable API.
  3. Convert your base prices into the target currency.
  4. Display the converted price with proper formatting.
  5. Handle checkout in either your base currency or the customer's local currency.

Step 1: Detect the Customer's Location and Currency

GeoIP Detection

Use the customer's IP address to determine their country. Services like MaxMind GeoLite2 or Cloudflare's CF-IPCountry header make this simple.

Manual Currency Selector

Always give customers the option to override automatic detection.

// Map country code to currency
const countryCurrencyMap = {
  US: 'USD', GB: 'GBP', DE: 'EUR', FR: 'EUR',
  JP: 'JPY', CA: 'CAD', AU: 'AUD', IN: 'INR',
  BR: 'BRL', MX: 'MXN', CN: 'CNY', KR: 'KRW'
};

function getCurrencyFromCountry(countryCode) {
  return countryCurrencyMap[countryCode] || 'USD';
}

Step 2: Fetch Exchange Rates from an API

Exchange Rate API is an excellent choice for e-commerce. It provides mid-market rates for 160+ currencies, updates every 60 seconds, and offers a free tier.

// Fetch exchange rates from Exchange Rate API
const API_KEY = 'your_api_key_here';

async function getExchangeRates(baseCurrency = 'USD') {
  const response = await fetch(
    `https://exchange-rateapi.com/api/v1/rates?base=${baseCurrency}`,
    { headers: { 'Authorization': `Bearer ${API_KEY}` } }
  );
  const data = await response.json();
  return data.rates; // { EUR: 0.9178, GBP: 0.7892, JPY: 149.53, ... }
}

Here is a simple caching layer:

// Simple in-memory cache for exchange rates
let cachedRates = null;
let cacheTimestamp = 0;
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

async function getRates(baseCurrency = 'USD') {
  const now = Date.now();
  if (cachedRates && (now - cacheTimestamp) < CACHE_TTL) {
    return cachedRates;
  }
  cachedRates = await getExchangeRates(baseCurrency);
  cacheTimestamp = now;
  return cachedRates;
}

Step 3: Convert and Display Prices

function convertAndFormat(priceInBase, targetCurrency, rates) {
  const converted = priceInBase * rates[targetCurrency];
  return new Intl.NumberFormat(undefined, {
    style: 'currency',
    currency: targetCurrency,
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  }).format(converted);
}

// Usage
const rates = await getRates('USD');
console.log(convertAndFormat(49.99, 'EUR', rates)); // "€45.89"
console.log(convertAndFormat(49.99, 'JPY', rates)); // "¥7,474"

Step 4: Handle Checkout and Payment

Option A: Display in Local Currency, Charge in Base Currency

Show the converted price throughout browsing, but charge in your base currency. Simpler to implement.

Option B: Charge in the Customer's Local Currency

Use your payment processor's multi-currency settlement feature. Stripe, PayPal, and Adyen all support this.

FactorOption A (Display Only)Option B (Charge Local)
Implementation effortLowMedium-High
Customer experienceGoodExcellent
Currency riskOn customerOn merchant
Recommended forGetting started quicklyScaling international sales

Common Pitfalls to Avoid

Rounding Errors

Always round after the final conversion, not during intermediate calculations.

Stale Exchange Rates

If your cache expires and the API is temporarily unreachable, serve the stale rates rather than showing an error.

Price Anchoring Issues

Consider adding a small buffer (1-3% markup on the mid-market rate) to absorb minor fluctuations so prices feel more stable.

Platform-Specific Tips

Shopify

Shopify Markets handles multi-currency natively. For more control over rates, integrate with Exchange Rate API through a custom app.

WooCommerce

Use the WPML WooCommerce Multilingual plugin and customize the rate source to pull from Exchange Rate API.

Custom Stores (Node.js, React, Next.js)

// Next.js API route example
// pages/api/prices.js
import { getRates } from '../../lib/rates';

export default async function handler(req, res) {
  const { currency = 'USD' } = req.query;
  const rates = await getRates('USD');
  const rate = rates[currency] || 1;

  const products = getProducts().map(product => ({
    ...product,
    displayPrice: formatPrice(product.basePrice * rate, currency),
    rawPrice: Math.round(product.basePrice * rate * 100) / 100
  }));

  res.json({ products, currency, rate });
}

Frequently Asked Questions

Does showing prices in local currency increase conversions?

Yes. Studies show 92% of shoppers prefer to see prices in their local currency, and multi-currency stores see 12-15% higher conversion rates.

How do I get exchange rates for my e-commerce store?

Use an exchange rate API like Exchange Rate API to fetch real-time mid-market rates. Rates update every 60 seconds for 160+ currencies.

Should I use mid-market or retail exchange rates for pricing?

Use mid-market rates as your baseline, then add a small markup (1-3%) to cover currency fluctuation risk.

Add live rates to your store

npm install @exchangerateapi/sdk

Power Your Store with Real-Time Rates

160+ currencies, 60-second updates, free tier with no credit card. Built for e-commerce.

Get Your Free API Key →

Related Articles