Conversion Tracking
Learn how to track when clicks turn into customers, signups, or any other conversion event — and attach the revenue behind each one so Track Link can compute ROI and ROAS for your campaigns.
Overview
Conversion tracking allows you to measure the effectiveness of your links by tracking when users complete desired actions (purchases, signups, form submissions, etc.) after clicking your tracked links.
Which method should I use?
There are two ways to report a conversion. The right one depends on a single question: do you control the page where the sale happens?
JavaScript snippet
You own the destination site and can add a script tag to the thank-you page. Easiest setup — the script captures the click ID and reports the sale for you.
Server-to-server postback
You don't own the checkout — you promote an affiliate offer on ClickBank, WarriorPlus, Digistore24 or similar. The network calls your postback URL when the sale clears.
How It Works
- User clicks your tracked link
A unique
utm_clickparameter is added to your destination URL automatically. - Track Link script captures it
Our lightweight tracking script automatically stores the click ID in localStorage.
- Register the conversion (with revenue)
Call
track()when the user completes a conversion, passing the order value so we can attribute revenue back to the link and campaign.
Quick Start (Recommended)
The easiest way to implement conversion tracking is using our tracking script. Add this snippet to your website:
1. Add the Tracking Script
Add this script to every page of your website (ideally in the <head>):
<script src="https://api.gettrack.link/t.js" data-api="https://api.gettrack.link"></script>
2. Track Conversions
Call track(eventType, details) when a user completes a desired action. Pass a value on revenue-generating events (like sales) so Track Link can roll up revenue, ROI and ROAS:
// A sale, with revenue (powers ROI / ROAS)
track('sale', {
value: 49.99, // Order total
currency: 'USD', // ISO code (defaults to USD)
event_name: 'Checkout' // Optional label
});
// A lead / signup (no monetary value)
track('lead', {
event_name: 'Newsletter signup'
});
// You can also attach the user who converted
track('sale', {
value: 49.99,
currency: 'USD',
event_name: 'Checkout',
id: 'user_12345', // Your internal user ID
name: 'John Doe',
email: '[email protected]',
metadata: { orderId: 'ord_987', plan: 'pro' }
});3. Example: After Purchase
// On your checkout success page
document.addEventListener('DOMContentLoaded', function() {
track('sale', {
value: order.total, // The revenue for this conversion
currency: order.currency, // e.g. 'USD'
event_name: 'Checkout',
id: currentUser.id,
name: currentUser.name,
email: currentUser.email,
metadata: { orderId: order.id }
});
});Backward compatible: trackConversion() still works exactly as before, and value is always optional — omit it for leads and signups.
That's it! The script automatically captures the click ID from the URL and cleans up after a successful conversion.
How the Script Works
The tracking script (t.js) is a lightweight, dependency-free (<2KB) JavaScript file that:
- Automatically detects the
utm_clickparameter in the URL - Stores the click ID in localStorage for persistence
- Provides the global
track()andtrackConversion()functions - Reports conversion
valueandcurrencyso revenue, ROI and ROAS roll up automatically - Automatically cleans up after a successful conversion
- Handles errors gracefully without breaking your site
Server-to-Server Postback (Affiliate Networks)
Use a postback when you don't control the destination page — the normal situation when you promote someone else's offer. The advertiser owns the checkout, so you can never install a script on it. Instead, the network calls a URL of yours the moment a sale is approved. Nothing runs in the visitor's browser, so ad blockers, cookie banners and closed tabs can't break it.
Your postback URL
https://api.gettrack.link/api/postback?click_id={CLICK_ID}&amount={AMOUNT}¤cy=USD&event=saleReplace {CLICK_ID} and {AMOUNT} with your network's own macros — see the table below.
Step 1 — Pass the click ID into the network
Every tracked link appends its click ID to your destination URL as utm_click. It looks like this:
https://the-offer.com/buy?utm_click=C9HW979UQ47Q69
Forward that value into the network's own tracking field so it comes back to you on the sale. The ID is 14 uppercase characters — deliberately short, because ClickBank truncates anything over 24 and a truncated ID silently never matches.
Step 2 — Register the postback with your network
| Network | Their field for your click ID | Postback URL to paste |
|---|---|---|
| ClickBank | TID | https://api.gettrack.link/api/postback?click_id=[[tid]]&amount=[[amount]] |
| WarriorPlus | cf_aff_sub | https://api.gettrack.link/api/postback?click_id=%%SUBID%%&amount=%%AMOUNT%% |
| Digistore24 | custom / cid | https://api.gettrack.link/api/postback?click_id={custom}&amount={amount_brutto} |
| JVZoo | cparam / subid | https://api.gettrack.link/api/postback?click_id={cparam}&amount={amount} |
| Any other network | subid / s1 / aff_sub | https://api.gettrack.link/api/postback?click_id={their_macro}&amount={their_macro} |
Macro names change over time — always copy the exact macro from your network's own postback documentation. Track Link accepts whatever you send it (see the parameter names below).
Accepted parameters
Networks all name their parameters differently and none let you reshape the callback, so the endpoint accepts every common spelling. Parameter names are case-insensitive.
| What it is | Accepted names | Required |
|---|---|---|
| Click ID | click_id, cid, tid, subid, sub_id, aff_sub, s1, utm_click | Yes |
| Sale value | amount, value, payout, revenue, total, price, sale_amount | No |
| Currency | currency, cur, ccy — defaults to USD | No |
| Event type | event, event_type, type, action — defaults to sale | No |
| Order reference | order_id, oid, txid, transaction_id, receipt | No |
| Anything else | Unrecognised parameters (sub2…sub5) are stored with the conversion | No |
Amounts are forgiving: 49.95, $49.95 and 49,95 are all read as 49.95.
What the endpoint returns
Always 200 OK with the body 1 — including for an unknown or already-converted click. Networks treat any non-2xx as a failure and retry, so a duplicate is never reported as an error. Each click records one conversion: if the same click is posted twice, the first value is kept.
Test it before you go live
Click one of your own tracked links, copy the utm_click value out of the address bar, then run:
curl "https://api.gettrack.link/api/postback?click_id=PASTE_ID_HERE&amount=9.99&event=sale"
The conversion appears on that link's detail page under Conversions. Use a throwaway test link rather than a live campaign, so you don't put fake revenue into real reporting.
Manual Implementation
If you prefer not to use our script, you can implement conversion tracking manually.
API Endpoint
POST https://api.gettrack.link/api/conversionsRequest Body
{
"click_id": "abc123-def456-ghi789",
"value": 49.99, // Optional - revenue for this conversion
"currency": "USD", // Optional - ISO code, defaults to USD
"event_type": "sale", // Optional - "sale" | "lead" | "signup" | custom
"event_name": "Checkout", // Optional - human label
"user_id": "user_12345", // Optional
"name": "John Doe", // Optional
"email": "[email protected]", // Optional
"host": "yoursite.com", // Optional
"page_url": "https://yoursite.com/success", // Optional
"metadata": { "plan": "pro" } // Optional
}Response
{ "success": true }The response is deliberately identical whether or not the click existed, so the endpoint can be called from a public page without revealing which click IDs are valid. A repeat call for a click that already converted also returns success and changes nothing.
Manual JavaScript Example
Capture the click ID and register conversions manually:
// 1. Capture click_id on page load
const urlParams = new URLSearchParams(window.location.search);
const clickId = urlParams.get('utm_click');
if (clickId) {
localStorage.setItem('link_track_id', clickId);
}
// 2. Register conversion when needed
async function registerConversion(userData) {
const clickId = localStorage.getItem('link_track_id');
if (!clickId) return;
try {
const response = await fetch('https://api.gettrack.link/api/conversions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
click_id: clickId,
value: userData?.value, // Optional - revenue for ROI / ROAS
currency: userData?.currency, // Optional - defaults to USD
event_type: userData?.eventType,
event_name: userData?.eventName,
user_id: userData?.id,
name: userData?.name,
email: userData?.email,
host: window.location.hostname,
page_url: window.location.href
}),
});
if (response.ok) {
localStorage.removeItem('link_track_id');
}
} catch (error) {
console.error('Conversion tracking failed:', error);
}
}Server-Side Examples
Node.js / Express
app.post('/checkout/success', async (req, res) => {
const { clickId, user, order } = req.body;
await fetch('https://api.gettrack.link/api/conversions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
click_id: clickId,
value: order.total, // Revenue for ROI / ROAS
currency: order.currency, // e.g. 'USD'
event_type: 'sale',
event_name: 'Checkout',
user_id: user.id,
name: user.name,
email: user.email,
}),
});
res.json({ success: true });
});Python
import requests
def register_conversion(click_id, value=None, currency=None,
event_type=None, event_name=None,
user_id=None, name=None, email=None):
response = requests.post(
'https://api.gettrack.link/api/conversions',
json={
'click_id': click_id,
'value': value, # Optional - revenue for ROI / ROAS
'currency': currency, # Optional - defaults to USD
'event_type': event_type,
'event_name': event_name,
'user_id': user_id,
'name': name,
'email': email,
}
)
return response.json()
# A sale, with revenue
register_conversion(
click_id='abc123-def456-ghi789',
value=49.99,
currency='USD',
event_type='sale',
event_name='Checkout',
user_id='user_12345',
name='John Doe',
email='[email protected]'
)
# A lead, no value
register_conversion(
click_id='abc123-def456-ghi789',
event_type='lead',
event_name='Demo request'
)Best Practices
- Use the tracking script - It handles edge cases and cleanup automatically.
- Send revenue on sales - Pass
value(andcurrency) on purchases so Track Link can compute ROI and ROAS for each campaign. Leave it off for leads and signups. - Include user data when possible - This helps you identify which users converted.
- Track meaningful conversions - Focus on actions that matter (purchases, signups, not page views).
- Test in development - Verify conversions are being tracked before going live.
- Server-side for critical conversions - For purchases, consider server-side tracking as a backup.
Viewing Conversions
Once conversions are registered, you can view them in your dashboard:
- Go to the Links page and click on a specific link
- The link details page shows conversion count and rate
- Click on individual clicks to see associated conversion data
Frequently Asked Questions
What is a server-to-server (S2S) postback?
A server-to-server postback is a plain HTTP request your affiliate network sends to a URL you register with them, at the moment a sale is approved. Nothing runs in the visitor's browser, so it works even when you do not control the checkout page — which is the normal situation for an affiliate promoting someone else's offer. Track Link's postback URL is https://api.gettrack.link/api/postback and it accepts a GET request.
When should I use a postback instead of the JavaScript snippet?
Use the JavaScript snippet when you own the destination site and can add a script tag to the thank-you page. Use the postback when you do not — for example when you promote a ClickBank, WarriorPlus or Digistore24 offer, where the advertiser owns the checkout and you can never install code on it. The postback is also more reliable in general, because it is not affected by ad blockers, cookie banners or the visitor closing the tab.
Where do I get the click ID for the postback?
Track Link appends it to your destination URL automatically as ?utm_click=. It is a 14-character uppercase code such as C9HW979UQ47Q69. Pass that value into your affiliate network's tracking field (ClickBank calls it TID, most others call it subid or s1), and the network will hand it back to you in the postback so the sale can be matched to the exact click that produced it.
Why is the Track Link click ID only 14 characters?
Affiliate networks cap the length of their tracking-id field — ClickBank truncates anything over 24 characters — so a long identifier silently fails to round-trip and the conversion is never matched. The 14-character uppercase format fits inside every major network's limit, and uses a single letter case so that networks which normalise parameter casing cannot break the match.
Does Track Link count a duplicate postback twice?
No. Each click can record one conversion, so a retried or repeated postback for the same click is ignored and the first recorded value is kept. The endpoint still answers 200 in that case, because networks treat any non-2xx response as a failure and will keep retrying.
Need Help?
If you have questions about implementing conversion tracking, please contact us at [email protected]