Meta Ads tracking instellen via Webhook Matching

Bewerkt

Dit artikel gaat over het Meta CAPI-deel van AdPage Webhook Matching: hoe je de AdPage - Meta Conversion API-tag koppelt aan de merged payload die Webhook Matching aanlevert. Belangrijk om vooraf te begrijpen: dit CAPI-event is geen vervanging van je browser-side Meta Pixel — het is een toevoeging daarop. Beide sturen een Purchase, en Meta dedupliceert ze aan de hand van een gedeeld event_id, zodat je aankoop niet dubbel telt.

Heb je Webhook Matching nog niet ingericht? Doorloop eerst het basisartikel (activeren, Event Notifier-template, BasketKey, Measurement Protocol Client) — dit artikel bouwt daar direct op verder.


Kort: wat is Webhook Matching ook alweer?

Webhook Matching is een AdPage-functionaliteit die twee databronnen server-side samenvoegt tot één gevalideerd event:

  • Prepare (browser-side, vlak vóór checkout): vangt browser-context — gclid, cookies (_fbp/_fbc), user-agent, items-array

  • Trigger (server-side webhook, bij de order): vangt de backend-ordergegevens — klant, adres, bedrag, transaction_id

Beide kanten worden gekoppeld via een BasketKey (user_id, cart_token of quote_id, afhankelijk van je platform). Het resultaat komt binnen op je sGTM server container via een Measurement Protocol (GA4) Client op het pad /data, en bevat direct alle velden die GA4, Meta, Google Ads, TikTok én Pinterest nodig hebben — inclusief consent-forwarding.


Hoe de deduplicatie werkt

Meta dedupliceert het browser-Pixel-event en het server-side CAPI-event van dezelfde aankoop wanneer beide hetzelfde event_id én dezelfde event_name (Purchase) dragen. Meta houdt er dan één aan (binnen een venster van ~48 uur) en negeert de tweede.

De sleutel is dus het event_id. Dat moet twee dingen tegelijk zijn:

  1. Identiek op de browser-Pixel én de CAPI-kant voor dezelfde aankoop.

  2. Uniek per aankoop — anders worden verschillende orders ten onrechte samengevoegd.

De enige waarde die aan beide voldoet is het transaction_id (order-ID). Gebruik dus:

Bron

event_id

Browser-side (bestaand)

Meta Pixel Purchase op de bedankpagina

transaction_id

Server-side (deze setup)

AdPage - Meta Conversion API op de Measurement Protocol Client

transaction_id uit de merged payload

⚠️ Gebruik niet user_id als event_id. Die is stabiel per klant, niet per order — een tweede aankoop van dezelfde klant binnen 48u zou dan onterecht als duplicaat worden weggegooid. user_id hoort thuis als BasketKey en als external_id, niet als dedup-sleutel.

⚠️ Het event_id moet exact dezelfde string zijn aan beide kanten. Let op prefixes of formatting: stuurt de browser 12345 en de server order_12345, dan ziet Meta twee verschillende events en dedupt het niet.

💡 Zorg dat het CAPI-event_id uit de Trigger/order-kant (transaction_id) komt, en niet uit een willekeurig event_id dat in de Prepare/begin_checkout-stap is gegenereerd — dat laatste matcht nooit met het browser-Purchase-event.


Wat heb je nodig?

  • Je bestaande browser-side Meta Pixel Purchase werkend, ingesteld met event_id = transaction_id

  • Webhook Matching actief voor deze klant (stap 1 uit het basisartikel)

  • De Prepare- en Trigger-tags (op basis van adpage-event-notifier.tpl) al ingericht met de juiste BasketKey — inclusief een consistent transaction_id

  • Een Measurement Protocol (GA4) Client op pad /data, met een herkenbare naam — in dit artikel gebruiken we Webhook Matching - GA4 als voorbeeld

  • Je Meta Pixel ID en API Access Token — zie dit artikel

  • Het template-bestand AdPage - Meta Conversion API.tpl (AdPage-fork van de Facebook Conversion API-template) — https://adpage.b-cdn.net/GTM-Templates/Facebook%20Conversion%20API.tpl


