Chatwidget met perfecte Core Web Vitals

Laad chatwidgets zonder PageSpeed te verliezen

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-02-26

Hoe je een chatwidget op de juiste manier laadt

Ik heb het keer op keer gezegd. Sommige scripts zijn belangrijker dan andere. Niemand in de geschiedenis van het internet heeft zich er ooit aan geërgerd dat een chatwidget niet binnen de eerste 500ms van het laden van de pagina is geladen. Die tijd dat de pagina nog leeg is.

Het zou toch nergens op slaan om een chatwidget te laden voordat de hoofdcontent van de pagina überhaupt is begonnen met laden? Nee, het zou veel logischer zijn om eerst de belangrijkste onderdelen te laden (je logo, je hoofdafbeelding, je stylesheets, je lettertypen, misschien wat superbelangrijke scripts die navigatie en conversie afhandelen).

Onderzoeken tonen aan dat slechts 3 tot 10 procent van de bezoekers daadwerkelijk een chatwidget gebruikt tijdens hun sessie. Het uitstellen van het chatscript kost je niets qua user experience, maar levert je alles op qua paginasnelheid.

Helaas is dit niet hoe de meeste websites het aanpakken. Dagelijks zie ik onbelangrijke scripts (zoals chatscripts) met de hoogste prioriteit laden, direct aan het begin van het laden van de pagina.

In dit artikel zal ik uitleggen hoe je een chatscript correct laadt en hoe dit belangrijke metrics zoals de Largest Contentful Paint en de Interaction to Next Paint beïnvloedt.

Laatst beoordeeld door Arjen Karel in februari 2026

Achtergrond: hoe werken chatwidgets

Een chatwidget werkt meestal door een klein script op je pagina te laden. Dat script laadt een aantal stijlen en injecteert een iframe op je pagina. Een iframe is een kleine, geïsoleerde webpagina binnen een webpagina. En die iframe regelt alles wat nodig is om met je klanten te chatten.

Hoe beïnvloeden chatwidgets de Core Web Vitals?

Chatwidgets beïnvloeden de Core Web Vitals op een paar manieren:

1. Ze beïnvloeden de First Contentful Paint en Largest Contentful Paint door te concurreren om vroege netwerkbronnen.

2. Ze beïnvloeden de Interaction to Next Paint door de main thread te blokkeren en soms door traag te updaten na een interactie.

3. Ze kunnen layout shifts veroorzaken wanneer ze niet correct renderen op de pagina.

De impact varieert enorm per aanbieder. De zwaarste chatwidgets (Zendesk, Tawk.to) laden 500 tot 750 KB aan JavaScript. Lichtere alternatieven zoals Zoho Desk en Crisp blijven onder de 155 KB. Gemiddeld voegt een chatwidget 300 tot 600 ms aan main thread blocking time toe. Dat is genoeg om een anders voldoende INP score in de "needs improvement" categorie te duwen.

Largest Contentful Paint problemen veroorzaakt door chatwidgets

Een chatwidget kan de Core Web Vitals beïnvloeden wanneer deze concurreert om netwerkbronnen. JavaScript-bestanden worden meestal eerder in de wachtrij geplaatst om te downloaden dan afbeeldingen. Dit betekent dat in het ergste geval (wanneer het chatscript render blocking is) de browser moet wachten tot het chatscript is gedownload en uitgevoerd voordat deze verder kan met iets anders. Een render-blocking chatwidget kan de First Contentful Paint verdubbelen van 1,0 seconde naar meer dan 2,3 seconden.

Zelfs wanneer het chatscript is uitgesteld (deferred), kan het nog steeds de paint metrics op een paar manieren beïnvloeden. Laat me eerst uitleggen wat deferred scripts doen. De browser kan deferred scripts parallel downloaden en de browser kan doorgaan met renderen tot het DOMContentLoaded event. Daarna zal het de scripts uitvoeren. Het probleem is dat voor terugkerende bezoekers het LCP-element waarschijnlijk niet geladen zal zijn op het moment van het DOMContentLoaded event, maar het (gecachete) chatscript zal wel uitvoeren, wat een vertraging in LCP metrics veroorzaakt.

Interaction to Next Paint (INP) problemen veroorzaakt door chatwidgets

Een chatwidget kan en zal de Interaction to Next Paint op 2 manieren beïnvloeden. De eerste manier is door de main thread voor een korte tijd te blokkeren terwijl de chatwidget zijn scripts uitvoert of controleert op updates. Dit is nu eenmaal hoe dingen werken. Alles wat je aan een pagina toevoegt, zal de pagina een beetje vertragen.

De tweede manier waarop het INP-problemen kan veroorzaken, is door slechte code (en geloof me, er zijn een aantal slecht gecodeerde chatwidgets in omloop). Als het om chatwidgets gaat, betekent "populairder" niet "beter gecodeerd". Wanneer slechte code er lang over doet om de presentatie te updaten, krijg je automatisch INP-problemen. Ik neem aan dat sommige chataanbieders een tandje bij moeten zetten. Dit deel heb ik helaas niet in de hand. Als je voor een slecht gecodeerde chatwidget hebt gekozen, is er voor mij geen manier om die code beter te maken.

Layout shift (CLS) problemen veroorzaakt door chatwidgets

