Currency conversion

Grabbing the conversion rate inside a Checkout UI extension is tricky business! There are a few approaches. I thought I’d share our specific approach!

1.) Set a Money metafield called currency_unit, with a large number, e.g 10,000,000
2.) Use query to grab the metafield IN CONTEXT of the current shopping session
3.) You’ll get your large number in the shopping currency, and can do a division to grab the conversion rate!

Pros:

  • This conversion rate will use Shopify Market conversion rates, rather than generic rates.
  • Does not rely on an external source (e.g currencies.js or storefront added cart attributes)

Here’s some “example” code:

Create the metafield:

export const SET_METAFIELD_MUTATION = /* GraphQL */ `
  mutation CreateAppOwnedMetafield(
    $metafieldsSetInput: [MetafieldsSetInput!]!
  ) {
    metafieldsSet(metafields: $metafieldsSetInput) {
      metafields {
        id
        namespace
        key
      }
      userErrors {
        field
        message
      }
    }
  }
`

const moneyMetafield = {
    namespace: 'my_namespace',
    key: 'shop_currency_unit',
    value: JSON.stringify({
      amount: '100000.00',
      currency_code: currencyCode,
    }),
    ownerId: shopGid,
    type: 'money',
  }

const response = await fetch(
    `https://${shop}/admin/api/${apiVersion}/graphql.json`,
    {
      method: 'POST',
      body: JSON.stringify({
        query: SET_METAFIELD_MUTATION,
        variables: {
          metafieldsSetInput: [moneyMetafield],
        },
      }),
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        'X-Shopify-Access-Token': token,
      },
    },
  )
  const jsonResult: any = await response.json()

Query from your Checkout extension:

export const CurrencyFromShopQuery  = `
  query getCurrencyRateFromShop ($namespace: String!, $key: String!, $language: LanguageCode!, $country: CountryCode!) @inContext(country: $country, language: $language) {
    shop {
      id
      currencyUnitField: metafield(namespace: $namespace, key: $key) {
        value
      }
    }
  }
`;

Hope that helps!

8 Likes

This is awesome!! Thanks for sharing this bkspace!

1 Like

Is there any new approach?

I call storefront API, but my data alway return null:
{
“data”: {
“shop”: {
“id”: “gid://shopify/Shop/90724303143”,
“metafield”: null
}
},
“extensions”: {
“context”: {
“country”: “VN”,
“language”: “EN”
},
“cost”: {
“requestedQueryCost”: 2
}
}
}

Make sure your metafield has an associated metafield definition AND has the correct storefront API permissions :slight_smile:

Sep 3, 2025 - I can confirm there’s no other way to get the conversion rate in checkout ui without using @bkspace solution.

Actually, the solution provided by @bkspace did not work on my end, so I used a different approach.

The solution I did fetches the product in its base currency and then makes another query to retrieve the same product in the context of the selected market. Using these two values, the conversion rate is calculated with the formula:

conversion_rate = product_price / product_market_price

Here’s the logic I used, written in a rough code format (of course, you’d want to structure it more cleanly):

const [conversion, setConversion] = useState<any>(null);
const country: Country = useLocalizationCountry();

  useEffect(() => {
    query(
      `query Products {
        products(first: 1, query: "variants.price:>1") {
          nodes {
            handle
            selectedOrFirstAvailableVariant {
              price {
                amount
              }
            }
          }
        }
      }`,
      {
        variables: {},
      }
    )
      .then(({ data, errors }) => {
        //@ts-ignore
        if (data.products?.nodes.length) {
          const productCompare = data.products?.nodes[0];
          query(
            `query Product($handle: String!, $country: CountryCode!) @inContext(country: $country) {
              product(handle: $handle) {
                handle
                selectedOrFirstAvailableVariant {
                  price {
                    amount
                  }
                }
              }
            }`,
            {
              variables: {
                // @ts-ignore
                handle: data.products?.nodes[0].handle,
                country: country.isoCode,
              },
            }
          ).then(({ data, errors }) => {
            const conversionRate =
              data.product.selectedOrFirstAvailableVariant.price.amount /
              productCompare.selectedOrFirstAvailableVariant.price.amount;
            setConversion(conversionRate);
          });
        }
      })
      .catch(console.error);
  }, [query]);

Then you use conversion state to calculate the price in checkout

const price_to_calculate = 100 * conversion;
1 Like

That would also be a smart approach, nice one!