Eerst: wat dit is en wat het niet is
Alles in dit artikel dat op een case lijkt — de winkel, de bestelaantallen, de omzetcijfers, de uitkomst — is fictief. Het bestaat om de diagnosemethode te demonstreren en de vorm van de documenten die je zou ontvangen. Het is geen klantresultaat en het claimt er geen.
Ik heb de drie hieronder gelinkte voorbeeldrapporten precies hiervoor gebouwd. Elke pagina van elk rapport draagt het label “Illustrative sample · Fictional business, data and outcomes” (illustratief voorbeeld; fictief bedrijf, fictieve data en uitkomsten). Waar ik hier cijfers uit die rapporten aanhaal, zijn het die fictieve cijfers, en ik heb er geen toegevoegd.
Eén keer openheid: ik ben de oprichter van Fixel Pixel, een trackingproduct voor Shopify. Dit artikel gaat over de consultingmethode, niet over het product. Niets hieronder hangt ervan af, en een diagnose heeft het product nooit als verplichte uitkomst.
De opdracht
De advertentieplatforms van een Shopify-merchant en zijn eigen orderboek zijn het oneens over hoeveel er is verkocht en hoeveel purchases er zijn afgevuurd. Vanuit welk dashboard dan ook is niet te zien welk cijfer, als er al een klopt, het juiste is.
Dat is de hele opdracht, en die is lastiger dan hij klinkt, omdat de dashboards niet zichtbaar liegen. GA4 en Meta kunnen er allebei prima uitzien terwijl ze te weinig of te veel rapporteren van wat Shopify werkelijk verkocht. Het verschil wordt pas zichtbaar als je elk platform naast de bestellingsdata legt.
De randvoorwaarden
Drie randvoorwaarden bepalen alles wat volgt, en geen ervan is optioneel.
Er wordt niets veranderd voordat de diagnose compleet is. Een pipeline aanpassen voordat je hem begrijpt betekent een systeem diagnosticeren dat je net hebt gewijzigd. Dus het werk begint met alleen-lezen toegang — een viewer-rol in GA4, Google Ads alleen-lezen, Meta Events Manager en een Shopify-medewerkersaccount met alleen-lezen rechten — en er wordt niets aangepast tot de diagnose klaar is en de merchant hem heeft gezien.
Het oordeel eindigt in een vaste prijs, niet in een schatting. Een merchant die al heeft betaald voor “fix”-werk dat niets repareerde, heeft een toetsbare bewering nodig, geen nieuwe belofte. Een vaste prijs kan alleen voor een afbakenbare scope, dus de diagnose moet er een opleveren, of duidelijk zeggen dat dat nog niet kan, en waarom.
“Gekoppeld” kan niet op elk platform hetzelfde betekenen. GA4 draagt het Shopify order-id als transaction_id, dus een purchase-event kan worden verbonden met de bestelling die het veroorzaakte. Meta stelt zijn eigen event_id beschikbaar, die een purchase-event aan één bestelling koppelt en laat zien dat het één keer is geteld, maar Meta geeft geen omzet per bestelling. Google Ads rapporteert geaggregeerd, zonder feed per bestelling om te lezen. Het bewijspakket moet elke rij labelen naar wat hij daadwerkelijk kan aantonen.
Waarom de voor de hand liggende route niet paste
De voor de hand liggende zet is een pixel opnieuw installeren, server-side tagging aanzetten en het klaar noemen. Dat behandelt het symptoom — een dashboardcijfer oogt laag, of hoog — zonder ooit vast te stellen welk cijfer om te beginnen waar was.
Het overleeft ook de vraag “bewijs het” van de merchant niet. Er zit geen bewijsspoor per bestelling achter “het zou nu gefixt moeten zijn”, dus het volgende verschil tussen platforms zet je terug bij het begin, met één laag tracking extra om te ontwarren.
Wat ik in plaats daarvan doe
De methode is een vaste volgorde, en die volgorde doet ertoe.
-
Een alleen-lezen afstemming per bestelling over elk actief platform — de Health Check — die eindigt in een schriftelijk oordeel: de bevestigde oorzaak van elk wezenlijk verschil binnen de scope, of wat onbekend blijft, waarom, en hoe je het verifieert. Defecten, normale meetverschillen en onbevestigde hypothesen worden uit elkaar gehouden. Het oordeel is klaar twee werkdagen nadat de kickoff is afgerond en de toegang toereikend is bevonden (tijdzone Europe/Madrid, weekends uitgesloten). Als er data ontbreekt, is de klok niet gestart, en dat zeg ik in plaats van de termijn stilletjes op te rekken. Je houdt het rapport hoe dan ook, ook als het antwoord “er is niets kapot” is.
-
Een schriftelijke scope en één vaste prijs, opgegeven vóór enige codewijziging, voor een scope die strak genoeg is afgebakend om te kunnen worden geprijsd. De implementatie is een aparte opdracht.
-
De fix, gebouwd parallel aan de bestaande opzet. De oude tracking blijft draaien tot de nieuwe route is bewezen met een echte testbestelling, in de volgorde waarin events moeten afvuren: consent, dan deduplicatie, dan de platformspecifieke payload. Een purchase-event dat correct afvuurt maar buiten die volgorde, is nog steeds kapot.
-
Een afstemmingsbewijspakket als deliverable. Een tabel per bestelling, elk platform naast Shopify als ground truth, met het verschil duidelijk getoond en elke rij gelabeld naar wat hij wel en niet kan aantonen. Als de cijfers nog altijd niet kloppen, blijft de opdracht open.
De rest van dit artikel loopt die volgorde door op de fictieve winkel.
Deel 1 — de audit (illustratief, fictieve data)
Het eerste document is Sample 01 — Measurement Audit (PDF; illustratief, fictieve data). Stel je een abonnementswinkel in voeding voor, die in Amerikaanse dollars handelt, met een maatwerk purchase-feed die verkopen naar een rapportagedataset stuurt. In een reviewvenster van één week maakte hij 1.000 in aanmerking komende betaalde bestellingen aan. De ontvangende dataset bevat 1.120 purchase-rijen.
Dat gat is de bevinding, maar nog geen diagnose. De audit koppelt bronbestellingen aan bestemmingsrijen via een stabiele bestelreferentie en bekijkt wat niet één-op-één matcht voordat er iets wordt opgeteld:
Vergelijkingstabel — scrol horizontaal om alle kolommen te bekijken
| Stap in de brug | Purchase-rijen | Productomzet |
|---|---|---|
| Ontvangende dataset, ongecorrigeerd | 1.120 | $134,400 |
| Min dubbele rijen voor 120 bestellingen | −120 | −$14,400 |
| Unieke in aanmerking komende bestellingen | 1.000 | $120,000 |
| Min terugbetalingen op dezelfde bestellingen tot de peildatum | geen wijziging in aantal bestellingen | −$5,000 |
| Netto productomzet op de peildatum | 1.000 betaalde bestellingen | $115,000 |
Twee verschillende dingen zaten verstopt in één klacht “de omzet is te hoog”. De 120 dubbele rijen zijn een bevestigd defect: de bestemming accepteerde een purchase, de verzender ontving nooit het succesantwoord, en de retry genereerde een nieuwe verkoopidentiteit die als een tweede purchase werd geaccepteerd. Koppelen op de bestelreferentie legt de herhalingen bloot; koppelen op alleen de leveringsidentiteit verbergt ze. De $5,000 daarentegen is helemaal geen defect. Het is het verschil tussen productomzet en netto productomzet na terugbetalingen, twee definities die niemand had opgeschreven.
Een derde punt blijft bewust open: 60 bestellingen missen de klantgeschiedenis die nodig is om ze als eerste of herhaalaankoop te classificeren. De audit zegt: houd ze op “onbekend”, behandel ze niet als nieuwe klanten.
De audit benoemt ook zijn eigen dekking — wat is bekeken, wat is getest, en dat de bevinding geldt voor de geauditeerde maatwerkfeed, niet voor elk advertentieplatform. Daarna levert hij een werklijst met per punt een eigenaar en een acceptatievoorwaarde, een release- en rollbackplan, en sluitcriteria: de oorspronkelijke cohort stemt af op 1.000 bestellingen en $120,000 productomzet, en een apart venster van na de release stemt ook af.
Deel 2 — de documentatie (illustratief, fictieve data)
Een fix die zes maanden later niemand meer kan vinden, is een fix die wacht om ongedaan gemaakt te worden. Daarom is het tweede document, Sample 02 — Tracking Documentation (PDF; illustratief, fictieve data), een systeemregister: elk component, waar het leeft, wie de eigenaar is, waarvoor het verantwoordelijk is en, minstens zo belangrijk, wat het niet doet.
Het eventrecord voor de purchase is het onderdeel dat voorkomt dat het defect terugkomt. In het voorbeeld definieert het een stabiele verkoopidentiteit per bestelling en bestemming die bij retries behouden blijft, zodat een timeout gevolgd door een retry één verkooprij oplevert; een eventtijd die niet verschuift als er een retry plaatsvindt; omzet na kortingen en vóór terugbetalingen, exclusief btw en verzending; een klantstatus van eerste, herhaal of onbekend; en terugbetalingscorrecties als aparte, aan de bestelling gekoppelde records die nooit een tweede purchase versturen.
Het somt ook de routinechecks op: wat je draait na een wijziging aan de collector of de feed, wat een geplande afstemming vergelijkt, wat je vastlegt als een cijfer verkeerd oogt, en wat er moet worden bijgevoegd voordat een wijziging wordt gesloten.
Deel 3 — de oplossing en validatie (illustratief, fictieve data)
Het derde document, Sample 03 — Issue Resolution & Validation (PDF; illustratief, fictieve data), sluit de twee bevindingen apart af, omdat het verschillende soorten dingen zijn.
De vraag over de $5,000 wordt opgelost zonder enige trackingconfiguratie aan te raken. Beide rapporten bevatten dezelfde 1.000 bestellingen; de gecorrigeerde purchase-weergave telt op tot $120,000; finance trekt $5,000 aan terugbetalingen op dezelfde bestellingen tot de peildatum af; en $120,000 − $5,000 = $115,000 laat een onverklaard verschil van nul over. De oplossing bestaat uit twee opgeslagen weergaven, “productomzet” en “netto productomzet”, met de peildatum van de terugbetalingen zichtbaar.
Het defect met de dubbele leveringen wordt aangepakt in de volgorde die ik voor elk defect gebruik:
- Koppel bestellingen aan bestemmingsrijen. 880 bestellingen hebben één rij, 120 hebben er twee, en elke dubbele rij komt overeen met de oorspronkelijke bestelwaarde.
- Traceer het mechanisme. De eerste levering werd geaccepteerd, het antwoord liep in een timeout, en de retry gebruikte een nieuwe verkoopidentiteit.
- Reproduceer voordat je code wijzigt. Een fixture van 1.000 bestellingen met 120 geaccepteerd-maar-timeout-gevallen levert 1.120 rijen op.
- Repareer en herhaal dezelfde test. 1.000 rijen, en werkelijk verschillende bestellingen maken nog steeds aparte verkopen aan.
- Release en corrigeer de rapportage. Sluit de 120 bewezen dubbele rijen uit van de rapportageweergave; bewaar de ruwe rijen en de uitsluitingsredenen.
- Verifieer live en sluit af. Een aparte, uitgekristalliseerde cohort van na de release met 250 betaalde bestellingen stemt af op 250 bestemmingsrijen zonder onverklaard verschil in productwaarde.
De afsluittabel zet voor en na naast elkaar, de acceptatiechecklist zegt wat is geslaagd, en één punt gaat mee: de 60 klantclassificaties “onbekend”, die het opgeloste defect niet heropenen.
Hoe ik dit verifieer in echte implementaties
Het fictieve voorbeeld is netjes. Echte winkels zijn dat niet, en de methode is daarop gebouwd.
De koppeling is altijd aan het orderboek van Shopify, één rij per bestelling met zijn omzet. Het eerste waar ik naar kijk zijn de rijen die niet één-op-één matchen — ontbrekend, dubbel of met een andere waarde — voordat er iets wordt opgeteld, omdat een totaal per toeval kan kloppen.
Een echte testbestelling gaat door elke nieuwe eventroute voordat die live gaat, en acceptatie hangt ervan af of de afstemming van elk platform met die bestelling overeenkomt, niet of een deploy zonder fouten afrondt.
De oude implementatie gaat pas met pensioen als de nieuwe zich heeft bewezen op live verkeer, met een rollbackpad bij elke wijziging. Als iets binnen de scope in de maand na acceptatie van de fix verschuift, kijk ik ernaar.
Wat de methode wel en niet kan bewijzen
De genoemde beperking zit in de methode zelf, niet in de kleine lettertjes.
Google Ads rapporteert geaggregeerd, dus de vergelijking daar is tussen de bestellingen die een conversie hadden moeten opleveren en de conversies die voor hetzelfde venster worden gerapporteerd; bewijs per bestelling bestaat alleen waar jij de conversie-uploads beheert. De matching per event van Meta laat zien welke purchase-events zijn aangekomen en één keer geteld, maar kan geen omzet per bestelling zien. Het bewijspakket zegt welke vergelijking elke rij ondersteunt in plaats van een gelijkheid tussen platforms te suggereren die niet bestaat.
De eigen slotverklaring van het voorbeeld is de eerlijke. Het gedocumenteerde defect is opgelost in de faaltest en in de gecontroleerde cohort van na de release. Dat bewijst geen universele attributie, geen volledigheid op elk advertentieplatform en geen betere ROAS; die hebben elk hun eigen validatie per bestemming nodig.
Het venster van 30 dagen van de Health Check is een basis, geen belofte van volledige historie. Een oordeel benoemt de bevestigde oorzaak waar die er is, en waar die er niet is, zegt het wat onbekend blijft en hoe je het verifieert.
Nog één keer, zodat het niet verkeerd gelezen kan worden
De winkel, de cijfers en de uitkomst hierboven zijn fictief, gebouwd om de methode te laten zien. Dit artikel demonstreert hoe ik werk. Het is geen bewijs van een resultaat voor welke klant dan ook, en de drie PDF’s zijn voorbeelden van formaat en redenering, geen verslagen van een opdracht.
Wil je de methode op je eigen winkel laten draaien, dan begint dat alleen-lezen, en het oordeel is van jou, wat het ook zegt.
Bronnen voor dit artikel
De methode is die welke op deze site staat beschreven; het uitgewerkte voorbeeld is de driedelige reeks voorbeeldrapporten. Er is niets anders gebruikt.
- Methode — Diagnosticeren, repareren, bewijzen: het verloop van een opdracht, de leverstandaard en “hoe matching werkt”.
- Sample 01 — Measurement Audit (PDF): illustratief, fictieve data.
- Sample 02 — Tracking Documentation (PDF): illustratief, fictieve data.
- Sample 03 — Issue Resolution & Validation (PDF): illustratief, fictieve data.