Naar de inhoud

GidsenAdvertentieplatformen12 min leestijd

Meta Pixel vs Conversions API vs beide op Shopify: wat elk echt meet

Wat de browser-Pixel van Meta ziet, wat een server-only Conversions API stuurt, en waarom de aanbevolen opzet beide met een gedeelde event_id draait.

Gepubliceerd
Gecontroleerd
Browserevents, backendevents en een gekoppelde implementatie.

Daniil MaximkinProduct & Solutions Engineer

Kort antwoord

Meta kan je Shopify-events op drie manieren ontvangen: een Pixel die alleen in de browser draait, een Conversions API die alleen op de server draait, of beide tegelijk. De Pixel ziet wat de pagina uitvoert, de server ziet wat je backend weet, en de aanbevolen redundante opzet stuurt beide met een gedeelde event_id, zodat Meta het paar samenvoegt tot één geteld event. Elk dekt een ander deel van de funnel.

— Daniil

Belangrijkste punten

  • Een Pixel die alleen in de browser draait, is de bron die van nature events op paginaniveau ziet — ViewContent, AddToCart, InitiateCheckout — omdat ze in de browser van de shopper gebeuren.
  • Een Conversions API die alleen op de server draait, is de natuurlijke plek voor Purchase-events op bestelniveau, inclusief bestellingen die de browser nooit heeft afgerond, maar hij kan geen pagina-events zien en heeft een browsercapture nodig voor fbp en fbc.
  • De redundante opzet is de configuratie die Meta aanbeveelt: dezelfde event_name en dezelfde event_id aan beide kanten, ontvangen binnen het matchvenster, zodat één purchase één keer telt.
  • Deduplicatie is een matchregel, geen standaardinstelling. Verschillende id's, verschillende eventnamen, een id die aan één kant ontbreekt, of een te lange tussenpoos laten allemaal twee events achter.
  • Geen van de drie lost consent, blockers of een verkeerde conversiedefinitie op. Ze veranderen wat Meta ontvangt, niet wat Shopify heeft geregistreerd.
In deze gids

Meta kan je Shopify-events ontvangen van een browser-Pixel, van een server-side call naar de Conversions API, of van beide tegelijk. Het zijn geen concurrerende producten: het zijn drie dekkingsniveaus over dezelfde funnel, en de verschillen komen naar voren in wat elke bron kan zien.

Deze gids is voor een Shopify-ondernemer of interne marketeer die beslist hoe Meta events moet ontvangen, en voor de developer die het implementeert. Hij vergelijkt de drie op het niveau van het mechanisme — waar het event afvuurt, welke parameters meereizen, hoe consent wordt gerespecteerd, hoe deduplicatie werkt, en wat elk je laat reconciliëren tegen Shopify-bestellingen. Er wordt geen winnaar gekozen, geen kosten genoemd, en geen winst in matchkwaliteit beloofd; die hangen af van je verkeer, catalogus, consentpercentages en team.

Wat meet een Meta-Pixel die alleen in de browser draait eigenlijk?

Een Pixel die alleen in de browser draait, meet wat de pagina van de shopper kan rapporteren: paginaweergaven en de acties op paginaniveau die je thema of een Shopify-webpixel in de browser afvuurt. Hij ziet ViewContent, AddToCart en InitiateCheckout van nature, en verliest elk event dat de browser nooit uitvoert.

Je installeert de basiscode één keer, en daarna rapporteert de Pixel via fbq('track', ...). Telkens wanneer de Pixel laadt, roept hij automatisch fbq('track', 'PageView') aan, dus paginaweergaven hangen niet af van of jij eventcode schrijft. Standaard-events dekken de funnel: ViewContent op een productpagina, AddToCart wanneer een artikel in het winkelmandje belandt, InitiateCheckout wanneer de checkout begint, en Purchase op de bevestigings- of bedankpagina. Elk accepteert een parameterobject — content_ids, contents, currency, value, content_type — zodat het event het product en zijn waarde meedraagt.

