All articles
12 min read

How to Track Facebook Ad Conversions for Affiliate Offers

Two heavy server machines linked by a taut cable with a small token traveling along the wire

A media buyer running a gambling offer in LATAM pulls up Ads Manager Monday morning: 40 purchases logged for the weekend. Their CRM, fed by the affiliate network’s postbacks, shows 71 deposits against the same campaign for the same window. Nobody stole 31 conversions — Facebook simply never saw them. The deposit happened two days after the click, on the advertiser’s domain, in a session with no Meta pixel loaded at all. If you’re trying to track Facebook ad conversions for affiliate offers and the numbers don’t reconcile, this is almost always why, and it’s fixable with the right layering of signal, not a bigger budget.

Why Facebook Under-Reports Affiliate Conversions

The standard Facebook Pixel is designed around a same-domain, same-session assumption: user clicks ad, lands on your site, converts on your site, pixel fires on your site. Affiliate funnels break every part of that chain. The click happens on your prelander or filtered tracking domain, the pixel (if any) fires there, and then the user is redirected to the advertiser’s domain — a casino, a dating platform, a broker — where the actual conversion event (deposit, FTD, verified signup) happens with zero Meta tracking present. Facebook has no code running on the advertiser’s checkout, deposit form, or KYC flow, so it structurally cannot see the event that actually matters to you.

Layer onto that the standard browser degradation everyone already deals with: Safari ITP truncating cookie life, ad blockers stripping pixel requests outright, users converting on a different device than the one that clicked. Industry estimates on lost browser-side signal commonly cite a range around 10–40% depending on GEO and vertical, and that’s before accounting for the cross-domain gap that’s specific to affiliate models. Stack both problems and it’s routine to see Facebook’s reported conversions sit at half or less of what your CRM actually recorded.

The consequence isn’t just a reporting annoyance. Facebook’s algorithm optimizes toward whatever signal it receives. If it only sees 40 of 71 deposits, it’s optimizing your budget toward whichever audience produced those 40 — which may not be your best-converting segment at all. You end up paying to scale the wrong lookalikes while your actual highest-LTV traffic gets no algorithmic credit.

The Three Layers of Tracking You Need

Fixing this requires accepting that no single signal source is complete on its own. Three layers, each catching what the others miss:

  • Browser pixel — cheap, fast, useful for early-funnel signals like landing page views, but blind to anything past the redirect and unreliable even for what it can technically see.
  • Conversions API (CAPI) — sends the same standard events server-to-server, recovering browser-blocked events for signals your own domain can still observe (page view, lead form submit, initial registration).
  • S2S postback — fires directly from your backend or CRM the instant a real downstream status changes, independent of any browser session, cookie, or domain boundary. This is the only layer that can see a deposit that happens two days later on someone else’s domain.

CAPI and postback solve different halves of the problem. CAPI recovers events your own tracking domain could have seen but the browser lost. Postback reports events your tracking domain was never present for in the first place, because they happened downstream on the advertiser’s system. For affiliate media buying specifically, postback is what closes the gap that actually costs you money — deposits, FTDs, verified accounts — while CAPI cleans up the standard-event noise around it.

If you want the deeper mechanical breakdown of how each layer behaves under ad-blocker and cookie pressure, see Pixel vs Conversions API vs S2S Postback.

A single thread passing through three separate gates, each gate letting through a different portion of light

Building the Signal Chain: Click ID to Conversion Event

The mechanism that ties all three layers together is a single persistent identifier that survives the entire journey — click, redirect, advertiser domain, conversion, and back to Facebook. Here’s the path:

  1. Click lands on your tracking domain. Your tracker generates a click_id (or fbclid-derived equivalent) and logs the click with campaign, ad set, ad, and any sub-parameters you need for segmentation.
  2. click_id passes through to the advertiser. It rides along as a URL parameter through the redirect chain to the offer’s landing page, then gets carried through their signup/deposit flow — usually via a hidden field, subid parameter, or affiliate tracking token the advertiser’s system already supports.
  3. Advertiser fires a postback on conversion. The moment a deposit clears or a lead qualifies, the advertiser’s backend calls your postback URL with the click_id and a status.
  4. Your tracker matches click_id back to the original click, recovering the full attribution chain: which ad, which creative, which GEO, which placement actually produced this deposit.
  5. A CAPI event fires to Facebook, tagged with the same event_id used for dedup, carrying whatever identity signal you have (hashed email, external ID, click-time fbc/fbp if captured) so Meta’s matching engine can stitch it back to the original ad exposure.

