Getting started
First offer in 10 minutes
Create an advertiser, a partner and an offer, get a tracking link, click it and record a test conversion.
This walkthrough uses the API so every step is copy-pasteable; each step is also available in the admin portal (Network, Offers). You need an API key with write access (see authentication) and one verified tracking domain. Replace the base URL if you self-host.
export API=https://api.metrixed.com/v1
export DT_API_KEY=... # admin portal: Settings, API keys
auth=(-H "Authorization: Bearer $DT_API_KEY" -H "Content-Type: application/json")
1. Create the advertiser
The advertiser's security mode decides how its postbacks are authenticated. token is the simplest: the advertiser sends security_token=... with every postback.
curl -s "${auth[@]}" -X POST $API/advertisers \
-d '{"name":"Acme Shop","status":"active","postback_security_mode":"token"}'
Keep the returned id as ADV. A random security_token is generated for the advertiser (read it from the response or GET /advertisers/ADV); give it to the advertiser, who must send it with every postback.
2. Create the partner
curl -s "${auth[@]}" -X POST $API/partners -d '{"name":"Jane Media","status":"active"}'
Keep the id as PARTNER.
3. Create the offer
Only name, advertiser_id and destination_url are required. Macros in the destination are filled in at click time; {click_id} is what the advertiser must send back.
curl -s "${auth[@]}" -X POST $API/offers -d '{
"name": "Acme spring sale",
"advertiser_id": "ADV",
"status": "active",
"visibility": "public",
"currency": "USD",
"destination_url": "https://acme.example/landing?cid={click_id}&src={source}",
"conversion_method": "server_postback",
"session_duration_hours": 720
}'
session_duration_hours is the click-to-conversion attribution window (720 hours is 30 days). Other defaults worth knowing: redirect mode http302, attribution last_touch, no cookies.
4. Add a goal and a payout
A goal is the result you pay for. Its key is what postbacks send in goal.
curl -s "${auth[@]}" -X POST $API/offers/OFFER/goals -d '{"name":"Sale","key":"sale","event_category":"sale","revenue_semantics":"from_sale_amount"}'
curl -s "${auth[@]}" -X POST $API/offers/OFFER/payouts -d '{
"goal_id": "GOAL", "payout_type": "percent_of_sale", "payout_percentage": "10",
"revenue_type": "percent_of_sale", "revenue_percentage": "14",
"currency": "USD", "is_default": true, "status": "active"
}'
Payout types are fixed, percent_of_sale, fixed_plus_percent, per_click, per_mille, per_sku, kpi_scaled, tiered and blank. Money is always a decimal string. See billing and payouts for overrides, tiers and scrub.
5. Give the partner access and build the link
Public offers are open to every active partner. For require_approval offers grant access first with PUT /partners/{id}/offers/{offerId} (see partners) or approve the partner's application.
A native tracking link is https://<tracking-domain>/c/<offer hash>/<partner hash>, where the hashes are the hash_id fields of the offer and the partner:
curl -s "${auth[@]}" $API/offers/OFFER | jq -r .hash_id # OFFER_HASH
curl -s "${auth[@]}" $API/partners/PARTNER | jq -r .hash_id # PARTNER_HASH
curl -s "${auth[@]}" "$API/tracking-domains?filter[status]=active" | jq -r '.data[].host'
Or let the API build it. POST /offers/{id}/tracking-link returns the native link on the default tracking domain plus every other link style, the impression URL and, on request, pixels and a QR code:
curl -s "${auth[@]}" -X POST $API/offers/OFFER/tracking-link \
-d '{"partner_id":"PARTNER","params":{"sub1":"newsletter-42"}}' | jq -r .url
The admin portal's Traffic, Link builder does the same with sub1 to sub10, QR codes and pixels.
6. Click it
curl -si "https://go.yourbrand.com/c/OFFER_HASH/PARTNER_HASH?sub1=newsletter-42&test=1"
You get a 302 to the destination with {click_id} replaced, and an X-Click-Id response header. test=1 marks the click as test traffic: it is stored and shows in the logs with is_test set, but is excluded from reports and never reaches the ledger.
7. Report a conversion
This is what the advertiser's server does after the sale. Replace the click id:
curl -s "https://go.yourbrand.com/p?click_id=CLICK_ID&goal=sale&txn_id=ORDER-1001&amount=49.90¤cy=USD&security_token=TOKEN&test=1"
{"status":"created","conversion_id":"01J...","conversion_status":"approved"}
Send the same request again and the answer is {"status":"duplicate", ...}: conversions de-duplicate on txn_id per offer and goal. See conversion tracking methods.
8. Look at it
In the admin portal open Insights, Logs and the Conversions tab: the row shows the matched click, the payout entry that priced it (here 10% of 49.90 = 4.99) and every decision taken. Insights, Investigator finds the click or conversion from any id, IP or email, and the testers replay and explain traffic without writing data.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Click returns 204 or your fallback URL | Offer paused or expired, partner inactive or blocked, or a rule denied it. The click log has the invalid_reason. |
Postback answers rejected with invalid_token | security_token missing or wrong for an advertiser in token mode. |
unmatched | The click_id is unknown (typo, other tenant) or its click was never recorded. Without a click id and no other match the conversion is stored but unattributed. |
rejected with expired_session | Conversion arrived after session_duration_hours. |