Als je Shopify-winkel vroeger purchases naar GA4 stuurde en nu niets meer stuurt, of ze dubbel stuurt, controleer dan waar het purchase-event wordt verzameld. Deze gids behandelt de huidige eventroute van Shopify, de uitgefaseerde scriptlocaties en de beperkingen van een custom pixel.
Hoe vuurt Shopify het purchase-event vandaag af?
Shopify heeft de checkout ondergebracht in een uitbreidbaar model, en tracking is daarin meeverhuisd. In plaats van scripts in checkoutpagina’s te injecteren, registreer je een pixel die zich abonneert op de events die Shopify uitstuurt — page views, product views, add-to-cart en, voor de voltooide bestelling, checkout_completed.
Het belangrijke architecturale feit is de sandbox. Custom pixels draaien niet op je storefront-pagina. Ze draaien in een aparte, beperkte context met hun eigen window, geïsoleerd van de scripts van je thema. Dat is bewust zo: het voorkomt dat pixels van derden alles op de pagina kunnen uitlezen. Maar het heeft twee gevolgen waar bijna elke kapotte setup die ik tegenkom op stukloopt:
- Een GTM-container of
gtag-snippet die door je thema wordt geladen, kan geen checkout-events zien, omdat de pixel en het thema in verschillende contexten leven. - Alles wat je vanuit de checkout wilt versturen — je GA4-tag inbegrepen — moet binnen de pixel zelf worden geladen, of vanuit Shopify naar een server worden doorgestuurd.
Zodra je dat doorhebt, kloppen de oude symptomen ineens: de reden dat de GTM van je thema geen purchases meer opving, is geen bug — het is de sandbox die zijn werk doet.
Wat is er gebeurd met Additional Scripts en checkout.liquid?
Twee oudere methodes duiken nog op in handleidingen en overgenomen winkels, en allebei zijn ze doodlopende wegen.
- Aanpassingen aan
checkout.liquidwaren de manier waarop Plus-winkels tracking in de checkout injecteerden. Die route is uitgefaseerd ten gunste van checkout extensibility. - Additional Scripts op de Thank you- en Order status-pagina’s was een oude trackinglocatie. 28 augustus 2025 was de einddatum voor Plus. Voor niet-Plus-winkels maakte Shopify Additional Scripts toen alleen-lezen en werd de pagina-upgrade uiterlijk 26 augustus 2026 verplicht. Order status-script tags hadden dezelfde einddatums per plan. Controleer de paginaversie en bestelgegevens in plaats van één datum op alle winkels toe te passen.
De praktische conclusie: als een winkel zijn purchase-tag nog in Additional Scripts heeft staan, controleer dan of die daadwerkelijk draait en of een andere integratie de purchase verstuurt. Als de tag niet meer draait, migreer het ontbrekende event naar een ondersteunde pixel en verifieer het met een testbestelling en orderreconciliatie.
De beperkingen van een custom-pixelimplementatie
Google ondersteunt geen Google-tags in custom pixels van Shopify en beveelt de Google & YouTube-app aan. Een tag in een sandbox kan data versturen terwijl andere functies niet werken. Ik bekijk de ondersteunde app voordat ik voor een eigen implementatie kies.
Het volgende is een hypothetisch custom-pixelvoorbeeld, geen ondersteunde Google-opzet of geteste productie-implementatie. Het toont de eventmapping voor een geüpgradede checkout met kortingen per bestelregel. Kortingen op bestelniveau en prijzen inclusief belasting moeten apart met de bestelling worden gecontroleerd; dit voorbeeld bewijst die aanpassingen niet. De sandbox laadt gtag zelf in plaats van de tag van het thema te gebruiken.
// Shopify admin → Settings → Customer events → Add custom pixel
// Deze code draait in de pixel-sandbox van Shopify: hij heeft zijn eigen
// window, geïsoleerd van je thema. Een GTM/gtag-snippet op het thema is
// HIER NIET bereikbaar, dus laad gtag binnen de pixel en vuur van hieruit af.
const MEASUREMENT_ID = 'G-XXXXXXXXXX';
// 1) Laad gtag.js in de sandbox en configureer GA4
const s = document.createElement('script');
s.src = 'https://www.googletagmanager.com/gtag/js?id=' + MEASUREMENT_ID;
s.async = true;
document.head.appendChild(s);
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', MEASUREMENT_ID, { send_page_view: false });
// 2) Vuur de purchase precies één keer af, wanneer de checkout wordt voltooid
analytics.subscribe('checkout_completed', (event) => {
const checkout = event.data.checkout;
if (!checkout.order?.id || !checkout.currencyCode || !checkout.lineItems?.length) return;
const items = (checkout.lineItems || []).map((line) => ({
item_id: line.variant && (line.variant.sku || line.variant.id),
item_name: line.title,
item_variant: line.variant && line.variant.title,
price: line.finalLinePrice.amount / line.quantity,
quantity: line.quantity,
}));
gtag('event', 'purchase', {
transaction_id: checkout.order.id,
value: items.reduce((sum, item) => sum + item.price * item.quantity, 0),
currency: checkout.currencyCode,
tax: checkout.totalTax && checkout.totalTax.amount,
shipping:
checkout.shippingLine &&
checkout.shippingLine.price &&
checkout.shippingLine.price.amount,
items: items,
});
});
Als je in plaats daarvan via Google Tag Manager routeert, duwt hetzelfde analytics.subscribe-blok een gelijkwaardig object naar een dataLayer die wordt uitgelezen door een container die binnen de pixel is geladen. De regel verandert niet: de doeltag moet samen met het abonnement in de sandbox leven, niet in het thema. Voor de mechaniek van dat object, zie de toelichting over de dataLayer.
Waar moet de GA4 items-array aan voldoen?
Google noemt items en transaction_id verplichte purchase-parameters. Een ontvangen event zonder die parameters bewijst niet dat de ecommerce-implementatie aan het gedocumenteerde schema voldoet.
Volgens de ecommerce-referentie van Google heeft elk item minstens één van item_id of item_name nodig; beide versturen maakt controle eenvoudiger. price, quantity en item_variant maken de itemrapporten bruikbaar. Een paar regels die je debugtijd besparen:
valueis de som vanprice × quantityper item, zonder belasting en verzending. Gebruik eenheidsprijzen na korting en verstuur belasting en verzending in hun aparte parameters. Vergelijk dezelfde waardedefinitie met Shopify.currencyis verplicht en moet een ISO-code van drie letters zijn. Stuur in winkels met meerdere valuta’s de valuta waarin de klant daadwerkelijk heeft afgerekend, en zorg datvaluein diezelfde valuta staat.item_idmoet stabiel zijn. Gebruik consequent de SKU of het variant-ID, want dat is de sleutel die GA4 gebruikt om items tussen events aan elkaar te koppelen.
Hoe dedupliceert GA4 Shopify-purchases?
GA4 dedupliceert purchases met dezelfde transaction_id in webstreams. Google beschrijft dit voor transacties van dezelfde gebruiker; het is geen garantie voor verschillende gebruikerscontexten of appstreams. Twee regels zijn belangrijk:
- Vuur de purchase vanuit precies één route af. Het native GA4-kanaal van Shopify en een custom pixel kunnen dezelfde bestelling in verschillende gebruikerscontexten versturen. Een overeenkomend transaction ID bewijst op zichzelf niet dat deduplicatie werkte. Kies één route en controleer het ontvangen event.
- Stuur nooit een lege transaction_id. GA4 dedupliceert alle purchases met een lege transaction ID samen, dus een lege waarde helpt niet alleen niet — hij smelt echte bestellingen actief samen tot één. Stuur altijd het echte order-ID.
Als je al hebt gezien dat GA4 hoger uitkomt dan Shopify, is deduplicatie de eerste plek om te kijken. Het bijbehorende artikel over waarom de omzet van GA4 niet overeenkomt met Shopify laat zien hoe je die duplicaten opspoort tijdens reconciliatie.
Verificatieprotocol
Verifiëren binnen de sandbox werkt anders dan het verifiëren van een normale pagina, en het gebruikelijke eerste instinct — GTM Preview of Tag Assistant openen — werkt hier grotendeels niet. Dit is de volgorde die ik vertrouw.
- DebugView, met een echte bestelling. Zet een testapparaat in debugmodus en doorloop een echte checkout. Kijk hoe de
purchasebinnenkomt in DebugView en inspecteer de parameters: istransaction_idaanwezig en niet leeg, kloptvalue, kloptcurrency, bevatitemsde producten? - Realtime als sanity check. De purchase zou binnen enkele ogenblikken in het Realtime-rapport moeten verschijnen. Realtime bevestigt dat het event binnenkomt, zelfs als het koppelen met DebugView lastig is.
- Accepteer de beperkingen van de tools. Tag Assistant en GTM Preview kunnen niet inhaken op de pixel-sandbox zoals ze dat op een pagina doen. Het event daar niet zien is te verwachten; het is geen bewijs dat de pixel faalde. Beoordeel succes op basis van DebugView en Realtime.
- Elke betaalroute, niet één. Test kaartbetaling, Shop Pay, express- of wallet-checkout en post-purchase-upsells. Shopify publiceert
checkout_completedéén keer: meestal op Thank you, maar bij post-purchase-flows op de eerste upsellpagina. Als die pagina niet laadt, wordt het event niet verstuurd. - Vergelijk na verwerking. Vergelijk GA4-purchases met Shopify-bestellingen op transaction ID nadat de rapporten zijn verwerkt. Volgens Google kan verwerking 24–48 uur duren. Reconciliatie meet geregistreerde dekking; het bewijst niet dat browsertracking elke bestelling heeft vastgelegd ongeacht consent of een pagina die niet laadt.
Veelvoorkomende faalpatronen
- Dubbele pixels. Het native GA4-kanaal en een custom pixel kunnen dubbele purchases versturen. Gebruik één purchase-route en controleer ID’s en gebruikerscontext voordat je concludeert dat de omzet verdubbeld is.
- Ontbrekende express-routes. De purchase is gekoppeld aan een flow die Shop Pay of express checkout overslaat, waardoor wallet-bestellingen nooit een purchase versturen en verdwijnen tijdens reconciliatie. Dit is hetzelfde type fout als in kapotte Shopify-checkouttracking.
- Blokkering door consent. Onder een consentbanner kan analytics-opslag geweigerd worden, waardoor de pixel voor die bezoekers niet mag versturen. Dat is een legitiem verlies, geen bug om omheen te coderen. Dit betreft technische implementatie, geen juridisch advies — zie voor het mechanisme consent mode v2.
- Verouderde tag in Additional Scripts. De purchase staat nog op een uitgefaseerde scriptlocatie. Controleer de paginaversie en of een vervangende pixel of app het event al verstuurt voordat je de opzet wijzigt.
- Lege of niet-overeenkomende transaction_id. Een lege ID smelt bestellingen samen; een ID dat per route verschilt, ondermijnt deduplicatie volledig. Zie de gerelateerde uitleg bij GA4 registreert geen purchases.
Beperkingen
Een custom pixel heeft de beperkingen van browsertracking en is niet de ondersteunde Shopify-integratie van Google. De ingestelde privacyvoorwaarden kunnen de pixel blokkeren zolang consent is geweigerd. Een pagina die niet laadt of browserblokkering kan de verzameling ook verhinderen.
De sandbox beperkt ook het debuggen, dus verificatie leunt op DebugView, Realtime en reconciliatie in plaats van de gebruikelijke page-level inspectors. En een pixel repareert de purchase; hij herstelt op zichzelf geen upstream-events zoals add-to-cart als die door dezelfde checkout-migratie kapot zijn gegaan.
Alternatieven
Er zijn drie brede manieren om de Shopify-purchase te versturen, en ze sluiten elkaar niet uit.
- Native Shopify-integratie. De Google & YouTube-app is de ondersteunde opzet van Google. Controleer vóór installatie of er al een eigen purchase-tag is, zodat niet twee routes dezelfde bestelling versturen.
- Custom pixel met GTM of gtag (het hypothetische voorbeeld hierboven). Je beheert de code, maar Google ondersteunt deze opzet niet. Eén succesvol verstuurd event bewijst niet dat andere Google-tagfuncties werken.
- Server-side. Een server-side opzet kan Shopify-orderwebhooks doorsturen terwijl browserevents sessie- en consentcontext aanleveren. Webhooks bevatten geen browsercookies. De opzet vraagt om hosting, monitoring en een consentontwerp; de consentvereiste blijft bestaan.
Als je wilt dat ik de purchase-route voor je kies, controleer en met bestellingen vergelijk in plaats van dat je die zelf onderhoudt, valt dat onder mijn GA4-implementatiewerk; de verificatiemethode is orderreconciliatie.