SHAZAM
Join ShazamCommunity

S2S Postback Tracking: The Complete Affiliate Guide

A practical guide to S2S postback tracking for affiliates: click IDs, postback URLs, testing, deduplication, and fixing conversions your tracker never received.

Published October 14, 2025Updated July 18, 202614 min read

You send 40,000 clicks in a month. Your tracker shows 312 conversions. The advertiser's panel shows 341. Nobody is lying, and nobody is stealing from you — somewhere in the chain, 29 conversions lost the thread that connects them back to a click. That gap is worth real money, and it is almost always a fixable configuration problem rather than a mystery.

S2S postback tracking is the mechanism that keeps that thread intact. It replaces the fragile browser-side pixel with a direct server-to-server call, and once you understand what is actually moving between the two machines, most conversion discrepancies stop being spooky and start being debuggable.

This guide walks the whole path: what a click ID is and where it can get dropped, how to read a postback URL parameter by parameter, why pixels degrade while postbacks do not, how deduplication works, how to test the whole loop before you spend a cent, and what to check when two dashboards disagree.

What a postback actually is

Strip away the jargon and a postback is an HTTP GET request. The advertiser's server calls a URL on your tracker's server. That URL contains a value — the click ID — that your tracker handed to the advertiser at click time. Your tracker looks up that click ID in its own database, finds the original click with all its attached metadata, and marks it converted.

That is the whole idea. Two servers, one shared identifier, no browser in the middle.

The reason this matters is that the browser is the least reliable participant in the funnel. It can be an in-app webview with no persistent storage. It can block third-party cookies by default. It can have an extension that kills the tracking script. The advertiser's server, by contrast, will happily make an outbound HTTP request every single time, because nothing in the user's environment can reach it.

The vocabulary, briefly

You will see the same concept called a postback, a server-to-server callback, S2S tracking, or a conversion callback. Some platforms call the click ID a clickid, others transaction_id, aff_sub, subid, sid, or cid. Do not assume the naming carries meaning — read the advertiser's integration doc and match their field names exactly. Half the broken setups I have unpicked were caused by an affiliate passing clickid to a platform that reads transaction_id.

The click ID is the entire system

Everything else in postback tracking is decoration. If the click ID survives the round trip, you get paid correctly. If it does not, nothing else you configure matters.

Your tracker generates the click ID at the moment of the click. It is a unique string — typically a UUID or a hashed sequence — created before the redirect fires. At that instant your tracker writes a row containing the click ID plus every dimension it knows: timestamp, IP, user agent, geo, device, offer, and all your sub-IDs. That row sits waiting.

The click ID then travels outward in the redirect URL. It rides through the advertiser's landing page, through their registration flow, into their internal user record, and eventually back to you inside the postback. The longer that journey, the more places it can get lost.

Where click IDs die

  • Your own landing page strips parameters. A common one. You run a pre-lander, and the outbound link on it is hardcoded rather than dynamically appending the incoming query string. The click ID reaches your lander and dies there.
  • A redirect chain drops the query string. Some redirect services, link shorteners, and CDN rules rewrite URLs without preserving parameters. Test every hop.
  • The advertiser's funnel loses it between steps. If registration is a multi-page flow and the click ID is only in the URL of step one, it can vanish by step three unless the advertiser stores it in a session or hidden field. This is their side, but it is your revenue, so ask.
  • Case sensitivity and encoding. ClickID is not clickid on most systems. And if your click ID contains characters that need URL encoding, an unencoded pass can truncate it.
  • The user opens the link, closes it, and returns later through a different path. Now the advertiser has a user with no click ID at all, and no amount of postback configuration will recover it.

Reading a postback URL parameter by parameter

A typical postback URL you would hand to an advertiser looks something like this:

https://track.yourdomain.com/postback?cid={clickid}&payout={payout}&currency={currency}&status={status}&txid={transaction_id}&goal={goal_id}

The curly braces are macros. The advertiser replaces them with real values when they fire the call.

Parameter What it carries Why you want it
cid / clickid The unique click identifier you generated The join key. Without it nothing matches.
payout The commission amount for this conversion Lets your tracker calculate real ROI per sub-ID instead of assuming a flat payout.
currency ISO code such as USD or EUR Prevents a EUR payout being counted as USD, which quietly inflates your reported profit.
status approved, pending, rejected, chargeback Enables lifecycle handling rather than treating every fire as final revenue.
txid The advertiser's own unique transaction reference The deduplication key. Covered below.
goal Which event fired: registration, deposit, qualification Essential for any funnel with more than one payable event.

