managed-components / managed-components/amplitude
Ecommerce `currency` is not mapped to Amplitude's native `$currency` property
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 4
- PR merge metrics
- No merged PRs in 30d
Description
## Summary
The Amplitude Managed Component receives Zaraz's standard ecommerce `currency` parameter but sends it only as `event_properties.currency`. It does not map it to Amplitude HTTP V2's top-level `currency` field.
As a result, Amplitude receives a custom `currency` event property but does not populate its native `$currency` property.
## Relevant contracts
Cloudflare documents `currency` as a standard Zaraz ecommerce parameter and includes it in its official `Order Completed` example:
- [Zaraz ecommerce parameters](https://developers.cloudflare.com/zaraz/web-api/ecommerce/#list-of-supported-parameters)
- [Zaraz Order Completed example](https://developers.cloudflare.com/zaraz/web-api/ecommerce/#order-completed)
The documentation also states:
> You do not need to map e-commerce events to triggers. Zaraz automatically forwards data using the right format to the tools with e-commerce support.
Amplitude HTTP V2 defines `currency` as a top-level event field:
- [Amplitude HTTP V2 event array keys](https://amplitude.com/docs/apis/analytics/http-v2#event-array-keys)
Amplitude defines the resulting native property as `$currency` and requires it alongside `$revenue` or `$price` for automatic currency conversion:
- [Amplitude revenue properties](https://amplitude.com/docs/data/sources/instrument-track-revenue#revenue-properties)
- [Amplitude currency conversion](https://amplitude.com/docs/data/currency-conversion#enabling-conversion)
## Reproduction
Send a standard Zaraz ecommerce event:
zaraz.ecommerce("Order Completed", {
order_id: "order-123",
currency: "USD",
revenue: 25,
products: [
{
product_id: "product-123",
price: 25,
quantity: 1
}
]
});
This payload follows Cloudflare's documented ecommerce contract.
## Current implementation
The component retains the incoming `currency` property when it builds the ecommerce payload:
- [`ecomDataMap()`](https://github.com/managed-components/amplitude/blob/44e8731a801acc4b1dc615666cfbf2c01e390b4e/src/index.ts#L100-L118)
However, `getEventData()` promotes only `revenue`, `revenueType`, `productId`, and `quantity` to Amplitude HTTP V2 top-level fields:
...(payload.revenue && { revenue: payload.revenue }),
...(payload.revenueType && { revenueType: payload.revenueType }),
...(payload.productId && { productId: payload.productId }),
...(payload.quantity && { quantity: payload.quantity }),
Source:
- [`getEventData()` top-level revenue mapping](https://github.com/managed-components/amplitude/blob/44e8731a801acc4b1dc615666cfbf2c01e390b4e/src/index.ts#L74-L84)
Because `currency` is missing from that mapping, the generic property loop places it under `event_properties`:
for (const [key, value] of Object.entries(payload)) {
if (key.startsWith('user_')) {
eventData.user_properties[key.substring(5)] = value
} else if (key.startsWith('groups_')) {
eventData.groups[key.substring(7)] = value
} else {
eventData.event_properties[key] = value
}
}
Source:
- [`event_properties` fallback](https://github.com/managed-components/amplitude/blob/44e8731a801acc4b1dc615666cfbf2c01e390b4e/src/index.ts#L86-L94)
The resulting Amplitude event contains:
{
"event_type": "Order Completed",
"revenue": 25,
"event_properties": {
"currency": "USD"
}
}
The component sends this object directly to Amplitude HTTP V2:
- [`sendEvent()` request construction](https://github.com/managed-components/amplitude/blob/44e8731a801acc4b1dc615666cfbf2c01e390b4e/src/index.ts#L140-L160)
## Expected behavior
The outgoing Amplitude event should contain `currency` at the top level:
{
"event_type": "Order Completed",
"revenue": 25,
"currency": "USD",
"event_properties": {
"currency": "USD"
}
}
Amplitude can then ingest it as the native `$currency` revenue property.
## Proposed fix
Add `currency` to the existing top-level revenue mapping:
...(payload.revenue && { revenue: payload.revenue }),
...(payload.revenueType && { revenueType: payload.revenueType }),
...(payload.productId && { productId: payload.productId }),
...(payload.quantity && { quantity: payload.quantity }),
...(payload.currency && { currency: payload.currency }),
No change should be required from callers. They are already using Zaraz's documented `currency` ecommerce parameter.
## Additional evidence
The component's own README includes `currency: "USD"` in its ecommerce example:
- [Managed Component ecommerce example](https://github.com/managed-components/amplitude/blob/44e8731a801acc4b1dc615666cfbf2c01e390b4e/README.md#L75-L106)
This indicates that `currency` is intended to be accepted as part of the component's ecommerce input, but the implementation currently does not translate it into Amplitude's native field.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/index.ts, especially getEventData() and its existing top-level revenue mapping; review ecomDataMap() to confirm the incoming currency field. Verify that the generated Amplitude event places currency at the top level while preserving the existing ecommerce payload behavior, then inspect the component's available tests or validation commands.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- analytics
- Issue type
- Bug
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 85/100