19 guides · Conversion APIs
Conversion API events still have a contract
A conversions API is a POST from your backend. No network tab. No Pixel Helper. The vendor returns 200 for conversion API events it will never attribute. These pages are the envelope, the clock, and the match keys.
One conversion API JSON cannot serve every vendor
Meta Conversions API event_time is seconds. Reddit CAPI event_at is milliseconds. LinkedIn conversionHappenedAt is milliseconds and still needs user.userIds. TikTok timestamp is ISO 8601. A shared conversion API event named event_time will be wrong on at least one hop.
What is a conversion API
A conversion API is a server POST that sends conversion API events your backend already knows: purchases, leads, app events. Meta names it the Conversions API (CAPI). TikTok names it Events API. Google names it Measurement Protocol. Same job, incompatible JSON.
Two pipes, one conversion
The recommended setup for Meta, TikTok, and others is browser pixel plus conversion API events, deduplicated on event_id. Drop either side without a plan and you undercount or double-count.
One event_id, two transports
Meta, TikTok, and others drop a duplicate conversion when the same event_id arrives on the pixel and the conversion API. Generate it once, persist it, send it on both pipes.
A conversion with nobody on it
Match quality is how confidently the platform attaches your event to a user. Click ids score high. Hashed email and phone help. IP plus user-agent are weak but real. Empty user data is a dark event.
Tell Meta where the event happened
Meta CAPI requires action_source so the event is filed as website, app, phone_call, chat, physical_store, system_generated, or other. website is not the default you hope it is if you omit the field.
Your API host is not a landing page
Conversion APIs want the URL of the page where the event happened. Sending https://api.yoursite.com/capi is a common helper-library bug and it wrecks domain quality.
sGTM is a proxy. CAPI is your job.
Server-side Google Tag Manager is a first-party collector that forwards to vendors. Direct CAPI from your backend skips the tag manager. Both are server events. They are not the same architecture.
Test events are not a lower environment
Meta's test_event_code and vendor debug flags keep QA out of production reporting. Forgetting to strip them, or never using them, are both ways to lie to yourself.
200 means the server was awake
PostHog capture, Segment track, and several ads CAPIs return 200 for payloads they will not ingest. Validate the body before you ship. Do not use status code as the contract.
Retry the body, not a new conversion
Retry on 429 and 5xx with the same body. A new event_id on retry double-counts. A retry storm from a cron that cannot remember success double-counts even harder.
The conversion happened in Salesforce
Offline conversions upload events that never happened in the browser: phone sales, in-store POS, Salesforce stages. Matching is PII-heavy. Timestamps are usually delayed. Dedup against any pixel you already fired.
Enhanced conversions are hashed PII on the Ads tag
Enhanced conversions send hashed first-party data with the Google Ads conversion tag or via the API. It is not GA4. It is not a replacement for gclid. It is extra matching when cookies are thin.
Value without currency is a non-event
Purchase events need a number and a three-letter currency. USD is not a symbol. 19,99 is not a JSON number in the US. Meta, GA4, and Floodlight all refuse to optimize on empty value.
Purchse is a custom event whether you meant it
Pinterest standard events are lowercase (pagevisit, checkout, addtocart). Meta is PascalCase (Purchase, Lead, AddToCart). Snap is UPPER_CASE. A typo becomes a custom event and still 200s.
Do not fire the whole funnel on thank-you
Funnel events exist so the platform can optimize toward the next step. Firing all of them on the thank-you page teaches the model that every user is a buyer. Firing none of them except Purchase starves upper-funnel learning.
A refund is a measurement event
If you send Purchase and never send Refund, the ads platform keeps spending toward orders that came back. Meta, GA4, and several CAPIs have refund events. Use the original transaction id.
CAPI returned 200. Test Events is still empty.
Conversions API not working usually means HTTP 200 and an empty Test Events panel. Count event_time digits, strip test_event_code in prod, hash email not IP, match Pixel ID and event_id, and lint the JSON before you debug the token.
Check the CAPI body before Test Events
A conversion API validator checks CAPI JSON against the vendor contract: Meta event_time in seconds, hashed em, action_source, event_source_url, Purchase value and currency. Paste the body. HTTP 200 is not that check.