Stap 1: Template uploaden

  1. Open je GTM server container en ga naar Templates

  2. Klik bij Tag Templates op New

  3. Klik rechtsboven op de drie puntjes (⋮) en kies Import

  4. Selecteer het bestand AdPage - Meta Conversion API.tpl (https://adpage.b-cdn.net/GTM-Templates/Facebook%20Conversion%20API.tpl)

  5. Klik op Save


Stap 2: Tag aanmaken en basisinstellingen

  1. Ga naar Tags in het linkermenu

  2. Klik op New

  3. Kies als Tag Configuration de AdPage - Meta Conversion API

  4. Geef de tag een herkenbare naam, bijvoorbeeld AdPage - Meta Purchase (Webhook Matching)

  5. Vul Facebook Pixel ID en API Access Token in

  6. Laat Action Source op de standaardwaarde Website staan

  7. Vink Generate _fbp cookie if it not exist uit — Webhook Matching stuurt de echte _fbp/_fbc van de Prepare-stap al mee; een zelfgegenereerde fallback voegt daar niets aan toe


Stap 3: Trigger instellen op de Measurement Protocol Client

Dit event komt niet binnen als een custom event met een trytagging_-prefix. Het komt binnen via de Measurement Protocol Client die je in stap 4 van het basisartikel hebt aangemaakt, met een schone event_name: "purchase".

  1. Klik in de tag op Triggering+

  2. Kies als trigger type Custom

  3. Stel in: {{Client Name}} komt overeen met de naam van je Measurement Protocol Client (bijv. Webhook Matching - GA4)

  4. Voeg optioneel een tweede voorwaarde toe: Event Name is gelijk aan purchase

  5. Geef de trigger een naam, bijvoorbeeld Webhook Matching - Purchase

  6. Klik op Save

💡 Je browser-side Meta Pixel Purchase blijft gewoon staan — dit is bewust. Het CAPI-event vult de gevallen op waar de browser faalt (ad-blockers, ITP, consent, afgebroken sessies), en Meta dedupt op het gedeelde event_id.

⚠️ Gebruik voor de CAPI-tag zelf maar één trigger. Zet niet ook nog de "Client Name equals GA4"-trigger uit het reguliere Meta CAPI-artikel op deze tag — dat zou een tweede server-side CAPI-event voor dezelfde aankoop veroorzaken, en die twee delen niet noodzakelijk hetzelfde event_id.


Stap 4: Event Name — "Inherit from client" werkt hier prima

Omdat de Measurement Protocol Client een schone event_name: "purchase" doorgeeft (géén trytagging_-prefix), herkent de tag dit automatisch als het standaard Facebook-event Purchase via de ingebouwde naam-mapping.

  1. Laat Event Name Setup Method op Inherit from client staan

Wil je liever expliciete controle? Zet dan Override → Standard → Purchase. Functioneel maakt het in deze setup geen verschil — zolang het event maar als Purchase bij Meta binnenkomt, want de dedup vereist dezelfde event_name als je browser-Pixel.


Stap 5: Consent — controleren, niet blind uitzetten

Webhook Matching stuurt consent standaard mee, in meerdere vormen (gcs/gcd, en een genest consent.*-object). Zet Consent Settings dus in eerste instantie niet op "Send data always", maar test eerst of het "gewoon werkt":

  1. Laat Consent Settings op de standaardwaarde staan: "Send data in case marketing consent given"

  2. Test de flow (zie Stap 7)

  3. Zie je in de preview mode dat de tag Fired toont, maar niets onder Outgoing HTTP Requests from Server? Dan komt de consent niet aan in het formaat dat deze tag verwacht (consent_state.ad_storage of x-ga-gcs) — zet dan als tijdelijke fix Consent Settings op Send data always, en meld dit door aan het Tracking & Tools-team, want dan klopt de gcs-doorvertaling van de Measurement Protocol Client niet.

💡 Dit is een bewuste afwijking van eerdere Meta CAPI/webhook-artikelen: bij de losse AdPage Webhook Client ontbreekt consent-data structureel (zie de kanttekening onderaan), maar bij Webhook Matching hoort consent er wél doorheen te komen omdat het via de Measurement Protocol Client loopt.


Stap 6: Klant- en aankoopdata — automatisch gemapt

De merged payload van Webhook Matching bevat exact de velden die deze tag automatisch herkent. Volgens het basisartikel worden deze Meta-velden standaard meegestuurd:

Meta-veld

Herkomst (via Webhook Matching)

fbp / fbc

_fbp/_fbc-cookie, gevangen tijdens de Prepare-stap

em, fn, ln, ph

e-mail, voornaam, achternaam, telefoon — tag hasht deze automatisch met SHA256 als ze nog niet gehasht zijn

zp, ct, st, country

postcode, stad, provincie, land

external_id

customer.id — stabiel over meerdere orders van dezelfde klant (identiteit, niet de dedup-sleutel)

client_ip_address / client_user_agent

IP en user-agent voor matching

event_id

transaction_id — de dedup-sleutel; moet exact gelijk zijn aan de event_id van je browser-Pixel

value, currency, contents/content_type

order- en productdata, inclusief de items-array uit de Prepare-stap

Je hoeft de User Data- en Custom Data-tabellen dus in de regel niet handmatig te vullen. Kom je toch een veld tegen dat leeg blijft? Check eerst in de sGTM preview of het veld daadwerkelijk in de payload van de Measurement Protocol Client staat, vóór je het als custom property toevoegt.


Stap 7: Testen

  1. Open je server container → Webhook Logs

  2. Zoek een recente purchase-webhook en klik op Replay

  3. Open je GTM server container in Preview Mode

  4. Klik rechtsboven op de drie puntjes en kies Send requests manually

  5. Kopieer de x-gtm-server-preview header en plak deze in de Webhook Replay-popup

  6. Klik op Replay

Via onderstaande link kun je de stappen zien: https://app.arcade.software/share/0HswbFejHQLFQeeC2NXw

Controleer in de preview mode, in deze volgorde:

  1. De Prepare- en Trigger-tag van Event Notifier hebben eerder al gematcht (geen missed-status in de Webhook Matching-logs — zie troubleshooting in het basisartikel)

  2. Je Measurement Protocol Client (Webhook Matching - GA4) verschijnt met het request op /data

  3. De AdPage - Meta Conversion API-tag toont Fired

  4. Onder Outgoing HTTP Requests from Server staat een request naar graph.facebook.com — staat hier None, ga terug naar Stap 5 (consent)

  5. Controleer dat het uitgaande event_id gelijk is aan het transaction_id — en aan het event_id dat je browser-Pixel voor dezelfde order meestuurt

💡 Extra check in Meta zelf: vul tijdens het testen het veld Test ID in met de code uit Gebeurtenisbeheer → Test-gebeurtenissen in Meta, zodat je meteen de Event Match Quality-score ziet. In het overzicht van gebeurtenissen zie je bovendien of het browser- en server-event als gededupliceerd worden herkend op basis van gedeeld event_id. Verwijder het Test ID voordat je live gaat.


Veelvoorkomende problemen

Aankoop wordt dubbel geteld in Meta

De dedup mislukt. Loop deze drie na:

  1. event_id: sturen browser-Pixel én CAPI exact dezelfde waarde (transaction_id, zonder prefix/formattingverschil)?

  2. event_name: komt het server-event als Purchase binnen, en niet als trytagging_purchase of een custom naam?

  3. Dubbele CAPI-trigger: staat er per ongeluk náást de Webhook Matching-trigger ook nog een "Client Name = GA4"-trigger op deze CAPI-tag? Gebruik er maar één.

Zie ook Event Deduplicatie instellen voor Meta Ads.

Tag toont "Fired", maar geen Outgoing HTTP Request

Zie Stap 5 — de gcs/consent-doorvertaling van de Measurement Protocol Client komt niet aan zoals de tag verwacht. Zet tijdelijk Consent Settings op Send data always en meld dit intern.

"Match identifier value could not be resolved" in de Webhook Matching-logs

Dit gebeurt vóór de Meta-tag en heeft niets met deze tag te maken — de BasketKey wordt niet gevonden. Zie de troubleshooting in het basisartikel.

Event komt bij Meta binnen met een lege of onverwachte event-naam

Controleer of de trigger inderdaad op de Measurement Protocol Client staat (Stap 3) en niet op een custom event met een trytagging_-prefix — dat laatste hoort bij de losse Webhook Client, niet bij Webhook Matching (zie hieronder).


Verschil met de standaard Webhook Client

Gebruik je (nog) geen Webhook Matching, maar wel de gewone AdPage Webhook Client rechtstreeks (zoals in het GA4 webhook-artikel)? Dan gelden twee afwijkende punten ten opzichte van dit artikel:

  • Het event komt binnen met de ruwe naam trytagging_purchase, niet als schone purchase. Zet Event Name Setup Method dan op Override → Standard → Purchase — "Inherit from client" stuurt anders een custom event trytagging_purchase naar Meta, dat niet dedupt met je browser-Pixel.

  • De payload bevat geen consent-signaal. Zet Consent Settings dan direct op Send data always, anders stopt de tag stilzwijgend zonder een request te versturen.


Gerelateerde artikelen

Was dit artikel nuttig?

Onze excuses! Zou je ons meer willen vertellen?

Bedankt voor de feedback!

Er is een probleem opgetreden bij het verzenden van uw feedback
Controleer uw verbinding en probeer het opnieuw.