---
title: Amazon Conversions API
slug: amazon-conversions-api
docTags: 
createdAt: 2026-10-16T16:56:40.989Z
---

The **Amazon Conversions API** destination sends off-Amazon conversion events to [Amazon Ads](https://advertising.amazon.com/) using the server-side [Events API](https://advertising.amazon.com/API/docs/en-us/amazon-ads/1-0/betas#tag/Events/operation/CreateEvent), so purchases, sign-ups and other conversions that happen on your storefront can be attributed to and optimized against Amazon Ads campaigns.

This is a **cloud-mode (server-side) destination only**, which is how Amazon intends the Conversions API to be used: it exists for server-side and offline conversions, while browser-side measurement belongs to the Amazon Ad Tag (AAT) pixel on your storefront. Sending the same conversion through both surfaces without deduplication will double-count it.

This destination is built to match the Segment **Amazon Conversions Api** destination: the same conversion types, the same normalization and SHA-256 hashing of match keys, and `messageId` as the deduplication id. The Chord tracking-plan event names are mapped alongside Segment's, so a migration needs no per-event configuration.

# Getting started

Amazon Ads authenticates with **Login with Amazon (LWA)**. Because Chord CDP cannot run an interactive OAuth flow inside a destination, you supply the credentials of an LWA application that has already been authorized for your advertiser account:

- **Amazon Advertiser ID.&#x20;**&#x59;our advertiser account ID, sent as the `Amazon-Ads-AccountId` header. Numeric; use the Amazon DSP CFID, **not** the Entity ID.
- **LWA Client ID** and **LWA Client Secret&#x20;**&#x66;rom the Amazon Ads API section of the [Amazon developer console](https://advertising.amazon.com/API/docs/en-us/guides/onboarding/create-lwa-app).
- **LWA Refresh Token**, issued when your application was authorized for the advertiser account. Chord exchanges it for a one-hour access token and caches that token until it expires; the refresh token itself is never logged.
- **Region.** `NA`, `EU` or `FE`, matching the marketplace region of the advertiser account. **Events sent to the wrong region are rejected.**

Amazon supports **Self-Service accounts only** for this API. Managed Service and Manager accounts are not supported.

:::hint{type="warning"}
**Warning:&#x20;**&#x42;efore connecting destinations in the Chord CDP, please verify with all Destination owners that all non-Chord CDP configured destinations are disabled. Running external destinations alongside configured Chord CDP destinations can result in duplicate events downstream.
:::

1. Log into the Chord data platform.
2. Navigate to the CDP.
3. Click the **"Add"** button next to Destinations.
4. Select **Amazon Conversions API** from the destination catalog.
5. Enter the destination name, **Region**, **Amazon Advertiser ID** and the three LWA credentials.
6. Set a **Dataset Name** now if you want one (see below); changing it later creates new conversion definitions.
7. Click **"Create"** to connect.

# Datasets

Amazon Ads groups uploaded events into **datasets**, which is how they appear in Amazon Ads Data Manager. Leaving **Dataset Name** empty puts everything in Amazon's `Default_Events` dataset.

Set the dataset name during initial setup. A dataset name must start with a letter, contain only letters, numbers, underscores or hyphens, and be 5–100 characters long. **Changing it on a live destination creates new conversion definitions in Amazon**, splitting your reporting history; treat it as immutable once events are flowing.

# Event mapping

Amazon has a closed set of twelve conversion types. Chord maps its canonical event names onto them, using the same event names as the Segment destination plus the Chord tracking-plan aliases for the same actions:

| **Chord Event**                   | **Amazon Conversion Type** |
| --------------------------------- | -------------------------- |
| `Product Added`                   | `ADD_TO_SHOPPING_CART`     |
| `Application Submitted`           | `APPLICATION`              |
| `Checkout Started`                | `CHECKOUT`                 |
| `Callback Started`                | `CONTACT`                  |
| `Lead Generated`                  | `LEAD`                     |
| `Order Completed`, `Order Placed` | `OFF_AMAZON_PURCHASES`     |
| `Application Opened`              | `MOBILE_APP_FIRST_START`   |
| `page` events, `Page Viewed`      | `PAGE_VIEW`                |
| `Products Searched`               | `SEARCH`                   |
| `Signed Up`, `Account Created`    | `SIGN_UP`                  |
| `Subscription Created`            | `SUBSCRIBE`                |
| Any other track event             | `OTHER`                    |

`identify`, `group` and other event types are skipped with an explicit log line.

## Custom events

`OTHER` is a conversion type Amazon defines for "customer actions that don't fit the definition of the standard event types", so this destination is **passthrough-capable**: an event with no mapping is forwarded under its own name as `OTHER` rather than dropped. Turn **Forward unmapped events as OTHER** off to send only the mapped conversion events; skipped events are logged explicitly either way. See [Custom Events](#).

## Overriding the mapping

Use **Event Mapping** to send a specific event under a different conversion type, e.g. `Subscription Renewed` → `OFF_AMAZON_PURCHASES`. Only the twelve types above are valid; an event mapped to anything else is skipped with a log line rather than guessed at.

:::hint{type="warning"}
A conversion definition in Amazon Ads is identified by the event name, conversion type and event source together. Renaming events, changing Event Action Source, or remapping conversion types all create new definitions in Amazon. Settle these before you start sending production traffic.
:::

# Identity (Match Keys)

Amazon requires **at least one match key** per event, and every PII match key must be normalized and SHA-256 hashed. Chord does both before the request leaves the platform; plaintext PII is never sent. A value that already looks like a SHA-256 digest is passed through rather than hashed twice.

| **Amazon Match Key** | **Chord Source**                                                                                  | **Normalization before hashing**                                   |
| -------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `EMAIL`              | `properties.email` > `context.traits.email`                                                       | Lowercase; keep alphanumerics plus `.`, `@`, `+`, `-`              |
| `PHONE`              | `properties.phone` / `phone_number` > traits                                                      | Digits only                                                        |
| `FIRST_NAME`         | `properties.firstName` / `first_name` > traits                                                    | Lowercase alphanumerics only                                       |
| `LAST_NAME`          | `properties.lastName` / `last_name` > traits                                                      | Lowercase alphanumerics only                                       |
| `ADDRESS`            | `traits.address.street` / `address1`                                                              | Lowercase alphanumerics only                                       |
| `CITY`               | `traits.address.city` > `properties.city` > `properties.shipping_city`                            | Lowercase alphanumerics only                                       |
| `STATE`              | `traits.address.state` > `properties.state` > `properties.shipping_state`                         | Lowercase alphanumerics only                                       |
| `POSTAL`             | `traits.address.postalCode` / `zipcode` > `properties.postalCode` > `properties.shipping_zipcode` | Lowercase, whitespace removed (punctuation kept for UK/CA formats) |
| `MAID`               | `context.device.advertisingId` / `idfa` / `adid`                                                  | Sent in the clear                                                  |
| `RAMP_ID`            | `properties.rampId` > traits > `context.clientIds.rampId`                                         | Sent in the clear                                                  |
| `MATCH_ID`           | `properties.matchId` / `match_id` > traits > `context.clientIds.matchId`                          | Sent in the clear                                                  |

"Lowercase alphanumerics only" means ASCII: `José` is hashed as `jos`. This matches the Segment destination; we have not been able to confirm it against Amazon's own guideline, which requires an Amazon Ads login to read. The same applies to email: their guideline quotes it keeps only `.`, `@` and `-`, but note that our code also keeps `+`.

Identifiers sent as numbers (a zip of `94107`, a phone of `14155550132`) are treated as their string form. Values that carry no matching signal are **dropped rather than hashed**: placeholders like `n/a`, `unknown` or `test`, an email without an `@`, and phone numbers with fewer than 7 digits or all one digit. A hash of `n/a` is the same for every brand that sends it, so it would match unrelated customers.

An event that carries **no** usable identifier cannot be attributed, so it fails with a non-retryable error rather than being sent and silently discarded by Amazon.

**Match ID** deserves a note: it is an opaque identifier of your own (a loyalty ID, an order reference) that Amazon correlates to users via the Amazon Ad Tag. If your storefront passes `match_id` to AAT, sending the same value here links offline and server-side conversions to the same customer journey without sharing hashed PII.

# Event fields

| **Amazon Field**                        | **Chord Source**                                                                                                             | **Notes**                                                                                               |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `eventDescription.name`                 | `event` (page: `name`, else `Page View`)                                                                                     | Sent verbatim                                                                                           |
| `eventDescription.conversionType`       | See [Event Mapping](#event-mapping)                                                                                          |                                                                                                         |
| `eventDescription.eventSource`          | **Event Action Source** setting, else `context.device.type`                                                                  | Uppercased. Device types Amazon does not accept (`mobile`, `desktop`) fall back to `WEBSITE`            |
| `eventDescription.eventIngestionMethod` | *(hardcoded)* `SERVER_TO_SERVER`                                                                                             | Required by Amazon for Conversions API events                                                           |
| `countryCode`                           | `properties.country` > `properties.shipping_country` > `context.locale` > `context.geo` > address > **Default Country Code** | Locale forms (`en-US`, `pt_BR`) are reduced to the region subtag                                        |
| `eventTime`                             | `timestamp`, else `receivedAt`                                                                                               | ISO 8601                                                                                                |
| `eventId`                               | `messageId`                                                                                                                  | Amazon's `clientDedupeId` — see [Deduplication](#deduplication)                                         |
| `value`                                 | `properties.value` > `revenue` > `total` > `price`                                                                           | Sent for every conversion type                                                                          |
| `currencyCode`                          | `properties.currency`                                                                                                        | `OFF_AMAZON_PURCHASES` only. Currencies outside Amazon's accepted list are omitted rather than rejected |
| `unitsSold`                             | `properties.quantity`, else the sum of `products[].quantity`                                                                 | `OFF_AMAZON_PURCHASES` only. Omitted when unknown — Amazon then defaults it to 1                        |
| `customData`                            | `brand`, `category`, `productId` + custom-mapped properties                                                                  | See [Custom attributes](#custom-attributes)                                                             |
| `consent`                               | See [Consent](#consent)                                                                                                      |                                                                                                         |
| `dataProcessingOptions`                 | **Limited Data Use** setting or `properties.dataProcessingOptions`                                                           |                                                                                                         |

## Country code

Amazon requires an ISO 3166-1 alpha-2 country code on **every** event. Browser events usually carry `context.locale` or geo data; back-end events (Shopify webhooks, server-to-server ingest) often carry neither, which is what the **Default Country Code** setting is for — it defaults to `US`. Clear it if you would rather such events fail loudly than be attributed to the wrong country.

## Custom attributes

Amazon's `customData` is a list of name/value pairs. Names accept letters, numbers and underscores; values are strings capped at 256 characters. Chord sends:

- `brand`, `category` and `productId`, resolved from the event's top-level properties and falling back to the first entry of `products[]`. These are the attributes Amazon uses for reporting, alongside `attr1`–`attr10`.
- Any property you have configured as a `properties.*` destination mapping in Hub, promoted into `customData` automatically. Names are sanitized (`gift-note` → `gift_note`) and nested values are JSON-stringified rather than dropped.

PII fields (email, phone, first/last name) are **never** promoted as plain custom attributes; they only ever leave as hashed match keys.

## Consent

| **Amazon Field**                                       | **Chord Source**                                                                                               |
| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
| `consent.geo.ipAddress`                                | `context.ip`                                                                                                   |
| `consent.amazonConsent.amznUserData` / `amznAdStorage` | `properties.amznUserData` / `amznAdStorage`, or `context.consent.*` — `GRANTED` / `DENIED` (booleans accepted) |
| `consent.tcf`                                          | `properties.tcf` > `context.consent.tcf`                                                                       |
| `consent.gpp`                                          | `properties.gpp` > `context.consent.gpp`                                                                       |

**In the EU region, Amazon requires at least one of these signals on every event.** An EU-region event carrying none fails with a non-retryable error instead of being sent and rejected. In practice `context.ip` satisfies this for browser-originated events; back-end events need an explicit consent property.

## Limited data use

Enabling **Limited Data Use** stamps every event with Amazon's `LIMITED_DATA_USE` data-processing option. Amazon does **not** process events marked this way for measurement or optimization, so enable it only where a privacy regime requires it. Individual events can opt in on their own by sending a `dataProcessingOptions` property containing `LIMITED_DATA_USE`.

# Deduplication

`messageId` is sent as Amazon's `clientDedupeId`. For events sharing a dedupe id Amazon processes only the most recent one, which makes pipeline retries and replays safe.

Note that Amazon deduplicates **across all event types**, not per event type — two different conversions must not share a `messageId`.

# Error handling

| **Condition**                                                        | **Behavior**                                                                                          |
| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| 5xx or 429 from Amazon                                               | Retried                                                                                               |
| 401                                                                  | The cached access token is discarded and the event retried with a freshly minted one                  |
| 403                                                                  | Not retried — the LWA application is not authorized for this advertiser, which a new token cannot fix |
| Other 4xx                                                            | Not retried — a malformed event will not become valid on a resend                                     |
| `207` with a per-event `error` entry                                 | Treated as a failure, with Amazon's own error message. A 207 whose events all succeeded passes        |
| Missing match key, missing country code, missing EU consent          | Not retried; the log line names the missing piece                                                     |
| LWA credentials rejected (`400`/`401` at the token endpoint)         | Not retried — the Client ID, Secret or Refresh Token needs fixing                                     |
| Non-numeric Advertiser ID, or a Dataset Name outside Amazon's format | Not retried, and no request is made. The console form flags both when the destination is saved        |

The access-token request is deliberately excluded from Live Events logging: it carries the client secret and refresh token in its body and returns the access token in its response.