Twee details zijn van belang naast het afvuren van het event. Advanced Matching: waarden die je doorgeeft aan fbq('init') worden door de Pixel met SHA-256 gehasht voordat ze de browser verlaten, zodat een gehasht e-mailadres kan meereizen zonder dat de ruwe waarde dat doet. Dan het identificatiepaar _fbp en _fbc: de Pixel zet een browseridentifier (_fbp) en leidt een klikidentifier (_fbc) af uit de fbclid van de advertentieklik die de bezoeker binnenbracht. Die waarden koppelen een browser-event terug aan een klik.

Omdat alles in de browser gebeurt, is de browser ook het plafond. Consent-gating stopt de Pixel voor shoppers die marketingdoeleinden weigeren; adblockers, een pagina die nooit rendert, of een tab die wordt gesloten voordat de bevestigingspagina verschijnt, produceren geen event. Op Shopify specifiek hangt een browser-purchase af van checkout_completed, dat één keer per checkout afvuurt — doorgaans op de bedankpagina, of op de eerste upsellpagina wanneer er post-purchase-aanbiedingen spelen — en helemaal niet afvuurt als die pagina niet laadt. Privacybescherming van browsers kan de cookies die een script zet ook verkorten of blokkeren, _fbp inbegrepen, en dat is een levensduurvraag die je test in plaats van aanneemt.

Wat de browser-Pixel je laat reconciliëren, is een telling van de purchases die de browser zag; een terugbetaling die later in het backoffice wordt verwerkt, valt buiten zijn zicht.

// Browser: one id per purchase, derived from the order so the server can reproduce it
fbq('track', 'Purchase', {
  value: 129.00,
  currency: 'USD',
  contents: [{ id: 'SKU-123', quantity: 1 }],
  content_type: 'product'
}, { eventID: 'purchase_4512890' });

Wat meet een Conversions API-opzet die alleen op de server draait eigenlijk?

Een Conversions API die alleen op de server draait, meet wat je backend weet. Hij stuurt benoemde events rechtstreeks naar Meta vanaf jouw infrastructuur, en rapporteert dus de purchases die jouw systeem registreert — inclusief bestellingen die de browser nooit heeft afgerond — zonder op het moment van verzenden afhankelijk te zijn van de pagina van de shopper.

Je doet een POST van een data-array naar het events-endpoint van Meta voor jouw Pixel, met authenticatie via een access token. Elk server-event draagt verplichte velden: event_name (de standaard- of custom eventnaam), event_time (wanneer het gebeurde) en action_source, dat aangeeft waar de conversie plaatsvond. Een website-event moet ook event_source_url en client_user_agent sturen; zonder die velden is het niet geldig.

action_source is geen decoratie. Meta vereist het bij elk event; de waarden zijn website, app, email, phone_call, chat, physical_store, system_generated, business_messaging en other. De verkeerde kiezen geeft een verkeerd beeld van waar de conversie plaatsvond, en volgens de voorwaarden van Meta ben je verantwoordelijk voor de juistheid ervan. Voor een purchase in een Shopify-storefront is de eerlijke waarde website — en daarom komen event_source_url en de user agent daarmee mee.

Gebruikersdata is waar de server zowel voordelen als gaten heeft. Hij kan em en ph sturen, genormaliseerd (bijvoorbeeld een e-mailadres zonder overbodige spaties en in kleine letters) en met SHA-256 gehasht, plus external_id en client_ip_address. Hij kan ook fbc en fbp sturen — maar alleen als die waarden bestaan. _fbc komt uit een fbclid op een landings-URL en _fbp wordt door de browser gezet; een server die nooit met de browser interacteert, heeft geen van beide en kan ze niet verzinnen. Een pipeline die alleen op de server draait, ziet acties op paginaniveau zoals ViewContent en AddToCart alleen als de pagina het de server expliciet vertelt, omdat niets anders dan de browser ze waarneemt.

Nog een eigenschap is van belang: deduplicatie geldt niet binnen één bron. Meta gooit niet twee identieke server-events weg die na elkaar worden verstuurd, en ook niet twee identieke browser-events. Deduplicatie bestaat alleen tussen een browser-event en zijn server-tweeling.

