A sales leader notices the EMEA forecast moved 6 percent overnight and nobody changed a deal. The cause: HubSpot pulled fresh exchange rates and converted historic deals at today’s spot. Multi-currency works in HubSpot, but the defaults assume you understand finance’s preferences. They usually do not match, and the reconciliation conversation gets ugly.
Enable in the right order
Settings > Currency. Set your company currency first — this is the base every report converts to. Add additional currencies one at a time, populating the rate at enable time. Once enabled, the company currency is hard to change without support intervention, so confirm with finance before you click.
Per-deal currency at creation
Every deal gets a Deal currency property at creation. This locks the amount in the buyer’s currency. Conversions to company currency happen at report time using the exchange rate effective on a date you choose. If you let reps change deal currency mid-cycle, your historic forecast drifts.
Deal: Acme EMEA Ltd renewal
deal_currency: EUR
amount: 50,000 EUR
amount_in_company_currency: 54,200 USD (auto-calculated)
Choose your exchange rate cadence
HubSpot offers manual or automatic rates from Open Exchange Rates. Automatic means daily updates. For finance teams that close books monthly with a fixed rate, automatic is wrong. Set rates manually on the first business day of each month and lock them. Document the source (ECB, OANDA, internal treasury) in the rate notes field.
Manual rate update workflow:
- 1st business day of month
- Pull rates from {finance-source}
- Update HubSpot Settings > Currency
- Notify revops in Slack
- Snapshot rates in /finance/exchange-rates/{YYYY-MM}.csv
Workflow on currency changes
A rep changing deal currency from EUR to USD on a renewal silently revalues the pipeline. Block it or audit it:
// Workflow triggered on Deal property change: deal_currency
const old = event.previousValue;
const next = event.newValue;
if (old && old !== next && event.dealAmount > 25000) {
await postToSlack(`Currency changed on deal ${event.dealId}: ${old} -> ${next}`);
await createTaskForRevOps(event.dealId, "Validate currency change");
}
return { outputFields: { audited: true } };
Reports converted at the right rate
Pipeline reports default to “today’s rate” for conversions. For board reporting, you want “rate at close date” or “rate at deal creation.” Set this per report under Display options. A weekly forecast on today’s rate plus a monthly forecast on close-date rate is the typical compromise.
Quotes and invoices
Quotes inherit currency from the deal. Branded quote templates need currency-aware formatting:
{% set qc = quote.currency %}
{% for li in quote.lineItems %}
{{ li.amount | format_currency(qc, locale="en_US") }}
{% endfor %}
{{ quote.total | format_currency(qc, locale="en_US") }}
Test quote rendering in every active currency before going live. The most common bug: hardcoded $ prefixes in custom templates that ignore the currency code.
Edge cases to plan for
- Multi-currency deals (split across regions): use line-item currency or split deals
- Currency on closed-won deals: never recompute historic at today’s rate
- Commission calculations: lock to deal-currency amount at close, not company currency
- Channel deals where partner pays you in one currency, customer pays partner in another
What to do this week
Confirm your company currency with finance, document your exchange rate cadence in a runbook, and add a Slack alert on currency changes for deals over your threshold. Snapshot this month’s rates before you enable any new currency.