Home Documentation Playground Pricing API Status Blog About FAQ Support

How to Add Real-Time Exchange Rates to Your Shopify Store

Reviewed by Madhushan, Fintech Developer — May 2026
Online shopping cart concept

Selling internationally on Shopify sounds straightforward until you realize your customers in Germany see prices that are 3% higher than the mid-market rate, your Australian shoppers get stale conversions from yesterday, and your checkout abandonment rate for international orders is double your domestic rate.

Shopify Markets handles basic multi-currency display, but it has limitations that serious international sellers hit quickly. Integrating an exchange rate API Shopify solution gives you control over the rates your customers see, when those rates update, and how you handle rounding and pricing psychology. This guide covers the limitations of Shopify's built-in tools, three integration approaches (Liquid, Shopify Functions, and theme app extensions), and practical code you can deploy today.

What Shopify Markets Gets Right (and Wrong)

Shopify Markets, introduced in 2022, lets you assign markets to countries and display prices in local currencies. On the surface it works well. Under the hood, there are issues:

What works:

What does not:

For stores doing under $10,000/month in international sales, Shopify Markets is fine. For stores where international revenue is material, you need an exchange rate API Shopify integration to take control.

Three Integration Approaches

Approach 1: Server-Side Conversion with a Middleware App

This is the most robust approach. You build a small server (or use a serverless function) that sits between your Shopify admin and your storefront.

How it works:

  1. A scheduled job fetches current rates from the API every 60 seconds.
  2. Rates are stored in a cache (Redis, or even a simple JSON file on a CDN).
  3. Your Shopify theme reads the cached rates and converts prices client-side, or your middleware writes converted prices to Shopify metafields.

Fetching rates:

// rates-updater.js (runs on a cron or serverless schedule)
const API_KEY = process.env.ALLRATESTODAY_API_KEY;

async function updateRates() {
  const response = await fetch(
    "https://api.allratestoday.com/v1/latest?base=USD&symbols=EUR,GBP,JPY,AUD,CAD,CHF,SEK,NOK,DKK",
    { headers: { "Authorization": "Bearer " + API_KEY } }
  );
  const data = await response.json();

  // Store in your cache layer
  await redis.set("fx_rates", JSON.stringify({
    rates: data.rates,
    updated_at: data.timestamp
  }), "EX", 120); // Expire after 120 seconds
}

Writing to Shopify metafields:

const shopify = new Shopify.Clients.Rest(shop, accessToken);

// Store rates as a shop-level metafield
await shopify.post({
  path: "metafields",
  data: {
    metafield: {
      namespace: "fx_rates",
      key: "current",
      value: JSON.stringify(rates),
      type: "json"
    }
  }
});

This approach gives you full control and works with any Shopify plan.

Approach 2: Liquid Template Snippets

If you want a lighter solution without a separate server, you can use Shopify metafields populated via the Admin API and read them in Liquid templates.

First, populate the rates using the Admin API (you can do this from a simple script running on your machine or a GitHub Action):

# Fetch rates
RATES=$(curl -s "https://api.allratestoday.com/v1/latest?base=USD" \
  -H "Authorization: Bearer YOUR_API_KEY" | jq '.rates')

# Write to Shopify metafield
curl -X POST "https://your-store.myshopify.com/admin/api/2026-04/metafields.json" \
  -H "X-Shopify-Access-Token: YOUR_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"metafield\": {\"namespace\": \"fx\", \"key\": \"rates\", \"value\": \"$RATES\", \"type\": \"json\"}}"

Then in your Liquid template:

{% assign fx_rates = shop.metafields.fx.rates.value %}
{% assign customer_currency = localization.country.currency.iso_code %}

{% if customer_currency != shop.currency %}
  {% assign rate = fx_rates[customer_currency] %}
  {% if rate %}
    {% assign converted_price = product.price | times: rate | round %}
    <span class="local-price">
      {{ converted_price | money_without_currency }} {{ customer_currency }}
    </span>
    <span class="base-price" style="font-size: 0.8em; color: #666;">
      ({{ product.price | money }})
    </span>
  {% endif %}
{% else %}
  {{ product.price | money }}
{% endif %}

This approach requires no app installation and works within Shopify's existing infrastructure. The downside is that Liquid cannot fetch external data directly, so you still need an external process to update the metafield.

Approach 3: Theme App Extension with Client-Side Conversion

For app developers or stores comfortable with JavaScript, a theme app extension provides the cleanest user experience.

