Normalise every conversion into one reporting currency at a stated exchange rate, and display that rate’s as-of date beside the total. Multi-currency attribution breaks because revenue arrives in the buyer’s currency while ad spend is billed in the ad account’s currency — so any ROAS figure silently depends on which rate was applied, and when.
This is a reporting problem before it’s a maths problem. Two people can compute the same month’s ROAS from the same underlying orders and get materially different answers, both correct, with nothing on either report explaining the difference.
Why does multi-currency break attribution?
Because the two halves of every efficiency metric are denominated differently and neither half tells you so.
A ROAS figure is revenue divided by spend. On a cross-border account, the numerator is a mixture — orders in Korean won, Australian dollars, Swedish krona, euros — and the denominator is a single currency chosen when the ad account was created. To divide them at all, something has to convert. That conversion is usually invisible, frequently undocumented, and occasionally done twice.
Three specific failures follow:
Rate drift makes periods incomparable. A campaign that looks like it improved 8% month over month may have done nothing of the sort; the currency its buyers use may simply have strengthened. Without a stated rate, you can’t separate performance from foreign exchange.
The ad platform converts too, using its own rate. Meta and Google report revenue back to you in the ad account’s currency, converted at their rates on their timing. Your commerce platform holds the original amounts. The two will not agree, and the gap is not a tracking bug — it’s two different conversion policies applied to the same sale.
Refunds land at a different time than the sale. A purchase in one month refunded in the next was converted at one rate and reversed at another. Net revenue for the period depends on which rate applies to the reversal, and most systems never state their answer.
Why can’t you just add the numbers up?
Because “add them up” requires a rate, and there are at least three defensible ones that produce different totals.
Consider the same set of orders, converted three ways:
- Rate at transaction time. Each order converts at the rate that applied the day it happened. Most accurate historically; means your reported total for a closed month keeps its value forever.
- Rate at report time. Every order converts at today’s rate. Makes periods directly comparable in today’s money; means last month’s total changes every time you open the report.
- A fixed planning rate. A rate set once per quarter or year for budgeting. Stable and predictable; drifts from reality as the period goes on.
None is wrong. But they are different numbers, and a report that doesn’t say which one it used is not reproducible — which is the actual problem. An agency handing a client a ROAS figure that can’t be recomputed a week later has handed over an opinion, not a measurement.
There’s also a trap in the mechanics. If revenue is converted to the reporting currency on the way in, and the original amount is discarded, the conversion is permanent and unauditable. Change your reporting currency later and you’ll be converting already-converted numbers — a second rounding on top of a rate you can no longer inspect.

What does honest multi-currency reporting require?
Four properties. Together they make a number someone else can reproduce.
1. Store the original currency and amount, always. The transaction record should carry what the buyer actually paid, in what they paid it in. Conversion is a display operation, not a storage operation. This single decision makes every other property possible.
2. Convert at display time, from a named source. European Central Bank reference rates are a reasonable default — they’re published daily, publicly, and by an institution with no stake in your numbers. What matters less is which source you choose and more that it’s named.
3. Show the as-of date next to the total. A converted figure without a rate date is unfalsifiable. With one, anyone can check it. This is the single highest-value habit in multi-currency reporting and the one most often skipped.
4. Net refunds in the original currency, then convert. Reversing a sale should operate on the amount that was actually reversed, in the currency it was reversed in. Converting first and netting second introduces an error that grows with volatility.
A useful test: hand your report to someone else along with the raw orders, and ask them to reproduce the total. If they can’t — because the rate or its date isn’t stated — the number isn’t a measurement.
How should agencies handle this across clients?
Two rules that prevent most of the pain.
Report in the client’s home currency, not yours. The client thinks in the currency they bank in and pay salaries in. An agency reporting everything in its own operating currency forces every client to mentally reconvert, and guarantees that the agency’s number and the client’s finance team’s number never match.
Keep spend and revenue conversion policies identical. If revenue converts at transaction-time rates and spend converts at month-end, the resulting ROAS contains a foreign-exchange artifact that nobody can see. Whatever policy you pick, apply it to both halves.
For accounts running multiple markets out of one ad account, it’s also worth reporting each market in its own currency alongside the consolidated view. The consolidated number answers “how did we do”; the per-market numbers answer “where”, and only the second one is actionable.
How does PartialLeads handle multiple currencies?
By keeping the original amount on every transaction and converting only at display time, against a named rate source with its date shown on the report.
A currency selector on the Attribution Report. You choose the reporting currency, and the whole report — attributed revenue, recovered revenue, channel rows, average order values — renders in it. Alongside it sit a period selector and a timezone selector, because all three change what a number means.
Normalisation at European Central Bank reference rates, with the as-of date displayed. The report carries a footnote naming the reporting currency and the rate date it used. The figure is reproducible by anyone with the same orders and the same published rates — which is the whole point of showing it.
Original currency retained per transaction. Revenue appears on the leads list in the currency it was actually received in, so the individual record keeps its truth while the aggregate is normalised for comparison. Changing your reporting currency re-renders the totals rather than re-converting already-converted figures.
Refunds net in the original currency. A refund is written as its own status-phase row against the original purchase and nets against revenue before any conversion happens, so a cross-period reversal doesn’t acquire a foreign-exchange artifact.
Every KPI carries a prior-period comparison. Attributed revenue, attributed purchases, time to purchase, match rate and recovered revenue all display against the previous period in the same currency at the same rate — so a change reflects the business rather than the rate.
Honest boundaries. Three. Converted totals are estimates, and the report says so — it uses the word estimated in its own footnote rather than presenting a normalised figure as exact. The rate source is a daily reference rate, not the rate your payment processor actually gave you on any individual transaction, so a normalised total will not reconcile to the cent against a bank statement; it is built for comparison across channels and periods, not for accounting. And PartialLeads converts revenue, not ad spend — spend stays as the ad platform reports it, so when you compare against a platform’s own ROAS figure you’re comparing two different conversion policies.

| Problem | PartialLeads mechanism | Where you see it working |
|---|---|---|
| Orders in several currencies can’t be summed | Normalisation to a chosen reporting currency | Currency selector on the Attribution Report |
| A converted total can’t be checked | Named rate source with the as-of date shown | Footnote beside the totals |
| Conversion on the way in destroys the original | Original currency and amount retained per transaction | Revenue column on the leads list |
| Refunds convert at the wrong rate | Refund netted in the original currency before conversion | Purchases ledger, net revenue |
| Period comparisons contain currency drift | Prior-period comparison rendered at the same rate | vs-prior on every KPI |
| One market’s performance hidden in the total | Per-channel and per-campaign rows inside the chosen currency | Channels table, campaign expansion |
Tell us what's broken. We'll fix your tracking — free.
Describe the tracking/attribution problem you're stuck on and we'll map it to a fix: server-side conversions to Meta, Google, TikTok and Pinterest, plus first-party tracking that survives Safari. No code required.
Sources
- European Central Bank — Euro foreign exchange reference rates: https://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html
- Shopify Dev Docs — Webhooks: https://shopify.dev/docs/api/webhooks
- Google Ads Help — About attribution models: https://support.google.com/google-ads/answer/6259715