Skip to content
Docs

Getting started

Conversion tracking methods

Postback, pixel, iframe, JavaScript, server-to-server events and SDKs compared, with endpoints, parameters and responses.

A click gets a unique click_id. A conversion is attributed by sending that id back. There are several ways to do it; pick per offer with the conversion_method setting (server_postback, image_pixel, iframe_pixel, javascript_sdk, cookie_based, gtm, shopify, s2s_event_api, coupon_code, call). The setting restricts which endpoint families are accepted for that offer; a mismatch is rejected with method_not_allowed.

Which method should I use?

MethodUse whenEndpoint (on the tracking or ingest host)Needs
Server postbackThe advertiser has a backend. Most reliable; recommended.GET or POST /p, /postback, /conversionThe click_id stored by the advertiser.
Image pixelNo backend access, only a thank-you page.GET /px.gifClick id from a cookie or URL parameter on the page.
Iframe pixelPage cannot host an image (ad blockers, CSP).GET /px.htmlSame as image pixel.
JavaScriptYou want the browser to read the cookie itself./sdk.js then dtk('conversion', {...}), or GET /jsWeb SDK on the thank-you page.
S2S event APIMany event types from a backend with an API key.POST /v1/events (API key)Authorization: Bearer key.
Mobile SDK / S2SApps: installs, sessions, in-app events./sdk/v1/*, POST /v1/eventsSee mobile.
Shopify, BigCommerceStore conversions through webhooks./integrations/shopify/webhook, /integrations/bigcommerce/webhookWebhook secret and tenant configured on ingest.
Coupon codeOffline or influencer codes, no click.any inbound endpoint with coupon=Coupon assigned to a partner.
CallsCall tracking.created internally from a qualified callSee call tracking.
Bulk / manualReconciliation, corrections.POST /v1/conversions/bulk (JSON or CSV), admin portalAPI key or portal.

/aff_lsr and /pb are accepted aliases of the postback path.

Postback

text
https://track.yourbrand.com/p?click_id={click_id}&goal=sale&txn_id={order_id}&amount={total}&currency=USD&security_token=TOKEN

The advertiser fills the braces on its side. Parameters are case-insensitive and accept many spellings; the registry is in the parameters reference:

CanonicalAccepted namesMeaning
click_idclickid, cid, transaction_id, tid, aff_click_id, _ef_transaction_id, dtk_clickThe id we put in the destination URL.
goalgoal_id, goal_value, event, event_name, adv_event_id, g, event_idGoal key (or id). Omit for the base goal.
txn_idorder_id, trans_id, ref_id, txid, transaction, adv_txnThe advertiser's unique id for this conversion; the de-duplication key.
amountsale_amount, sale, revenue, rev, value, sumSale amount for percentage payouts and revenue.
payoutpayoutExplicit payout, honoured only for advertisers with token, IP or HMAC security.
currencycurISO currency of amount; converted with a locked FX rate.
statusstatusapproved, pending or rejected, for trusted advertisers; also used to update an existing conversion.
security_tokentoken, key, secretAdvertiser token.
tstimestamp, date, click_timeBackdate a conversion (bounded to roughly 400 days back and 5 minutes forward; it must still fit the attribution window).
adv1..adv10, sub1..Advertiser-defined values kept on the conversion, usable as payout calc_param sources.
coupon, user_id, email, phone, ip, ua, device_id, testMatching and test signals.

Security modes

Set per advertiser (postback_security_mode):

ModeCheckFailure reason
noneNothing.
tokensecurity_token equals the advertiser's token.invalid_token
ipSource IP (postbacks and S2S) is inside the advertiser's whitelist.ip_not_whitelisted
hmacHex HMAC-SHA256 of the raw query string (or request body) keyed with the advertiser's security_token, sent in the X-DT-Signature header or a signature parameter.invalid_signature

Response

Ingest never answers a conversion hit with a 4xx or 5xx for business reasons, because advertiser systems retry on errors. It answers 200:

json
{"status":"created","conversion_id":"01J...","reason":"","conversion_status":"approved"}
statusMeaning
createdNew conversion recorded (its conversion_status may be pending or flagged).
duplicateSame txn_id (or click and goal) already recorded; nothing changed.
updatedAn existing conversion changed status because a trusted advertiser sent a different status for the same txn_id.
rejectedFailed validation; a rejected conversion is still stored with its reason.
unmatchedNo click could be found. Stored and visible so it can be assigned.

Pixels additionally return a 1x1 GIF (or an empty HTML page for iframes).

Validation order

First failure wins; the reason appears in the logs and the response.

  1. Offer: offer_paused, offer_inactive, offer_expired.
  2. Partner: partner_inactive, blocked_partner.
  3. method_not_allowed (conversion method vs endpoint family).
  4. Advertiser security: invalid_token, ip_not_whitelisted, invalid_signature.
  5. Click checks: invalid_click (the click was flagged invalid), then the timing window: expired_session, ctit_too_short, ctit_too_long, and kpi_window_exceeded for goals with a KPI window.
  6. Hooks: caps and fraud can reject or downgrade the status at their stage.

Details of matching are in attribution, duplicates in deduplication.

Pixel and iframe

html
<img src="https://track.yourbrand.com/px.gif?click_id=CLICK&goal=lead&txn_id=ORDER42" width="1" height="1" alt="">
<iframe src="https://track.yourbrand.com/px.html?click_id=CLICK&goal=lead&txn_id=ORDER42" width="0" height="0" style="display:none"></iframe>

A token placed in a pixel URL is visible to every visitor, so pixels are best used on offers whose advertiser security mode is none, or with only a click id while a server postback confirms the amount.

JavaScript SDK

Load the SDK from your tracking domain (/sdk.js, under 6 kB gzipped, served with an ETag), initialise it with your tracking domain, and report from the thank-you page. The SDK reads the click id from the landing URL, keeps it in a first-party cookie and local storage, and posts conversions to POST /p.

html
<script src="https://track.yourbrand.com/sdk.js" async
        data-domain="https://track.yourbrand.com" data-consent="granted"></script>
<script>
  window.dtk = window.dtk || function () { (dtk.q = dtk.q || []).push(arguments); };
  dtk('conversion', { goal: 'sale', txn_id: 'ORDER42', amount: '49.90', currency: 'USD' });
</script>
CommandPurpose
dtk('init', {domain, tenant, consent, ttl, cookie, cookieEndpoint, debug})Configure (the data-* attributes on the script tag do the same).
dtk('consent', 'granted' | 'denied' | {ad_storage})Nothing is stored before consent; conversions are queued (up to 50) and flushed when consent is granted.
dtk('conversion', {...}) or dtk('track', {...})Send a conversion. A repeated txn_id in the same browser is dropped client-side.
dtk('identify', {user_id, email_hash})Attach user identifiers.
dtk('pixel', {...})Build a pixel URL.
dtk('click_id'), dtk('params')Read the captured ids.

With cookieEndpoint: true the SDK also asks POST /sdk/v1/cookie to set an HttpOnly cookie from your tracking CNAME, which survives Safari's limits on script-written cookies. Allowed origins for these browser calls are configured on ingest with DT_INGEST_SDK_ORIGINS. A Google Tag Manager template ships in packages/web-sdk/gtm.

Server-to-server events

For richer events from your backend use an ingest API key of the tenant. The body is one event object or {"events":[...]}; a single event returns its outcome, a batch returns {"results":[...]}.

bash
curl -X POST https://ingest.yourbrand.com/v1/events \
  -H "Authorization: Bearer $DT_API_KEY" -H "Content-Type: application/json" \
  -d '{"click_id":"CLICK","goal":"deposit","txn_id":"T-9","amount":"100.00","currency":"EUR"}'

Bodies that carry an app token, app id or device block, or an X-Dt-App-Token / X-Dt-Signature header, are routed to the mobile pipeline instead; see install attribution. To correct statuses later use POST /v1/conversions/{id}/status (approve, reject, pending) with the same key. POST /v1/conversions/bulk accepts JSON or CSV for bulk reconciliation.

Shopify and BigCommerce

Ingest verifies Shopify webhooks with HMAC (X-Shopify-Hmac-Sha256, secret DT_INGEST_SHOPIFY_SECRET, tenant DT_INGEST_SHOPIFY_TENANT). BigCommerce needs the shared secret in X-DTK-Webhook-Secret and reads the click id from a cart metafield (dtk_click). Both are idempotent on the order id. The WooCommerce plugin in integrations/woocommerce posts to /p and honours the WordPress consent API (options dtrackier_domain, dtrackier_tenant, dtrackier_goal, dtrackier_token, dtrackier_ttl_days).

Postbacks from Metrixed to others

Conversions can also fire postbacks out to partners and ad platforms; that direction is documented in postbacks and webhooks.