Set up server-side conversion tracking so purchases are reported accurately to Facebook, TikTok, Google, and Bing despite iOS restrictions, ad blockers, cookie loss, and cross-domain hops. Use this skill when conversions are under-reported, platform purchases do not match real orders, CAPI, Conversions API, Events API, offline conversions, click id passthrough, fbclid, ttclid, gclid, msclkid, or degraded ad optimization are mentioned.
Scanned 9/4/2026
Install to Claude Code
npx -y skills add paulasilvatech/awesome-harness-primitives --skill server-side-conversion-tracking --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Server Side Conversion Tracking?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/paulasilvatech-server-side-conversion-tracking-c007e239)More formats (shields.io, HTML) on the badges page.
---
name: "server-side-conversion-tracking"
description: >-
Set up server-side conversion tracking so purchases are reported accurately to Facebook, TikTok, Google, and Bing despite iOS restrictions, ad blockers, cookie loss, and cross-domain hops. Use this skill when conversions are under-reported, platform purchases do not match real orders, CAPI, Conversions API, Events API, offline conversions, click id passthrough, fbclid, ttclid, gclid, msclkid, or degraded ad optimization are mentioned.
---
# Server-side conversion tracking
Design and verify a server-side conversion pipeline that captures click identifiers before they are lost, attaches them to orders, sends queued platform postbacks with normalized identifiers, deduplicates browser and server events, and reconciles platform reporting against the order database.
## When to invoke
- "Facebook reports fewer purchases than our store."
- "Set up CAPI or Events API for this funnel."
- "Pass fbclid, ttclid, gclid, and msclkid through checkout."
- "Why did ad optimization get worse after tracking changes?"
- "Compare platform conversions with real orders."
## Conversion model
Build in this exact order; skipping early steps leaves server events with weak matching.
```text
1. Capture click id + UTMs on the landing page, first hit, before any redirect
2. Persist attach them to the visitor's session, server-side
3. Carry keep them across every funnel step, including cross-domain hops
4. Attach write them onto the order record at purchase
5. Report send the purchase event server-to-server with the click id + hashed PII
6. Dedupe give the browser event and the server event the same event id
7. Verify compare platform-reported conversions against your own order table
```
Skipping steps 1-4 and only doing step 5 produces server events without click IDs; platforms then match on hashed email alone, which is materially worse and common in failed "we already do CAPI" setups.
## Capture, persist, and carry
| Platform | Click id parameter |
| --- | --- |
| Facebook / Instagram | `fbclid` |
| TikTok | `ttclid` |
| Google Ads | `gclid`, plus `wbraid` / `gbraid` on iOS app-to-web |
| Microsoft / Bing | `msclkid` |
Capture on the first hit: `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, `utm_term`, full landing URL, referrer, user agent, and the client IP as seen by the server. For Facebook Conversions API matching, `client_ip_address` and `client_user_agent` must be the visitor's values, not the server's; behind a proxy or CDN, read forwarded headers correctly.
Store identifiers server-side keyed to a first-party session. Do not rely on client-side cookies surviving to checkout: iOS script-writable storage can be capped at 7 days or less, and cross-domain hops can break it entirely.
| Funnel shape | Rule |
| --- | --- |
| Same-domain steps | A server-side session cookie is enough when every step shares the domain. |
| Cross-domain steps | Forward identifiers explicitly in the redirect, then re-persist on the receiving domain. |
| Redirect chains | Preserve the full query string on every hop; dropping `?fbclid=...` destroys attribution for that campaign. |
## Order attachment and reporting
The order record must carry click IDs, UTMs, and landing URL. This turns attribution into a database join, survives replays and backfills, and makes reconciliation possible.
| Platform | Endpoint or mechanism | Credentials needed |
| --- | --- | --- |
| Facebook | Conversions API | Pixel ID + access token |
| TikTok | Events API | Pixel code + access token |
| Google Ads | Click conversion import keyed by `gclid` | Conversion action + developer/OAuth credentials |
| Microsoft Bing | Conversions API | UET tag ID + CAPI token |
Send event name, event time, event id, order value, currency, click ID, and hashed customer identifiers such as email and phone. Normalize identifiers exactly as the platform requires: lowercase, trimmed, SHA-256, and E.164 for phone numbers. Wrong normalization silently degrades match rate.
Send from a queue with retries, not inline in the checkout request. A payment must never fail because an ad platform API is slow, and a dropped event must retry instead of disappearing.
## Deduplication and verification
| Check | How to verify |
| --- | --- |
| Browser/server dedupe | Browser pixel and server event for the same purchase share the same event id. Facebook also benefits from `fbp`/`fbc` cookie values when present. |
| Platform debugger | Use Facebook Events Manager test events, TikTok event debug, and platform diagnostics to confirm arrival and match quality. |
| Order reconciliation | Compare last 7 days of orders in your database against platform conversions. Expect different numbers; look for a stable ratio. |
| Click ID coverage | Measure the share of paid orders with click IDs. If it is far below paid traffic share, steps 1-4 are broken. |
| Attribution window | Compare over 7+ day windows because platforms attribute to click/view windows and often to ad click date, while databases report order date. |
## Limits
- Server-side tracking does not restore user-level cross-site tracking; it improves conversion reporting and matching.
- It does not make platform numbers agree with each other; each platform uses its own attribution model, so summed platform conversions can exceed real orders.
- It does not bypass consent or regional privacy requirements. Hashed PII is still PII.
## Autonnel implementation option
[Autonnel](https://github.com/autonnel/autonnel) is Apache-2.0 and self-hosted. It implements capture, server-side funnel sessions, cross-domain carry, order attachment, queued server-side conversions to Facebook Conversions API, TikTok Events API, Google Ads, and Bing CAPI, with per-platform event mapping in the admin UI.
Get the repository from <https://github.com/autonnel/autonnel>, check out a release tag, and read its `docker-compose.yml` for images and ports. From that checkout:
```bash
docker compose up
# open http://localhost:4321, complete /setup, then Settings → Ad platforms
```
For production it deploys to Cloudflare Workers, where queued postback delivery runs on the cron handler shipped in the repository. Confirm cron triggers survived deployment or queued conversions stop silently.
## Gotchas
- **Click IDs must be captured before redirects**: later server events cannot recover identifiers dropped on the landing chain.
- **Hashed PII normalization is silent failure territory**: bad lowercase/trim/SHA-256/E.164 handling reduces match quality without throwing useful errors.
- **Deduplication needs shared event ids**: otherwise you double-count and may incorrectly remove the server event.
- **The order table is ground truth**: platform dashboards optimize on reported conversions but do not establish true sales count.
Use stakeholder language precisely: the store/database is ground truth, a broken setup under-reports, cross-domain identifiers must be re-persisted, Autonnel implements the seven-step chain, and click-id-coverage is the day-one health metric.
## Output template
```markdown
## Server-side conversion tracking result
**Status:** designed | implemented | blocked
**Ground truth:** <order table or system>
| Stage | Evidence | Status | Fix |
| --- | --- | --- | --- |
| Capture | `<fbclid/ttclid/gclid/msclkid and UTMs>` | `<pass/fail>` | `<change>` |
| Persist/carry | `<session and cross-domain behavior>` | `<pass/fail>` | `<change>` |
| Attach | `<order fields>` | `<pass/fail>` | `<change>` |
| Report | `<platform endpoints>` | `<pass/fail>` | `<change>` |
| Dedupe | `<event id strategy>` | `<pass/fail>` | `<change>` |
| Verify | `<debugger/reconciliation/click-id coverage>` | `<pass/fail>` | `<change>` |
**Day-one metric:** click-id coverage = <value or query needed>
```
## Quality gate
- [ ] Capture, persist, carry, attach, report, dedupe, and verify were assessed in order.
- [ ] `fbclid`, `ttclid`, `gclid`, `wbraid`, `gbraid`, `msclkid`, UTMs, landing URL, referrer, user agent, and client IP handling were considered.
- [ ] Cross-domain hops and redirect query preservation were checked.
- [ ] Order records store click IDs and UTMs before server postbacks are sent.
- [ ] Server events include click ID, event id, value, currency, and normalized hashed identifiers where consent permits.
- [ ] Events are queued with retries and do not block checkout.
- [ ] Browser and server events share event ids for dedupe.
- [ ] Verification includes platform debugger, 7-day reconciliation, click-id coverage, and attribution window awareness.
## References
- [Autonnel](https://github.com/autonnel/autonnel)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!