Terugbetalingen gedragen zich hier anders. Een server die de bestelling en het terugbetalingsrecord leest, is de natuurlijke plek om een terugbetaling weer te geven; hoe dat wordt uitgedrukt, is een ontwerpbeslissing die je verifieert tegen de documentatie van Meta.

Wat verandert er als je beide draait met event_id-deduplicatie?

Beide draaien maakt van twee gedeeltelijke registraties één volledige, maar alleen wanneer Meta ze kan matchen. In de aanbevolen redundante opzet sturen de Pixel en de Conversions API dezelfde event_name en dezelfde event_id, en voegt Meta het paar samen tot één event.

Meta documenteert de redundante opzet — alle events vanuit beide bronnen versturen — als de aanbevolen configuratie, mits je voor beide een persistente event_id kunt genereren. De regel is concreet: de eventID van de Pixel moet gelijk zijn aan de event_id van de server, en het event van de Pixel moet gelijk zijn aan de event_name van de server. Wanneer beide overeenkomen en het tweede event binnen 48 uur na het eerste aankomt, houdt Meta het eerste en gooit het duplicaat weg; als de twee binnen ongeveer vijf minuten van elkaar landen, geeft Meta de voorkeur aan het browser-event.

Er is een gedocumenteerde terugvaloptie — matchen op event_name plus fbp en/of external_id — en daar zitten voorwaarden aan: ze werkt doorgaans alleen wanneer het browser-event eerst aankomt en het server-event daarna volgt, en een server-event wordt niet weggegooid alleen omdat er later een identiek browser-event opduikt.

Wat deduplicatie dus vereist, is een stabiele id die beide kanten onafhankelijk kunnen produceren. Een ordernummer of transaction ID is de gebruikelijke keuze, omdat de browser die op de bevestigingspagina kan lezen en de server hem al heeft. Wat het breekt, is elke vorm van onenigheid: een id die bij elke paginalaad opnieuw wordt gegenereerd, een id die aan de ene kant aanwezig is en aan de andere kant ontbreekt, een verschil in hoofdletters of spelling in de eventnaam (purchase versus Purchase), een tussenpoos langer dan het matchvenster, of een opzet waarin slechts één bron live is. Elk geval laat twee events achter, en twee events worden gelezen als twee purchases.

Events Manager toont het resultaat. Test Events toont inkomende events met hun bron; een gematcht paar wordt als gededupliceerd gepresenteerd in plaats van als twee afzonderlijke conversies, en het eventdetail toont hoe elk is aangekomen. Het geaggregeerde dashboard toont alleen totalen, en totalen verbergen de duplicatie die je zoekt.

{
  "data": [{
    "event_name": "Purchase",
    "event_time": 1690000000,
    "event_id": "purchase_4512890",
    "action_source": "website",
    "event_source_url": "https://store.example/checkout/thank-you",
    "user_data": {
      "em": ["<sha256 of the normalized email>"],
      "fbp": "fb.1.1690000000.1234567890",
      "fbc": "fb.1.1690000000.AbCdEfGh"
    },
    "custom_data": { "value": 129.00, "currency": "USD" }
  }]
}

Naast elkaar

De tabel vergelijkt de drie op de criteria die de meeste Shopify-implementaties bepalen. Hij beschrijft afwegingen in plaats van ze te rangschikken, en noemt geen prijzen van leveranciers.