Not every advertiser supports every macro. Ask for their macro list rather than guessing, because a macro that does not exist on their side is usually passed through as the literal string {payout}, and your tracker will either reject it or record a payout of zero.

Dynamic payout is worth insisting on

If you accept a static payout in your tracker instead of a dynamic {payout} macro, every conversion gets recorded at your assumed rate. On a fixed CPA that is fine. On a tiered deal, a hybrid, or anything revshare-flavoured, it is fiction. You will optimise toward placements that look profitable because the tracker assumed a payout they never actually earned. If you are comparing offers on earnings per click and the other core metrics, a static payout assumption corrupts every one of them at the source.

The full lifecycle, click to fire

Walking this end to end makes the failure points obvious.

  1. User clicks your link. The request hits your tracker.
  2. Tracker generates the click ID and writes the click row with all sub-IDs, geo, device, and timestamp.
  3. Tracker issues a redirect to the offer URL, appending the click ID in whatever parameter the advertiser specified.
  4. Advertiser's landing page receives it. They store the click ID in a cookie, session, or hidden form field on their own domain — this is first-party storage on their side, which is far more durable than anything cross-site.
  5. User registers. The advertiser attaches the click ID to the new user record in their database. From here it is permanent and no longer dependent on any browser state.
  6. User converts — a deposit, a purchase, a qualified action. Could be minutes later. Could be eleven days later.
  7. Advertiser's server fires the postback, substituting real values into the macros in the URL you gave them.
  8. Your tracker receives the call, looks up the click ID, validates it, checks for duplicates, and records the conversion against the original click with all its dimensions intact.
  9. Your tracker responds with a 200 status. Most advertisers log non-200 responses and some retry; many do not.

Note step 5. Once the click ID is bound to a user account on the advertiser's server, browser restrictions become completely irrelevant. A conversion that happens three weeks later on a different device still fires correctly. That durability is the real argument for S2S postback tracking, and it is why offers with long consideration cycles — high-ticket funnels especially — are effectively untrackable any other way.

Why pixels break and postbacks do not

A conversion pixel is an image or script tag on the advertiser's confirmation page. It fires in the user's browser, and it identifies the click by reading a cookie your tracking domain set earlier. Every one of those dependencies is now under pressure.

Cookie lifetime restrictions. Browsers have progressively shortened how long script-set cookies survive, in some configurations to a matter of days or even a single day. Any conversion with a delay longer than that window is invisible to a pixel. Deposit journeys in finance and iGaming routinely run longer than that.

Third-party context. A cookie set by your tracking domain while the user is browsing the advertiser's domain is a cross-site cookie. Default blocking of those is now normal rather than exotic.

In-app browsers. A large share of paid social and messenger traffic never touches a real browser. It opens in an embedded webview inside the app. Those webviews often have isolated or ephemeral storage, so a cookie set at click time may not exist at conversion time even seconds later. If most of your volume is Telegram or messenger traffic, pixel-based tracking will understate you badly.

Ad blockers and script failures. Blockers commonly filter known tracking domains. A pixel that never loads is a conversion that never existed as far as you are concerned.

Page-load dependency. If the user closes the confirmation page before the pixel executes, or the advertiser fires the conversion in a JavaScript modal that a slow connection never renders, the pixel silently does not fire.

A postback bypasses all five. The advertiser's backend calls your server directly, carrying the click ID as an explicit parameter. There is no cookie to expire, no script to block, no page to load.

The honest caveat: postbacks are only as good as the advertiser's implementation. If their server has a bug, queues calls and drops them under load, or fires only on a subset of events, you lose conversions in a way you cannot see from your side. Which is why testing is not optional.

Deduplication and why you need the transaction ID

Postbacks get fired twice more often than you would expect. Retry logic after a timeout, a manual conversion re-push by an account manager, a status change from pending to approved implemented as a second fire rather than an update — all of these produce a repeat call.

If your tracker counts both, your reported revenue inflates and your optimisation decisions get built on phantom conversions. The fix is the advertiser's transaction ID. Store it against the conversion, and reject any incoming postback whose transaction ID you already have for that click.