Soms veroorzaken chatwidgets een layout shift. Er zijn 3 gebruikelijke verdachten waar ik naar zoek tijdens het controleren op gerelateerde layout shifts door chatwidgets.

  • Layout shifts die elke keer optreden bij het laden van de chat
  • Layout shifts die gebeuren bij een vertraagde "chat open"
  • Layout shifts die optreden wanneer een chatgeschiedenis wordt geladen (terugkerende chatbezoeker)

Hoe los je Core Web Vitals problemen op die worden veroorzaakt door chatscripts

Gelukkig is het vrij eenvoudig om de impact die een chatwidget kan hebben op paint metrics (LCP en FCP) en op sommige delen van de Interaction to Next Paint (INP) te minimaliseren. In mijn inleiding vertelde ik je dat scripts een tijd en plaats hebben. En voor chatscripts is dat niet "direct en ten koste van alles". Ik laad chatscripts graag na het load event, wanneer de pagina niet reageert op user input en ik wil ook graag de preload scanner omzeilen om netwerkconcurrentie te voorkomen.

Dus hoe doen we dat? We gebruiken het load event omdat wanneer het load event is afgevuurd, het LCP-element op de pagina zal zijn getekend (tenzij je het lazy geladen hebt met JavaScript). We gebruiken requestIdleCallback om te wachten op een inactief moment wanneer de browser niet reageert op user input. En we gebruiken JavaScript om het chatscript te injecteren, om ervoor te zorgen dat de preload scanner het script src niet onmiddellijk herkent en een vroege download triggert (en dat is precies wat we willen vermijden). Dit is hetzelfde script deferral patroon dat wordt gebruikt voor YouTube-embeds en Google Maps.

<script>
window.addEventListener('load', function(){
  requestIdleCallback(function(){
    var s = document.createElement('script');
    s.src = 'https://your-chat-widget-url.com/chat.js';
    document.body.appendChild(s);
  })
})
</script>

Merk op dat requestIdleCallback niet wordt ondersteund in Safari. Gebruik een fallback: const idle = window.requestIdleCallback || ((cb) => setTimeout(cb, 1)); en vervang requestIdleCallback met idle in het bovenstaande voorbeeld.

Met dit load event plus requestIdleCallback patroon, daalt de impact van een chatwidget op de Lighthouse-score van 9 tot 16 punten naar 0 tot 1 punt.

Alternatief: op interactie gebaseerd laden

In plaats van de chatwidget automatisch te laden na het load event, kun je wachten totdat de bezoeker daadwerkelijk interactie heeft met de pagina. Luister naar mousemove, scroll, of touchstart en laad het chatscript bij de eerste interactie. Dit garandeert nul impact op alle Core Web Vitals voor bezoekers die nooit scrollen of een interactie aangaan.

<script>
function loadChat() {
  var s = document.createElement('script');
  s.src = 'https://your-chat-widget-url.com/chat.js';
  document.body.appendChild(s);
  ['mousemove','scroll','touchstart'].forEach(function(e){
    document.removeEventListener(e, loadChat);
  });
}
['mousemove','scroll','touchstart'].forEach(function(e){
  document.addEventListener(e, loadChat, {once: true});
});
</script>

Los Cumulative Layout Shift problemen op die worden veroorzaakt door chatwidgets

Chatwidgets veroorzaken meestal een kleine layout shift. Dat hoeft geen enorm probleem te zijn. Maar soms renderen chatwidgets gewoon slecht. Gelukkig kunnen we dat (min of meer) ook oplossen door de slechte weergave te verbergen totdat de widget klaar is met renderen.

Om dit te doen moeten we de documentatie van de chatwidget lezen (er zijn veel verschillende chataanbieders en ze werken allemaal net even anders). Zoek in de documentatie naar callback-functies die worden aangeroepen in verschillende stadia van de chat rendering. Aangezien ik niet weet welke chatwidget je gebruikt, zullen we om het mechanisme te illustreren de chat.ready() functie gebruiken.

Nu kunnen we met wat slimme styling de chat verbergen en weergeven met de CSS opacity eigenschap. Eerst voegen we enkele classes toe om de chatwidget standaard te verbergen (wijzig de selectors zodat ze overeenkomen met je chatwidget). Vervolgens voegen we in de chat.ready() callback "showchat" toe aan de body classlist om de tweede CSS-regel te activeren die de chat weer laat zien.

<style>
/*hide chat widget by default*/
.chatwidget{opacity:0}
/*show chat widget after .showchat body class*/
body.showchat .chatwidget {opacity:1}
</style>

<script>
chat.ready(function(){
  document.documentElement.classList.add('showchat');
})
</script>

Dat is het! Veel succes met het versnellen van je chatwidget. Om je wijzigingen met echte bezoekers te verifiëren, stel je Real User Monitoring in. Lab scores zijn nuttig voor debugging, maar praktijkdata (field data) van echte gebruikers is wat Google gebruikt voor ranking.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

Performance degrades the moment you stop watching.

I set up the monitoring, the budgets, and the processes. That is the difference between a fix and a solution.

Let's talk
Chatwidget met perfecte Core Web VitalsCore Web Vitals Chatwidget met perfecte Core Web Vitals