CriteriumAlleen browser-PixelAlleen Conversions APIBeide, met event_id
EventbronDe browser van de shopper, op de paginaJe server of backendBeide, die dezelfde actie beschrijven
Dekking purchase en terugbetalingPurchase wanneer de bevestigingspagina draait; terugbetalingen niet gezienPurchases uit het backoffice; terugbetalingen weer te geven vanuit orderdataPurchase twee keer gedekt en één keer samengevoegd; terugbetalingen blijven een ontwerpbeslissing
DeduplicatieNiet van toepassing — één bronNiet van toepassing — één bronMatchen op event_id en event_name
ConsentafhandelingGegated in de browser door de consenttoolJe pipeline moet het consentsignaal meedragen en geweigerde events onderdrukkenBeide kanten moeten hetzelfde signaal respecteren
Eigenaarschap van dataEventdata wordt door de browser samengesteld en verstuurdEventdata wordt door jouw infrastructuur samengesteld en verstuurdVerdeeld: de browser legt vast, de server stuurt door
Afhankelijkheid / lock-inHangt af van of de pagina draait en van browserbeschermingHangt af van je endpoint, token en id-schemaHangt af van of beide kanten het eens blijven
OnderhoudslastLaag, tot een privacy- of themawijziging het pad breektHet id-schema, de retries en de monitoring zijn van jouHet hoogst — twee paden die moeten matchen
Voor wie het pastWinkels met genoeg browsersignaal en geen andere Meta-bronWinkels waarvan het verlies in de browser zit en die een pipeline kunnen onderhoudenWinkels die volledige funneldekking willen en één getelde purchase

Beslistabel

Koppel de winkel die je voor je hebt aan een startpunt. Dit zijn standaardwaarden voor veelvoorkomende gevallen, geen regels.

Als je situatie is …Kies …
Je optimaliseert alleen voor Purchase en het browserpad dekt dat alAlleen browser-Pixel
Je wilt signalen uit de bovenkant van de funnel (view, add to cart) én purchasesBrowser-Pixel plus Conversions API, gededupliceerd op event_id
Je hebt purchases nodig die de browser nooit heeft afgerond — handmatige bestellingen, checkouts buiten de site, sommige upsellsConversions API, met de browser-Pixel behouden voor pagina-events
Een ander systeem stuurt Meta al een Purchase (een verkoopkanaal of een app)Bepaal welk enkel pad Purchase bezit en dedupliceer de rest op een gedeelde event_id
Je moet bepalen welke gebruikersparameters meereizen en wanneer consent de verzending blokkeertConversions API, doorgaans via server-side verzameling
Je kunt geen id onderhouden die herlaadbeurten overleeftAlleen browser-Pixel, en accepteer de dekkingsgrenzen
Meta en Shopify zijn het oneens over de totalenEerst reconciliatie — de mismatch kan aan telregels liggen, niet aan dekking

Wanneer je elke optie beter niet gebruikt

Een Pixel die alleen in de browser draait, is verkeerd wanneer het verlies in het transport zit; een server-only opzet is verkeerd wanneer niemand het id-schema onderhoudt; beide draaien is verkeerd wanneer niemand de id’s kan laten overeenkomen. Geen van de drie is een manier om consent te omzeilen.

Kies niet voor alleen browser wanneer:

  • De meeste purchases gebeuren na een pagina die vaak niet laadt, of binnen een post-purchase-flow.
  • Je campagnes consistent toegeschreven events uit de bovenkant van de funnel nodig hebben en je browserpad zwaar wordt geblokkeerd.
  • Je een kruiscontrole op het purchaseaantal wilt, die één enkele bron je niet kan geven.

Kies niet voor alleen server wanneer:

  • Je campagnes ViewContent en AddToCart nodig hebben voor catalogus- of retargetingpubliek; de server kan die niet zien tenzij de pagina ze verstuurt.
  • Je geen manier hebt om fbclid en browseridentifiers vast te leggen, zodat fbp en fbc ontbreken en de koppeling met de klik verdwijnt.
  • Niemand het token, de retries en de monitoring op zich neemt. Een serverpad faalt stil.

Kies niet voor beide wanneer:

  • Niemand één stabiele id kan definiëren die beide kanten produceren. Twee niet-gematchte bronnen blazen aantallen meer op dan één onvolmaakte bron.
  • De tweede bron een systeem is dat je niet kunt wijzigen — een kanaalapp die zijn eigen id genereert. Consolideer in plaats van een derde toe te voegen.