Deduplicating on click ID alone is the wrong instinct, because some funnels legitimately produce multiple conversions from one click: a registration, then a first deposit, then a second deposit under a revshare arrangement. Deduplicate on the pair — click ID plus transaction ID, or click ID plus goal plus transaction ID for multi-event setups.

Set a sensible window too. If the same transaction ID arrives 40 days later it is far more likely to be a system replay than a genuine event.

Testing a postback before you send traffic

Do this every time you take on a new offer. It takes ten minutes and it has caught broken setups on plenty of offers that were supposedly live and working for other affiliates.

  1. Generate a real click. Click your own tracking link. Do not fabricate a click ID — use one your tracker actually issued, because you also want to confirm the click row was written correctly.
  2. Capture the click ID from the redirect URL in your browser's network tab. Confirm it arrived at the advertiser's landing page URL and was not stripped by any hop in between.
  3. Fire the postback manually. Take the postback URL, substitute the real click ID and a test payout, and request it — a browser address bar or a single curl command is enough.
  4. Check the HTTP response. You want a 200 and a body your tracker considers a success. A 200 with an error message in the body is a failure that many advertisers will log as a success.
  5. Verify in your reporting. The conversion should appear against the correct offer, with the correct payout, the correct currency, and every sub-ID from the original click still attached. Sub-IDs going missing at this point is common and is the single most damaging silent failure, because it makes optimisation impossible.
  6. Fire the identical postback again. It should be rejected as a duplicate. If it creates a second conversion, fix that before you scale anything.
  7. Test each goal separately if the offer has multiple payable events.
  8. Ask the advertiser to fire a real test conversion from their end. Manual firing proves your receiver works. Only their fire proves their sender works, and their sender is the half you cannot see.

Then delete the test conversions so they do not pollute your baseline.

Misconfigurations that quietly cost you money

Postback registered against the wrong event. You are paid on qualified deposit but the postback fires on registration. Your volume looks fantastic and your revenue does not match it.

Whitelisting that blocks the caller. If your tracker sits behind a firewall or WAF that filters unknown server IPs, the advertiser's calls get rejected before your tracker sees them. Nothing appears in your logs, because nothing reached your logs. Check the edge, not just the application.

HTTP versus HTTPS mismatch. Some advertisers refuse to call insecure endpoints; some fail silently on certificate errors. An expired certificate on your tracking domain kills every postback until you renew it, and the failure mode is total silence.

Redirects on the postback endpoint. If your postback URL 301s to a canonical version, some callers follow it and some do not. Give them the final URL.

Currency assumptions. An advertiser paying in EUR while your tracker assumes USD will overstate your revenue by whatever the exchange rate difference happens to be. Small per conversion. Substantial at volume.

Ignoring status. If you count pending conversions as approved, your reported profit runs ahead of reality and corrects downward later, usually right when you have already scaled spend on the strength of it.

Rate limiting. A tracker that rate limits by IP will start dropping calls during a traffic spike, which is exactly when you can least afford it.

A worked example: what a small gap actually costs

Run the arithmetic, because "a few percent" sounds tolerable until you price it.

You are running a CPA offer at $180. In a month you drive 40,000 clicks at $0.22 CPC, so $8,800 in media spend. Your tracker records 312 conversions.

  • Recorded revenue: 312 × $180 = $56,160
  • Spend: $8,800
  • Recorded profit: $47,360

The advertiser's panel shows 341 conversions. The 29 missing ones are worth 29 × $180 = $5,220. Assuming the advertiser pays on their own count, you are not losing that cash — you are losing the information.

That matters because the missing conversions are not randomly distributed. Suppose 21 of them came from one placement, an in-app messenger source that sent 6,400 clicks and cost $1,408.

  • What your tracker showed for that placement: 18 conversions, $3,240 revenue, $1,832 profit
  • Reality: 39 conversions, $7,020 revenue, $5,612 profit

Your tracker reported an EPC of $0.51 on that source. The real EPC was $1.10. You would rank it mid-table and cap its budget, when it was your best source by a wide margin. The 29 lost conversions cost you nothing directly and cost you a great deal in misallocated spend — which is precisely why per-source verification matters more than the headline total. This is the same discipline that makes sub-ID reporting useful in the first place.

Multi-event funnels

Single-event offers are easy. Most serious verticals are not single-event.