A representative postback URL, with the macros your tracker needs populated by the advertiser’s system:

https://track.yourdomain.com/postback?click_id={click_id}&status=deposit&payout={payout}&currency={currency}&event_id={click_id}_deposit

And the CAPI payload your backend sends once that postback lands, using the same event_id for dedup against anything the browser pixel might still fire:

{
  "data": [
    {
      "event_name": "Purchase",
      "event_time": 1751980800,
      "event_id": "abc123click_deposit",
      "action_source": "website",
      "user_data": {
        "em": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
        "external_id": "abc123click"
      },
      "custom_data": {
        "currency": "USD",
        "value": 45.00
      }
    }
  ]
}

The event_id is what prevents double-counting if a browser pixel also happened to catch a lighter-weight signal earlier in the same session — Facebook dedups any event sharing that ID between pixel and CAPI submissions.

Mapping Conversion Status to Facebook Events

Affiliate verticals rarely have one conversion — they have a funnel of statuses, and each one may or may not deserve to reach Facebook as a distinct optimization event. A registration isn’t a deposit, and a deposit isn’t a rebill. Sending all of them to Facebook as generic Purchase events destroys the algorithm’s ability to tell a $2 lead from a $200 FTD.

Funnel statusTypical Facebook eventSend to Facebook?
Landing page viewPageViewOptional — low value, high volume
Form submit / registrationLead or CompleteRegistrationYes — early optimization signal
First deposit (FTD)PurchaseYes — primary optimization target
Rebill / repeat depositCustom event, e.g. RebillSometimes — useful for LTV-aware bidding, but don’t conflate with FTD
Chargeback / refundNot sent, or handled via CRM reconciliation onlyNo — Facebook has no native negative-event flow

The mapping should live as configuration, not code — every new status your vertical introduces (a KYC-verified status, a second-deposit milestone) needs to be assignable to a Facebook event name without an engineering ticket. This is exactly the gap DarkCore’s pixel setup closes: event mapping is per-status, per-pixel, so deposit can map to Purchase for one offer and to a custom event for another, without touching a postback template every time a new vertical goes live.

Common Mistakes

  • Sending every postback status as Purchase. This flattens registrations, deposits, and rebills into one signal, which wrecks Facebook’s ability to optimize toward high-value users specifically. The algorithm ends up chasing volume instead of deposit quality.
  • Skipping event_id dedup between pixel and CAPI. Without a shared event ID, the same conversion gets counted twice — once from whatever browser signal fired, once from the server-side event — inflating your reported conversions and quietly corrupting ROAS math.
  • Losing the click_id across the redirect to the advertiser’s domain. If the affiliate network or advertiser doesn’t reliably pass your click identifier through their own signup/deposit flow, the postback that eventually fires has nothing to match against, and the conversion is unattributed even though your backend technically received it.
  • Treating CAPI as a replacement for postback. CAPI only recovers events your own domain was present for. It cannot report a deposit that happened entirely inside the advertiser’s system days later — that gap only closes with a real S2S postback from the advertiser or network.
  • Firing CAPI events without delay-awareness. A deposit that happens 3 days after the click still needs to attribute to the original ad exposure. If your event timestamp or attribution window logic assumes same-session conversion, Facebook may reject the event as low-quality or fail to match it to the original click at all.

A hand releasing a small marked token that travels along a long winding wire toward a distant lit window

Setting Ad Account Structure Around Delayed Signal