En geen van de drie lost dit op:

  • Consent. Een correct gebouwd serverpad onderdrukt nog steeds events voor bezoekers die hebben geweigerd. (Dit betreft technische implementatie, geen juridisch advies.)
  • Een verkeerde conversiedefinitie of een ontbrekend purchase-event.
  • De structurele kloof tussen de telling van Meta en de bestellingen van Shopify — dat is orderreconciliatie, geen nieuwe eventbron.

Hoe ik dit verifieer in echte implementaties

Ik verifieer door te tellen en te matchen, niet door dashboards te lezen: bevestig de live bronnen, bekijk een echt event in Test Events van Meta, controleer de id’s en reconciliëer het aantal tegen een Shopify-orderexport.

  1. Inventariseer elke bron die Meta-events kan sturen. Verkoopkanaal, apps, webpixel, themacode, serverpipeline. Duplicatie begint bij een bron die niemand zich herinnerde.
  2. Bekijk een live event. Gebruik Test Events in Events Manager en stuur een server-event met een test_event_code, zodat het naast het browser-event verschijnt. DebugView is het oppervlak van GA4 en toont geen Meta-events.
  3. Controleer de sleutel, niet alleen de aankomst. Bevestig dat de eventID van de browser en de event_id van de server dezelfde string zijn, en dat beide eventnamen exact overeenkomen. Een gededupliceerd paar is het signaal; twee afzonderlijke conversies zijn de bug.
  4. Bevestig de dekking aan beide kanten. Verifieer dat ViewContent, AddToCart en InitiateCheckout vanuit de browser aankomen, en dat Purchase voor dezelfde bestelling vanuit beide bronnen aankomt.
  5. Bevestig dat de identifiers meereizen. Controleer waar een browsercapture plaatsvond dat fbp en fbc op het server-event staan; waar dat niet gebeurde, ga nergens van uit.
  6. Reconciliëer tegen een afgesloten periode. Vergelijk het aantal purchase-events met een Shopify-orderexport over een vast venster.
  7. Bewijs consent in beide richtingen. Bevestig met geweigerd marketingconsent dat er niets afvuurt; geef het en bevestig dat events stromen.

Veelvoorkomende faalpatronen

De meeste storingen zijn niet exotisch: een id die verandert, een eventnaam die niet overeenkomt, een parameter die de server nooit heeft ontvangen, of een tweede bron die niemand zich herinnerde.

  • Een id die per paginalaad opnieuw wordt gegenereerd. Een event_id die bij het renderen uit een nieuwe UUID of een timestamp wordt opgebouwd, kan nooit matchen met de server-tweeling.
  • Een id die slechts aan één kant wordt afgeleid. De Pixel en de server sturen verschillende strings voor dezelfde bestelling, dus Meta ziet er twee.
  • Afwijkende eventnamen. Purchase aan de ene kant, purchase of een custom naam aan de andere. De id’s kunnen perfect matchen en toch faalt het.
  • Een ontbrekende id aan één kant. Niets om tegen te matchen.
  • Een vertraagde serververzending die buiten het matchvenster landt.
  • Een tweede bron die na een migratie aan blijft staan, waarbij elke helft zijn eigen id genereert.
  • Een server-event gemarkeerd als website zonder event_source_url of client_user_agent, wat geen geldig website-event is.
  • fbp/fbc aangenomen in plaats van vastgelegd. De server heeft ze alleen als de browser ze heeft doorgegeven.
  • Consent gerespecteerd in de browser, maar niet in de serverpipeline.

Beperkingen

Elke optie heeft een plafond dat wordt bepaald door wat hem bereikt. Een browser-Pixel kan niet rapporteren wat de browser nooit uitvoert; een server-only opzet kan geen pagina-events zien waarvan hem nooit is verteld; beide draaien kan zichzelf niet reconciliëren, omdat deduplicatie afhangt van identifiers die jij correct houdt.

Geen van deze opties verandert de telregels van Meta of de bestellingstotalen van Shopify. fbp en fbc helpen bij de koppeling wanneer ze aanwezig zijn, maar een serverpad zonder browsercapture zal ze niet hebben. De redundante opzet voegt ook onderhoud toe: twee paden die het voor onbepaalde tijd eens moeten blijven. En de consent- en dataminimalisatieverplichtingen gelden voor alle drie, waar het event ook wordt samengesteld. Gebruikt als wat elk is — een uitkijkpunt op de funnel — zijn ze complementair.

