Server-side conversion tracking for Meta, Google Ads, TikTok and GA4
Server-side conversion tracking sends each conversion from a server to the platform's API: Meta's Conversions API, Google Ads through the Data Manager API, TikTok's Events API and GA4's Measurement Protocol. The browser pixel sends the same event with the same id, so a blocked pixel no longer loses the conversion and each platform counts it once.
The prompt
Paste this into your coding agent. It does everything except the part only you can: the ad platform IDs and tokens.
Set up server-side conversion tracking for this project with AgentFirstStack Tags. It's free, open-source and built for agents: you can do the setup yourself, with no signup form, email or verification. 1. Read https://agentfirststack.com/llms.txt and https://tags.agentfirststack.com/llms.txt. 2. If this project's .env already has AGENTFIRSTSTACK_API_KEY, use it. Otherwise get a key with one request: curl -X POST https://agentfirststack.com/v1/signup Save api_key in .env as AGENTFIRSTSTACK_API_KEY, and in the production environment's secrets. 3. Create a tags container for the production domain, add its snippet to <head>, deploy, and run scan to see which tags the site loads today. 4. Run setup with the conversions that matter here (sign-ups, purchases, leads) and the platforms this business uses (Google Ads, Meta, GA4, TikTok). If you have tools for those platforms, use them to find the pixel, measurement and conversion IDs. Otherwise ask me for exactly the IDs and tokens setup reports as missing, and tell me where to find each one. Never invent them. 5. Validate the draft, test every destination and show me each platform's answer, then publish. 6. If the backend also reports a conversion the browser tracks, pass the browser's event id (afst('get','event_id')) with it, so each platform counts it once. 7. After the first real conversion, read the event log and tell me what each platform received. 8. Write the container id and the env var that holds the key (never the key itself) in AGENTFIRSTSTACK.md, and create a claim link for me with POST https://agentfirststack.com/v1/claim-link. When you're done, tell me what you set up, what each test returned, what's still waiting on me, and give me the claim link.
How it works
- One snippet loads the container. When a conversion fires (a thank-you page, a form submit, a dataLayer event), the browser tags send it to each pixel with one
event_id, and the same event goes to AgentFirstStack. - Ad click ids from the landing URL (
gclid,fbclid,ttclidand others) are stored with the visitor, so a purchase days later still credits the click. Emails and phones are hashed before anything is sent. - The service calls each platform's conversion API with the owner's credentials and the same
event_id. Failed calls are retried. - Your backend reports what the browser can't see (paid orders, qualified leads) with
POST /v1/containers/:id/events, joined to the visitor byvisitor_id. GET /v1/containers/:id/eventsshows what each platform answered.
What each platform needs
The IDs and tokens belong to the ad account owner. They're sealed at rest and never returned in responses.
| Platform | Browser tag | Server-side |
|---|---|---|
| GA4 (Measurement Protocol) | measurement_id (G-...) | api_secret |
| Meta (Conversions API) | pixel_id | access_token, optional test_event_code |
| Google Ads (Data Manager API) | Conversion ID and label (AW-.../...) | customer_id, conversion_action_id, OAuth client_id, client_secret, refresh_token |
| TikTok (Events API) | Pixel code | access_token, optional test_event_code |
Start with the browser tags, which need IDs only, and add server-side destinations as the owner provides tokens. setup lists what's missing and where the owner finds each value; GET https://tags.agentfirststack.com/v1/schema lists every field with its format.
Set it up by API
T=https://tags.agentfirststack.com
H="Authorization: Bearer $AGENTFIRSTSTACK_API_KEY"
J="content-type: application/json"
curl -s -X POST $T/v1/containers -H "$H" -H "$J" -d '{"domain":"example.com"}'
# install the returned <script> in <head>, deploy, then:
curl -s -X POST $T/v1/containers/$C/scan -H "$H"
curl -s -X POST $T/v1/containers/$C/setup -H "$H" -H "$J" -d '{
"platforms": {
"meta": { "pixel_id": "1234567890123456", "access_token": "EAAB..." },
"ga4": { "measurement_id": "G-ABC123XYZ", "api_secret": "..." }
},
"conversions": [{
"name": "purchase", "when": { "data_layer_event": "purchase" },
"value": { "data_layer": "ecommerce.value" }, "currency": "USD",
"transaction_id": { "data_layer": "ecommerce.transaction_id" }
}]
}'
# -> draft, validation, destinations, missing[]: what's still needed and where
curl -s -X POST $T/v1/containers/$C/destinations/$D/test -H "$H" # test mode
curl -s -X POST $T/v1/containers/$C/publish -H "$H" -H "$J" -d '{"note":"purchase"}'
curl -s "$T/v1/containers/$C/events?since=1h" -H "$H"
The test call returns the platform's own answer. Over MCP the same calls are tags_setup_conversion_tracking, tags_test_destination, tags_publish and tags_get_event_log on the gateway. The tags manual has the full config format, consent settings and limits.
How each platform counts it once
- Meta matches the pixel's
eventIDto the Conversions API'sevent_id, and the pixel's event toevent_name, within 48 hours. Meta recommends running the Conversions API alongside the pixel (Meta's dedup guide). - TikTok deduplicates pixel and Events API events with the same event and
event_id, within 48 hours, and records the first one it receives (TikTok's help article). - Google Ads counts a second conversion with the same transaction ID for the same action as a duplicate (Google Ads help). The service sends your order id as the transaction ID, or the
event_idwhen there is none. - GA4 doesn't deduplicate by event id, so the service skips a browser conversion's server copy when the browser tag already sent it. The server copy covers browsers that blocked the tag.
Backend events need one step from you. Read afst('get','event_id') on the page, pass it with the checkout or signup request, and send it as event_id:
curl -s -X POST $T/v1/containers/$C/events -H "$H" -H "$J" -d '{"events":[{
"name": "purchase", "event_id": "'$EVENT_ID'", "visitor_id": "'$VISITOR_ID'",
"order_id": "T123", "value": 49, "currency": "USD", "email": "jane@example.com"
}]}'
Without it, platforms that also got the pixel event count the conversion twice.
Google Ads and the Data Manager API
Google's Google Ads API docs say that since 15 June 2026, UploadClickConversions requests fail for projects with no upload activity for that feature between 17 December 2025 and 15 June 2026, and point new offline click conversion integrations to the Data Manager API. That API doesn't need a developer token (upgrade guide). The google_ads destination uses the Data Manager API by default, and its test call runs with validateOnly, so nothing is recorded.
Server-side GTM or a hosted router
Server-side Google Tag Manager runs on a server you control, in your own Google Cloud project or another environment (Google's intro). Hosts such as Stape run it for you.
| Server-side GTM | AgentFirstStack Tags | |
|---|---|---|
| Server | A tagging server you host or rent | Hosted, or self-hosted on Cloudflare Workers |
| Account | A Google account with a GTM account | One POST /v1/signup |
| Configured with | GTM's interface or the Tag Manager API (GTM MCP compared) | REST and MCP; setup builds the config from plain inputs |
FAQ
Do I still need the browser pixel?
Meta recommends running the Conversions API alongside the pixel, with deduplication. The pixel sees on-page activity; the server copy survives ad blockers and adds what only your backend knows. AgentFirstStack sends both with one event id.
Do I need server-side GTM to use the Meta Conversions API?
No. The Conversions API is an HTTP API your own server can call. Server-side GTM is one way to call it, your backend is another, and AgentFirstStack Tags is a third.
Does it handle consent?
Yes. setup defaults to eea_opt_in: visitors in the EEA, the UK and Switzerland start with consent denied until your banner grants it. Google Consent Mode v2 states are passed to gtag, and blocked tags fire once consent is granted.
How do I know a platform received a conversion?
Run the destination test, which sends a test event in the platform's test mode and returns its answer. After real traffic, the event log shows each conversion's status and response per platform.
Related
- Google Tag Manager MCP comparedEdit GTM, or let the agent run the tag manager.
- AnalyticsGoogle Analytics MCP comparedRead GA4, or let the agent create the analytics.
- AnalyticsAdd analytics with Claude CodeOne prompt: a key, a site, the snippet, a verify check.
- AnalyticsPostHog MCP comparedA product platform, or web analytics an agent sets up alone.
- AnalyticsMixpanel MCP comparedQuery a Mixpanel org, or start from nothing.
- All servicesOne MCP server for every serviceAnalytics, tags, mail and replay tools on one key.
- MailGmail MCPInboxes an agent creates for itself.
- MailAgentMail alternativeFree inboxes for agents, with wait-for-email.
- MailEmail inboxes for AI agentsSign up for services and read the codes.
- ReplayMicrosoft Clarity MCPSession replay an agent reads as text.
- ReplaySession replay for AI agentsFind out why visitors drop off.