Once the postback-to-CAPI chain is live, there’s a second-order problem: your ad account structure needs to tolerate the delay between spend and confirmed signal. If deposits land 2-5 days after the click, campaigns optimizing on a 1-day attribution window will always look worse than they are, and Facebook’s automated rules — which only ever see FB-side pixel data — may pause or throttle a campaign that’s actually performing well in your CRM.

Practical adjustments:

  • Set attribution windows in Ads Manager to match your actual median time-to-deposit, not the platform default.
  • Don’t let Facebook’s own automated rules make budget decisions off pixel-only data if your real conversion event is deep-funnel and delayed — those rules have no visibility into what your CRM already confirmed.
  • Keep enough historical spend in each ad set before judging performance; a campaign that looks cold on day one because deposits haven’t posted yet can look completely different by day four once postbacks catch up.

This is where automation built around your actual backend data earns its keep — DarkCore’s stream and pixel setup lets auto-rules act on confirmed CRM deposits and revenue rather than whatever partial signal Facebook’s own dashboard happens to have at that moment, which matters most in exactly the delayed-conversion scenario affiliate offers create by default.

Verifying the Setup Actually Works

Before trusting the numbers, confirm each link in the chain independently:

  1. Fire a test click through your tracking link and confirm the click_id is logged with correct campaign/ad-set/ad IDs.
  2. Manually trigger (or wait for) a test postback from the advertiser/network and confirm your tracker matches it to the original click, not a stray or unmatched conversion.
  3. Check Facebook’s Events Manager for the corresponding CAPI event — confirm the event name, value, and event_id all landed as expected, and that match quality (email/external ID coverage) isn’t flagged as low.
  4. Compare Ads Manager’s reported conversions for a given day against your CRM’s confirmed conversions for the same cohort a few days later, once delayed events have had time to post. A persistent, large gap after that window means a step in the chain — usually click_id passthrough — is still broken.

FAQ

Does CAPI replace the Facebook Pixel entirely?

No. CAPI is meant to run alongside the pixel, with event_id-based dedup so overlapping events aren’t double-counted. The pixel still has value for cheap, high-volume, early-funnel signals; CAPI’s job is recovering what the browser drops, not replacing the browser layer.

Can I send deposit events to Facebook if the advertiser doesn’t support S2S postback?

Only partially, and only if you control some part of the conversion flow yourself — for example if your prelander redirects through a domain you can instrument, or the advertiser exposes any kind of API/webhook. If the advertiser’s system is a pure black box with no postback and no API, there is no reliable way to get that specific event back to Facebook, and you should be honest with yourself that your optimization signal for that offer will always be incomplete.

How long should my Facebook attribution window be for affiliate offers with delayed deposits?

Set it to cover your actual median time-to-deposit, which you can pull straight from your tracker’s click-to-conversion timestamps. A 1-day click window on an offer where deposits typically post on day 2-3 will systematically under-attribute, regardless of how well your CAPI and postback setup works.

What’s the minimum identity data CAPI needs to match an event well?

At minimum, a hashed email or external ID tied to the original click. Adding IP, user agent, and the fbc/fbp browser IDs captured at click time (if you had any browser presence at all) meaningfully improves match rate, especially for events that fire days after the original session ended.

Getting the Full Picture Back

None of this requires exotic infrastructure — it requires accepting that Facebook’s dashboard was never going to see your full funnel on its own, because the conversion that pays your bills happens somewhere Facebook’s pixel was never invited. Postback recovers the event, CAPI gets it back to Meta with dedup intact, and status mapping keeps the algorithm optimizing toward the deposits that actually matter instead of a flattened, generic “purchase.” DarkCore’s stream and pixel configuration handle this chain by default — click_id passthrough, per-status postback routing, and CAPI dedup are wired together rather than stitched by hand. If your Ads Manager numbers and your CRM haven’t matched in a while, it’s worth checking the chain before you check the budget — talk to us on Telegram.

  • facebook conversions
  • capi
  • affiliate tracking
  • s2s postback
  • attribution