// assets/currency-converter.js
class CurrencyConverter {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.rates = {};
    this.baseCurrency = Shopify.currency.active;
  }

  async loadRates() {
    // In production, proxy through your own server to protect the API key
    const cached = sessionStorage.getItem("fx_rates");
    if (cached) {
      const parsed = JSON.parse(cached);
      const age = Date.now() - parsed.timestamp;
      if (age < 120000) { // 2 minutes
        this.rates = parsed.rates;
        return;
      }
    }

    const res = await fetch("/apps/fx-proxy/rates?base=" + this.baseCurrency);
    const data = await res.json();
    this.rates = data.rates;
    sessionStorage.setItem("fx_rates", JSON.stringify({
      rates: data.rates,
      timestamp: Date.now()
    }));
  }

  convert(amount, targetCurrency) {
    const rate = this.rates[targetCurrency];
    if (!rate) return null;
    return (amount * rate).toFixed(2);
  }

  applyToPage(targetCurrency) {
    document.querySelectorAll("[data-price-amount]").forEach(el => {
      const baseAmount = parseFloat(el.dataset.priceAmount);
      const converted = this.convert(baseAmount, targetCurrency);
      if (converted) {
        el.textContent = converted + " " + targetCurrency;
      }
    });
  }
}

The proxy endpoint (/apps/fx-proxy/rates) keeps your API key server-side and adds caching.

Handling Price Psychology Across Currencies

Raw mathematical conversion creates awkward prices. $49.99 USD converts to 45.7241 EUR, which looks wrong on a product page. You need rounding rules per currency.

Here is a rounding configuration you can apply after conversion:

const roundingRules = {
  USD: { precision: 2, charm: 0.99 },   // $49.99
  EUR: { precision: 2, charm: 0.99 },   // 45.99
  GBP: { precision: 2, charm: 0.99 },   // 39.99
  JPY: { precision: 0, charm: 0 },      // 7600 (no decimals)
  SEK: { precision: 0, charm: 0 },      // 499
  CHF: { precision: 1, charm: 0.90 },   // 44.90
  INR: { precision: 0, charm: 0 },      // 4199
};

function applyPsychologicalRounding(amount, currency) {
  const rule = roundingRules[currency] || { precision: 2, charm: 0 };
  const factor = Math.pow(10, rule.precision);
  let rounded = Math.ceil(amount * factor) / factor;

  if (rule.charm > 0) {
    rounded = Math.floor(rounded) + rule.charm;
  }

  return rounded;
}

This turns 45.7241 EUR into 45.99 EUR and 7648.47 JPY into 7648 JPY, which look natural to local shoppers.

Automatic Price Updates: How Often Is Enough?

For most Shopify stores, updating exchange rates every 15 to 60 minutes strikes the right balance between freshness and API usage. Here is a usage estimate:

Update IntervalRequests/DayRequests/MonthAllRatesToday Tier Needed
Every 60 seconds1,44043,200Paid
Every 15 minutes962,880Paid (just above free)
Every 60 minutes24720Free (1,500/month)
Every 4 hours6180Free
Once daily130Free

For an exchange rate API Shopify integration on the free tier, hourly updates use only 720 requests per month, leaving room for historical and conversion queries.

Dealing with Shopify Markets Conflicts

If you already have Shopify Markets enabled, adding your own exchange rate source can create conflicts. Here is how to handle it:

Option A: Disable Shopify Markets currency conversion. Set all markets to manual pricing, then use your API-driven prices. This gives you full control but means you manage everything.

Option B: Use Shopify Markets for checkout, API for display. Show your API-converted prices on product pages and collection pages, but let Shopify handle the actual checkout conversion. Add a disclaimer: "Final price may vary slightly at checkout."

Option C: Overwrite Shopify rates via the API. Use the Shopify Admin API to write your own exchange rates into the Markets configuration. This is the cleanest approach if you have Shopify Plus.

Most merchants choose Option B because it works on any Shopify plan and avoids disrupting the checkout flow.

Showing "Last Updated" for Trust

International shoppers appreciate knowing that prices are current. Add a small timestamp near your currency selector:

{% assign fx_updated = shop.metafields.fx.updated_at.value %}
<div class="fx-freshness">
  Rates updated: {{ fx_updated | date: "%b %d, %Y %H:%M UTC" }}
  <br>
  <small>Source: Mid-market rates via AllRatesToday</small>
</div>

This transparency builds trust and differentiates your store from competitors who show stale or opaque conversions.

Measuring the Impact

After integrating an exchange rate API Shopify solution, track these metrics:

Give it 30 days and compare against your pre-integration baseline.

Step-by-Step Quick Start

  1. Sign up at allratestoday.com/pricing -- the free tier is enough to get started.
  2. Choose your integration approach from the three options above based on your Shopify plan and technical comfort.
  3. Set up rate fetching using the latest rates endpoint: GET /v1/latest?base=USD.
  4. Implement rounding rules for your target currencies.
  5. Deploy and monitor checkout completion rates for 30 days.

Full API documentation, including code examples in JavaScript, Python, Ruby, and PHP, is available at allratestoday.com/developers. The exchange rate API Shopify integration typically takes a developer half a day to implement and starts paying for itself within the first week through reduced checkout abandonment.

Try AllRatesToday free

npm install @allratestoday/sdk

Real-Time Rates for Your Shopify Store

Accurate local currency pricing, 60-second updates, 160+ currencies. Reduce checkout abandonment and sell more internationally.

Get Your Free API Key