← blog/how-posteptrack-works
    // blog/how-posteptrack-works.md

    Inside PostepTrack: from click to stamped lead

    Three entry doors, four steps in the engine, two destinations — and the retry that leaves no lead behind. The complete attribution mechanics.

    2026-07-17·6 min read·engineering·POSTEP Digital

    ctwa_clid · leadgen_id · utm_* → Graph API → CRM + database · retry every 5 min · revenue per ad

    // the flow in one picture
    InvesteAnúnciosMeta · Google
    Click-to-WhatsAppabre conversa
    Lead Adsformulário Meta
    Landing / sitePixel + CAPI
    AtribuiPostepTrackqual anúncio gerou
    OrganizaSeu CRMKommo · Clint · Ploomes
    MedeDashboardtempo real
    SupabaseBanco de atribuição: cada lead é gravado com sua origem, o CRM sincroniza o status da venda de volta, e o dashboard lê tudo em tempo real.
    a venda ganha volta como atribuição de receita — você sabe qual anúncio deu lucro e realoca a verba
    // 01

    What PostepTrack stamps (and why)

    PostepTrack stamps every lead, the moment it lands in the CRM, with the exact origin of the click: campaign, ad set and ad — name and ID. Not “came from Meta”. It's “came from ad X, ad set Y, campaign Z”.

    We've already covered why each client gets their own instance and which pitfalls this pipeline hides. This post is the missing piece: the mechanics. What happens, in the order it happens, from click to stamped lead.

    // 02

    The three entry doors

    Every lead arrives through one of three paths, and each one drops a different identifier. The rest of the system exists to turn that identifier into attribution.

    CTWA — ad → WhatsAppctwa_clid

    the customer clicks the ad and lands straight in WhatsApp. The first message carries the click identifier, delivered by the WhatsApp Business webhook

    Lead Ads — Meta's native formleadgen_id

    the customer fills the form without leaving Instagram/Facebook. The leadgen webhook delivers the generated lead's ID

    Website / landing pageutm_* + fbclid

    the click reaches the site with tracking parameters in the URL, which travel along when the lead is submitted

    Three different formats, one destination: the webhook hits the client's Edge Function in real time.

    // 03

    The engine: 4 steps inside the Edge Function

    Each client has a dedicated Edge Function running on Supabase (Deno). It answers Meta in milliseconds and processes in the background. The real work is four steps:

    // from webhook to stamp
    webhook arrives (ctwa · leadgen · site)
    a. identifies the event type and extracts the click identifier
    b. queries the Graph API: identifier → ad_id → adset_id → campaign_id (+ names)
    c. locates the freshly created lead in the CRM (phone / ID)
    d. writes the attribution to both destinations
    stamped lead ✓ campaign · ad set · ad

    Step b is the heart: it's Meta's Graph API that answers which ad that click came from. PostepTrack just asks the right question, with the right token, at the right time — and stores the answer where it's worth money.

    // 04

    Two destinations + the retry that leaves no lead behind

    The same attribution is written to two places, because it serves two different audiences:

    // same data, two consumers
    CRM — lead fields
    PATCH via API (Kommo · Clint · Ploomes)
    campaign, ad set and ad in custom fields
    sales rep sees the origin on the lead card
    CRM reports filter by ad
    Database (Supabase) — leads table
    1 row per lead, ~30 attribution columns
    protected by RLS
    feeds the client's dashboards
    REAL cost per lead by campaign

    And there's the timing race: sometimes Meta's webhook arrives BEFORE the CRM creates the lead. If step c finds nobody, the event isn't dropped — it goes to a recovery queue and an automatic retry runs every 5 minutes until it matches.

    No click gets lost because the CRM took ten seconds. That queue (recovery_pending) was born from a real incident — not from paranoia.

    // 05

    Closing the loop: revenue per ad

    When the client's CRM supports outbound webhooks, PostepTrack goes beyond the lead: it closes the loop all the way to revenue.

    // from the register back to the ad
    deal marked as won in the CRM
    outbound webhook fires with deal_id + amount
    PostepTrack matches the deal to the original lead
    match by the deal_id stored on entry → recovers campaign/ad set/ad
    ✓ sale amount added to the ad that originated the lead

    The question changes from “how many leads did this ad bring” to “how much revenue did this ad generate”. ROI per ad, not per channel.

    // 06

    The pieces of an instance

    Each client runs a dedicated, isolated instance — nothing shared. Four pieces:

    #01 — Dedicated Meta App

    The client's own app on Meta, with a System User token (never expires). Receives the CTWA and Lead Ads webhooks and authenticates the Graph API queries.

    #02 — Edge Function

    Serverless function (Supabase/Deno) exclusive to the client. Answers the webhook in milliseconds and does the heavy lifting in the background.

    #03 — Leads table

    Postgres with ~30 attribution columns, protected by RLS. It's the base for dashboards and cost-per-lead analysis.

    #04 — CRM integration

    Kommo (API v4), Clint or Ploomes (OData, with outbound webhook for revenue). Custom fields created on the client's CRM lead.

    // what gets stamped on every lead

    campaign · ad set · ad (name + id) · event source · utm_source/medium/campaign/content · ctwa_clid / leadgen_id / fbclid · normalized phone · timestamps · deal_id (for revenue)

    written by
    POSTEP Digital
    ← all posts