> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thrad.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Track purchases

> Fire window.thradTag("conversion", ...) on the order confirmation page.

A conversion is the moment that closes the loop — typically the order confirmation page.

## The call

Place this on your **order confirmation / thank-you page only**, with values rendered by your backend:

```js theme={null}
window.thradTag("conversion", {
  order_id: "order_123",
  value: 99.99,
  currency: "USD"
});
```

Provide the final order ID, nonnegative total value in major currency units and
three-letter currency. The Tag captures signed Thrad and OpenAI context from the
landing journey; OpenAI-only context does not require a fabricated Thrad signature.

Thrad must confirm availability of the updated purchase adapter and matching
collector before you migrate existing browser/server purchase senders. For
Shopify checkout, follow the separate [Custom Pixel guide](https://docs.thrad.ai/advertisers/attribution/tag/guides/shopify.md).

> **Where to fire it** Submit confirmed purchases only. The updated adapter derives
> a stable identity from the configured tag and final order ID. Retries keep that
> same identity. Missing order ID, value or currency prevents purchase submission;
> do not substitute a cart or checkout token for the final order ID.

## Using the Browser Tag and Server-to-server CAPI together

The browser purchase command sends the configured tag and final order ID. The
collector derives `purchase:v1:` followed by the SHA-256 of compact UTF-8 JSON
`[tag_id, order_id]`, after trimming both strings and normalizing an exact
`gid://shopify/Order/<positive numeric ID>` to that numeric ID. Your
[server purchase](https://docs.thrad.ai/advertisers/attribution/server-events/overview.md#using-the-browser-tag-and-server-to-server-capi-together)
must use the same canonical `event_id` and tag. Do not rely on an `event_id` in
browser conversion parameters to override this identity: the command supplies
tag/order rather than forwarding that field. If you submit a versioned purchase
HTTP body with an explicit `event_id`, the collector rejects it unless it matches
the derived identity. An arbitrary ID such as `order_123:purchase` is not a valid
canonical purchase ID.

Coordinate existing server sender identities with Thrad before cutover. A hosted
runtime update cannot change the ID generated by your server, and historical
random IDs require a verified order mapping rather than an invented alias.

## Fields

| Field | Required | Notes |
| - | - | - |
| `order_id` | yes | Final stable order ID; unique within this tag. |
| `event_id` | not needed in browser command | Does not override tag/order identity; an explicit versioned HTTP/server ID must match the canonical identity. |
| `value` | yes for purchases | Nonnegative total order value in major currency units. |
| `currency` | yes for purchases | Three-letter ISO code (`USD`, `EUR`, …). |

## Delivery outcomes

The purchase command sends an inspectable `/v1/collect` request with unload-compatible
`keepalive` where the payload size permits it. Temporary network failures and
HTTP 429/5xx responses can make at most three attempts with the same tag/order
identity. Known terminal validation/authorization reasons and malformed receipts
stop; consent and signed expiry are checked before each attempt. There is no
persistent browser purchase queue or guarantee of recovery after browser shutdown.

| Observation | Meaning and next step |
| - | - |
| `missing_order` or `invalid_order_data` | No purchase submitted. Fix the final order ID, amount or currency. |
| `missing_context` | No supported attribution context. Check landing capture and propagation to checkout. |
| `http_rejected` | Inspect the HTTP status and safe reason. Correct invalid/expired signed claims or business fields; do not remove signed fields to force an OpenAI-only retry. |
| `network_failed` | The server outcome is unknown. Bounded retries retain the same canonical identity. |
| `invalid_receipt` or `invalid_provider_identity` | The response is not a valid acknowledgment. Check the collector/configuration; browser provider dispatch is withheld. |
| `purchase_retry_exhausted` | Three attempts failed. Investigate network/collector health before resubmitting the same final order. |
| `purchase_queue_full` | The page already has 100 pending purchases. Investigate duplicate/bulk triggers; this call was not admitted to the in-page queue. |
| Valid receipt: `accepted`, stage `queued` | The collector queued the purchase; durable storage still needs verification. |
| Valid receipt: `accepted`, stage `stored`, or `duplicate` | The collector admitted the canonical purchase or recognized it. Verify stored identity/value when reconciling. |

A beacon result only confirms browser queueing. A GTM trigger, HTTP 2xx, collector
receipt or provider acknowledgment is not proof that a provider credited a
conversion. Verify the final purchase in Thrad's ledger and the provider's
attribution reporting separately. If a corrected explicit callback is needed,
keep the same final order and canonical identity; never create a second pixel
or a new random ID to escape a rejection.

That's it for client-side conversions. If you'd rather send conversions from your backend (more reliable and resilient to ad blockers), use the [Server-to-server Conversions API](https://docs.thrad.ai/advertisers/attribution/server-events/overview.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.