Alternatieven

Als het probleem niet is welke eventbron je kiest, maar wat er onderweg naar Meta met het verzoek gebeurt, ligt het antwoord een laag dieper: server-side verzameling via een first-party endpoint, beschreven op de dienstpagina server-side tracking en eerlijk afgewogen in Server-side tracking: voordelen, grenzen en architectuur.

Als je een Meta-pipeline kiest in plaats van een eventbron, staat de leveranciersvergelijking in Meta Conversions API op Shopify: native app vs Stape vs server-side GTM. Als het symptoom is dat Meta te veel rapporteert, begin dan bij de diagnose van Meta CAPI-deduplicatie en de mechanica in Meta CAPI-deduplicatie: hoe event_id echt werkt. Voor de Google-kant van dezelfde winkel, zie Het GA4 purchase-event op Shopify oplossen en Waarom de omzet van GA4 niet overeenkomt met Shopify-bestellingen. De concepten eronder staan in event ID, event match quality en Consent Mode v2.

Als de gids geen uitsluitsel gafEUR 375

Ik doe deze afstemming op je winkel alleen-lezen, voor EUR 375 — schriftelijk oordeel twee werkdagen na de kickoff.

Vraag een Health Check aan

Vragen

Vragen die deze gids beantwoordt

Heb ik de browser-Pixel nog nodig als ik een Conversions API vanaf de server stuur?

Meestal wel, en de eigen richtlijnen van Meta wijzen die kant op. De browser ziet de events op paginaniveau die de server niet kan waarnemen — ViewContent, AddToCart, InitiateCheckout — en hij legt de identifiers fbp en fbc vast die uit het bezoek en de advertentieklik komen. Een pipeline die alleen op de server draait, verliest die tenzij de pagina de informatie doorgeeft. Het aanbevolen patroon is beide, gededupliceerd op een gedeelde event_id.

Wat moet er precies overeenkomen zodat deduplicatie werkt?

Twee paren velden. De eventID van de Pixel moet gelijk zijn aan de event_id van de server, en het event van de Pixel moet gelijk zijn aan de event_name van de server. Wanneer beide overeenkomen en het tweede event binnen het matchvenster van Meta aankomt, wordt het ene behouden en het andere weggegooid. Als je event_name plus fbp en/of external_id consequent meestuurt, kun je op die methode terugvallen, maar die werkt doorgaans alleen wanneer het browser-event eerst aankomt.

Kan ik de Conversions API sturen zonder fbp en fbc?

Je kunt het event sturen, maar die velden ontbreken dan, en de koppeling met de klik die de browser zou hebben geleverd, is er niet. fbc komt uit een fbclid op de landings-URL en fbp wordt door de Pixel in de browser gezet; een server die nooit met de browser interacteert, heeft geen van beide en kan ze niet verzinnen. Wil je ze op server-events, dan moet de browser ze vastleggen en doorgeven.

Hoe controleer ik in Events Manager of deduplicatie werkt?

Gebruik Test Events in plaats van het geaggregeerde dashboard. Stuur een server-event met een test_event_code, zodat het naast het browser-event verschijnt, en bevestig daarna dat het paar als gededupliceerd verschijnt en niet als twee afzonderlijke conversies, waarbij de eventID van de browser en de event_id van de server als dezelfde string worden gelezen. De totalenweergave verbergt duplicatie; Test Events en het eventdetail laten zien hoe elk event is aangekomen.

Daniil Maximkin

Hoi, ik ben Daniil.

Ik werk met je samen, van probleemdefinitie tot implementatie en overdracht. Je praat met degene die het werk doet. Ik werk in het Engels en het Russisch.

Geprobeerd en kom je er nog niet uit?

Beschrijf je taak

Het eerste antwoord is gratis, binnen één werkdag. Of schrijf rechtstreeks: next@taskfordaniel.com