← blog/capi-gtm-one-pipelinePT
    // blog/capi-gtm-one-pipeline.md

    CAPI and GTM Aren't Two Projects — They're One Pipeline

    An event_id that survives client and server, exclusive attribution per channel, and CTWA with zero browser cookies.

    2026-08-18·7 min·tracking·POSTEP Digital

    event_id as glue · exclusive attribution · CTWA via CRM · AI assembles, humans verify

    // 00

    Two names, one system

    It's common to treat “configure GTM” and “ship CAPI” as two separate projects — one goes to the media team, the other becomes a dev ticket. In practice, if they don't get born as the same pipeline, you end up with duplicated events, events that never arrive, or both fighting over the same conversion.

    The event is born once. The browser sends the first copy (pixel, via GTM). The server sends the second copy (CAPI), with the SAME identifier. If that's not true, you don't have redundancy — you have two sources disagreeing about what happened.

    // 01

    event_id is the glue

    Meta deduplicates pixel and CAPI events by event_id, within a 48h window. If the browser sends one ID and the server generates a different one at PATCH time, the two count as separate conversions — and your CPL drops by half in the report, without dropping for real.

    // the ID is born in the browser, travels to the server
    // GTM — in the event's dataLayer.push
    eventId: crypto.randomUUID()
    ↓ rides along in the payload that reaches the backend
    // server — when sending CAPI
    event_id: payload.eventId // NEVER generate a new one here

    Sounds obvious written down. In practice, it's the first place where GTM and CAPI disconnect: the team that configures GTM tags doesn't know a server is sending a copy, and the team that ships CAPI doesn't know which dataLayer variable carries the right ID.

    Rule: the event_id is generated ONCE, on the client, and travels along to the server. If CAPI is generating its own ID, it's not deduplicating — it's duplicating.

    // 02

    Exclusive attribution per channel — don't fire both

    A default GTM setup fires the Meta Pixel AND the Google tag on the same click — both get credit for the same conversion. That's not redundancy, it's inflated attribution: both channels think they converted the same lead, and each report lies upward.

    // last-click by parameter, not by trigger exception
    has a recent gclid or _gcl_aw? → Google gets the conversion
    has a recent fbclid or _fbc? → Meta gets the conversion
    // PageView / ViewContent stay OUTSIDE this rule —
    // audiences/remarketing need both on 100% of traffic

    The split lives in the event NAME inside GTM (a dedicated event per channel), not in a hidden condition buried inside the trigger — otherwise the next person who touches the container won't see the rule and will silently reintroduce the double fire.

    Rule: conversion is exclusive to one channel at a time, decided by the most recent parameter. Audiences/remarketing is the declared exception, not the silent default.

    // 03

    When the lead leaves the site and becomes WhatsApp

    So far, pixel and CAPI live in the same domain: someone visited the site. But a good chunk of our operation is WhatsApp-first — the ad click sends the person straight into a conversation, never touching the site. That path has zero browser cookies to carry. What carries the trail is the CRM.

    That's where CAPI stops being a “site project” and becomes part of PostepTrack: the same phone number and the same ctwa_clid that match the lead to the CRM are what let you send the LeadSubmitted event to Meta afterward — every entry channel (site, direct WhatsApp, form) feeding the same conversion account, without duplicating and without forgetting any of them.

    // CTWA has its own rules that site CAPI doesn't
    event_name LeadSubmitted (not "Lead")
    user_data requires whatsapp_business_account_id
    dataset dedicated PER WABA — can't reuse the site's

    Rule: site CAPI and WhatsApp CAPI aren't the same implementation with a swapped endpoint. They're two different contracts with Meta — same goal, different requirements.

    // 04

    What AI solves fast — and what it doesn't decide for you

    The mechanical part of GTM — a new variable, a regex trigger, a tag pointing at the right dataLayer key — is fast to put together with AI describing the expected behavior. That removes the technical friction of configuring a container.

    What AI doesn't solve on its own: which channel gets which conversion, whether the event_id truly survives client→server without getting regenerated along the way, whether the CTWA dataset is actually linked to the right WABA. That gets checked against real behavior — Dataset Quality API, a real test event, server logs — never assumed because “AI configured it correctly.”

    Rule: AI assembles the container faster. The attribution decision and the proof the data arrived correctly are still verified by a human, against the real system — never by inference.

    // 05

    Summary: one pipeline, not two projects

    event_id

    born once on the client (GTM), travels to the server. CAPI never generates its own ID — if it does, it's duplicating, not deduplicating.

    attribution

    exclusive per channel, decided by the most recent parameter (gclid × fbclid), split by event name in GTM — never both firing together.

    CTWA

    no browser cookies — the CRM (via PostepTrack) carries the trail. LeadSubmitted + dataset per WABA, a different contract than site CAPI.

    AI in the middle

    assembles the GTM container fast. Doesn't decide attribution, doesn't prove the data arrived right — that's human verification against the real system.

    // the main rule

    GTM, CAPI and CRM aren't three systems talking to each other by accident — they're one attribution pipeline, from the click to the dashboard. Treat them as separate projects and you get duplicated events; treat them as one pipeline and the data matches reality.

    written by
    POSTEP Digital
    ← see all posts