E-commerce
Shopify LCP-slopers: een veldgids voor de trage zeven
Je opent PageSpeed Insights om middernacht, de productpagina komt uit op 4,2s LCP, en het thema is de boosdoener niet. De zeven apps die je vorig kwartaal installeerde wel.

Waar die 1,8 seconde zich verstopt
Je opent PageSpeed Insights om middernacht, de productpagina komt uit op 4,2s LCP, en Dawn is de boosdoener niet. De hero-afbeelding is in orde. De fonts zijn gepreload. De zeven Shopify-apps die je vorig kwartaal installeerde, elk met de belofte van "minimale impact op de snelheid van je winkel" in de app store, vormen samen anderhalve seconde aan third-party JavaScript die vecht om de main thread.
Dit is een veldgids voor de gebruikelijke verdachten. De cijfers hieronder komen uit echte audits die we draaiden op echte winkels op geknepen 4G, op de productpagina die er echt toe doet (degene waar je advertenties naartoe wijzen). De exacte getallen verschillen per thema en app-versie, maar het patroon is consistent in elke Shopify-winkel die we sinds 2024 hebben bekeken.
Largest Contentful Paint is het moment waarop het grootste element boven de vouw klaar is met painten. Op een typische Shopify-productpagina is dat element de productafbeelding. Elk script dat vecht om de main thread voordat die afbeelding decodeert, belast je LCP, zelfs als het script zelf asynchroon laadde. Async betekent non-render-blocking. Het betekent niet gratis.
De review-widget
Judge.me, Loox, Yotpo. Kies je gif. Sterren bij de producttitel zijn omzet boven de vouw, dus de widget heeft alle reden om synchroon te renderen. Loox levert in het bijzonder zijn eigen font, zijn eigen carousel-library, en een poll-lus die elke 250ms de DOM scant op review-haken totdat hij ze vindt.
Typische LCP-kosten die we in audits zien: 200ms tot 400ms. De oplossing is zelden "verwijderen". Meestal is het een van drie dingen:
- Vervang de live widget door server-rendered sterren-markup die de app na LCP hydrateert.
- Verplaats de foto-review carousel naar onder de vouw zodat hij niet om paint vecht.
- Gebruik het Theme App Extension-blok van de app in plaats van zijn legacy ScriptTag-injectie. Dat geeft je controle over plaatsing en timing.
De valuta- en geolocatie-switcher
Verkoop je internationaal en gebruik je nog een third-party valuta-app (iets anders dan Shopify Markets), dan ga je hier last van krijgen. Het patroon is voorspelbaar: de app haalt het IP van de bezoeker op, slaat zijn eigen geolocatie-API aan, en re-rendert vervolgens elke prijs op de pagina. Dat is een layout shift die je in CLS terugziet, plus een render-blocker die je in LCP terugziet.
Shopify Markets heeft de meeste van deze apps overbodig gemaakt. Markets regelt valuta via de storefront-API en Shopify's CDN, zonder extra client script. Migreerde je vorig jaar naar Markets en vergat je de oude converter te verwijderen, dan betaal je voor allebei.
De e-mail pop-up
Privy, Klaviyo Forms, Justuno. De pop-up verschijnt na zeven seconden, dus je zou denken dat hij LCP niet kan beïnvloeden. Toch wel. De library wordt geladen bij pageload. Hij parset je A/B-testconfig. Hij plaatst event listeners op elk klikbaar element op de pagina. Alleen de onsite-forms-bundle van Klaviyo is al ongeveer 90KB gzipped voordat je eigen formuliercode überhaupt draait.
Een "async" pop-up script draait nog steeds op de main thread zodra het binnenkomt. Je LCP komt niet later doordat het script de parser blokkeerde. Het komt doordat het script de renderer blokkeerde op het moment dat het ging draaien, ongeveer tegelijk met het moment dat je hero-afbeelding wilde decoderen.
De chatbubbel
Tidio, Gorgias Chat, Shopify Inbox, Tawk.to. De chatbubbel is in onze ervaring de grootste third-party kostenpost op de meeste Shopify-pagina's. De widget laadt, opent een websocket, registreert service workers, en op sommige stacks laadt hij een tweede iframe voor het eigenlijke chatvenster.
Beantwoord je chats niet binnen vijf minuten tijdens kantooruren, dan kost de bubbel je LCP en converteert hij niks. We hebben verschillende klanten verhuisd naar een statisch contactformulier buiten kantooruren, met de chat-widget alleen lazy-loaded op de contactpagina zelf. LCP herstelde 300ms tot 500ms op elke andere pagina in de winkel, inclusief de productpagina's waar de advertenties naar wezen.
De cart drawer en upsell-engine
ReConvert, Bold Upsell, Honeycomb. Deze apps injecteren een cart drawer en een upsell-modal op elke pagina, niet alleen op de cart. De CSS van de drawer is render-blocking. De product feed van de modal wordt bij pageload opgehaald, zodat hij "klaar" is op het moment dat de bezoeker iets aan de cart toevoegt.
Niks daarvan hoeft klaar te zijn voordat LCP afgaat. Een moderne cart drawer kun je lazy-loaden op het moment dat de bezoeker op "in winkelwagen" klikt. De 200ms tot 300ms die je vooraan bespaart, is van jou op elke pageview die niet in een conversie eindigt. Dat zijn er nogal wat.
De page builder
PageFly, Shogun, GemPages. Page builders lossen een echt lastig probleem op: het marketingteam wil landingspagina's lanceren zonder Liquid aan te raken. Ze nestelen ook de hele builder-runtime in elke pagina die ze genereren. Een PageFly-homepage levert standaard 600KB aan builder-specifieke CSS en JS af voordat je eigen content arriveert.
De verschuiving naar Theme App Extensions plus Shopify's section-rendering API betekent dat de meeste page-builder use cases inmiddels door native sections opgelost kunnen worden. Delen je landingspagina's allemaal hetzelfde skelet (hero, drie kolommen, video, CTA), dan heb je geen builder nodig. Je hebt drie Liquid-secties nodig en een Slack-thread met je developer.
De trust strip en countdown-balk
De "Gratis verzending / 30 dagen retour / Nog 3 op voorraad!"-balk. Meestal een widget van 30KB voor iets wat drie Liquid-spans en een CSS-animatie hadden kunnen zijn. De countdown-timer leest voorraad uit via AJAX bij pageload, wat een extra round-trip oplevert voordat LCP kan painten als de balk boven de hero staat.
Moet je een third-party trust strip houden, zet 'm dan onder de vouw. De bezoeker ziet 'm voordat hij eraan voorbij scrollt. Hij heeft 'm niet nodig tijdens de initial paint.
De audit van 30 minuten die je vandaag kunt draaien
Begin met het ophalen van elke ScriptTag die je winkel heeft geïnjecteerd. De meeste merchants zijn verbaasd om apps tegen te komen die ze maanden geleden hebben verwijderd, maar nog steeds scripts injecteren. Verwijderen laat soms ScriptTags wees achter, en het opruimen van de app is de verantwoordelijkheid van de app-developer, niet die van Shopify.
curl -s "https://yourstore.myshopify.com/admin/api/2024-04/script_tags.json" \
-H "X-Shopify-Access-Token: $TOKEN" | jq '.script_tags[] | {id, src, event}'Je krijgt een lijst zoals deze:
[
{"id": 81923, "src": "https://cdn.judge.me/widget.js", "event": "onload"},
{"id": 81924, "src": "https://static.klaviyo.com/onsite/js/klaviyo.js", "event": "onload"},
{"id": 81925, "src": "https://app.tidio.co/talk.js", "event": "onload"}
]Vergelijk met je geïnstalleerde apps. Alles wat niet matcht met een momenteel geïnstalleerde app is een wees. Verwijder die via hetzelfde endpoint (DELETE /script_tags/{id}.json). De ScriptTag API-docs van Shopify behandelen de auth, paginering en de response codes die je wilt afhandelen.
Draai daarna Lighthouse tegen je productpagina met het meeste verkeer (degene waar de advertenties naar wijzen, niet de homepage), met het netwerk geknepen tot de verbinding die je bezoekers daadwerkelijk gebruiken:
npx lighthouse https://yourstore.com/products/$YOUR_TOP_SKU \
--only-categories=performance \
--throttling-method=simulate \
--form-factor=mobile \
--output=json --output-path=./before.jsonVerwijder één app. Draai opnieuw. Vergelijk het LCP-getal. Herhaal. Voor de lunch ben je klaar en weet je voor welke van de zeven apps je in seconden betaalt, elke keer dat een bezoeker op een productpagina landt.
Toen we eerder dit jaar de Shopify front-end voor HorizonCanvasCo herbouwden, liepen we ertegenaan dat drie van de zeven apps op deze lijst technisch verwijderd waren, maar nog steeds scripts injecteerden via wees-geraakte ScriptTags. We losten het op zoals jij dat zou doen: API-call, lijst, verwijderen, opnieuw testen. Het is het soort operationele opschoning waar ons webwerk meestal mee begint voordat enig nieuw ontwerp de storefront raakt.
Kern
Shopify LCP-problemen zitten zelden in het thema. Het zijn zeven kleine apps die elk 200ms boven de vouw toevoegen, vaak inclusief wezen van apps die je allang verwijderd hebt.
FAQ
Verwijdert het uninstallen van een Shopify-app ook zijn ScriptTags?
Meestal wel, maar niet altijd. Sommige apps ruimen op bij uninstall, andere laten ScriptTag-entries wees achter. Check de admin-API en verwijder alles wat niet matcht met een momenteel geïnstalleerde app.
Is Shopify Markets genoeg om een third-party valutaconverter te vervangen?
Voor de meeste winkels wel. Markets regelt valuta, geolocatie en btw via Shopify's CDN zonder extra client script. De third-party app is na migratie meestal overbodig en voegt alleen laadtijd toe.
Schaadt het lazy-loaden van de chat-widget je supportreactietijd?
Alleen als je team chats binnen minuten beantwoordt tijdens kantooruren. Doe je dat niet, dan herstelt het lazy-loaden van de bubbel naar de contactpagina LCP overal elders, zonder meetbaar conversieverlies.
Waarom beïnvloedt een async script alsnog je LCP?
Async betekent non-render-blocking op het moment van laden. Zodra het script binnenkomt en draait, bezet het de main thread. Dat is dezelfde thread die je hero-afbeelding decodeert. De strijd erom zie je terug in je LCP-getal.