A typical iGaming or broker funnel has a registration, a first-time deposit, and sometimes a qualification threshold — a minimum deposit, a volume requirement, or a KYC completion. Each of those should fire its own postback with a distinct goal value.

Configure them as separate goals in your tracker rather than one lumped conversion. The reason is diagnostic: registration-to-deposit ratio is one of the most informative numbers you have. A source producing plenty of registrations and almost no deposits is usually low-intent traffic or a geo mismatch, and you cannot see that if every event collapses into a single counter.

Watch the status lifecycle too. Deposits reverse. Chargebacks arrive weeks later. If your advertiser sends a status-update postback for a reversal, handle it — a conversion that flipped to rejected should stop counting as revenue, and if you are on a revshare deal with negative carryover, that reversal has consequences beyond a single row in a report.

When the numbers disagree

Some discrepancy is normal. Timezone boundaries alone will make any single day's figures differ. What you are hunting is a persistent, one-directional gap.

Work through it in this order:

  1. Align timezones. Your tracker in UTC and the advertiser's panel in UTC+2 will disagree on every daily total while matching perfectly on the monthly.
  2. Align on status. You may be counting pending; they may be reporting approved only. Or the reverse.
  3. Compare per day, not per month. A gap that appears on one specific date points at a deploy, a certificate renewal, or an outage. A gap spread evenly points at a structural configuration issue.
  4. Compare per sub-ID. If the gap concentrates in one source, the click ID is being lost on that specific path — often a placement that opens links in a webview with aggressive URL rewriting.
  5. Pull raw postback logs. Ask the advertiser for the timestamps and response codes of the calls they made. If they logged a 200 and you have no record, the problem is between your edge and your application. If they logged a timeout, the problem is your server availability. If they never fired, the problem is their configuration.
  6. Check for silent duplicate rejection. Occasionally your tracker is rejecting valid conversions as duplicates because the advertiser reuses transaction IDs across offers.

Bring evidence to your manager, not vibes. Timestamps, click IDs, and response codes get a fix in a day. A message saying your numbers look low gets you a shrug.

Working with Shazam on tracking

Tracking infrastructure is one of the things we build and maintain for our partners rather than leaving to you. That means postbacks configured and tested against each advertiser before traffic runs, sub-IDs verified end to end, and discrepancies chased directly with the platform rather than through a support queue. We also build the sites and landing pages, which removes the most common click ID failure point — a pre-lander that quietly drops your query string.

Our partners run on a 50% revenue share across crypto, forex, iGaming, gaming, high-ticket and tech, with direct platform relationships that make it possible to get raw postback logs from an advertiser when something looks off. If you would rather spend your time on traffic than on debugging why 29 conversions went missing, start on our Telegram bot or come ask questions in the community chat first.

Frequently asked questions

What is S2S postback tracking in affiliate marketing?

S2S postback tracking is a server-to-server method of recording conversions. When a user clicks your link, your tracker generates a unique click ID and passes it to the advertiser. If that user converts, the advertiser's server calls a postback URL on your tracker with the same click ID attached, and your tracker matches it back to the original click. No browser, cookie, or pixel is involved.

Is a postback more accurate than a conversion pixel?

In almost every case, yes. A pixel fires in the user's browser and depends on cookies, JavaScript execution, and the page actually loading. Cookie lifetime limits, ad blockers, in-app browsers, and cross-site restrictions all break pixels. A postback is a direct server call that carries the click ID as a parameter, so none of those conditions affect it.

Why are conversions missing from my tracker but visible in the advertiser panel?

The usual cause is a lost click ID. Check whether your landing page strips URL parameters on redirect, whether the advertiser's signup form preserves the click ID across steps, and whether you are passing the parameter name the advertiser actually expects. Also confirm the postback is configured for the correct event and that your tracker is not rejecting duplicates.

What parameters should a postback URL contain?

At minimum the click ID and a status or event type. Most setups also pass payout amount, currency, the advertiser's own transaction ID for deduplication, and the offer or goal identifier for multi-event funnels. Anything else, such as geo or device, is usually already stored against the click on your side and does not need repeating.

Keep reading

CryptoJune 30, 202611 min read

Crypto affiliate marketing in 2026: a field guide

Exchanges still pay the best lifetime economics online, but the traffic that earns them changed. What converts now, what quietly died, and how to price a program before you send traffic.

Read post