Le service client a demandé un chat. Le marketing a demandé des avis clients sur les fiches produit. Les commerciaux ont demandé un module de prise de rendez-vous. La qualité a demandé un questionnaire de satisfaction qui s’ouvre au bout de dix secondes. Chacun de ces widgets a été validé séparément, chacun paraissait indolore, et aucun n’a jamais été mesuré. Six mois plus tard, le site a vu ses Core Web Vitals chuter sans qu’une seule ligne de son propre code ait changé.
Un widget de relation client est un morceau d’interface fourni par un tiers, injecté dans vos pages par un script, et qui vit sa propre vie : il charge son application, ses styles, souvent ses polices, parfois une connexion permanente, et il le fait pour tous vos visiteurs, y compris les 95 % qui ne l’ouvriront jamais. Le Web Almanac 2024 relève que le service client est, avec le consentement et la vidéo, l’une des trois catégories de tiers les plus présentes sur le web, et le projet third-party-web précise que ces scripts sont généralement plus lourds que les autres.
Cet article établit ce que coûte réellement chaque famille de widgets, du chat aux avis en passant par les enquêtes et la prise de rendez-vous, pourquoi ce coût reste invisible dans la plupart des outils de mesure, et comment décider lesquels garder, lesquels charger à la demande et lesquels retirer. Vous ne choisirez pas entre avoir un chat et ne pas en avoir. Vous choisirez lequel, et comment le charger. Combien votre pile de widgets vous coûte-t-elle, et laquelle de ses briques pèse le plus ?
Combien coûte vraiment un widget de chat ?
Beaucoup plus que son apparence ne le laisse croire, et de façon très inégale selon l’éditeur. Dans le jeu de données third-party-web consulté le 17 septembre 2026, un chat mesure 33 millisecondes d’impact moyen sur le thread principal quand un autre, à fonctionnalité comparable, en mesure 2 157. Entre deux outils équivalents, le rapport dépasse le facteur soixante.
Le chargeur n’est pas le widget
Le script que vous collez dans le HTML paraît léger parce que ce n’est pas le widget, c’est un chargeur. Quelques kilooctets dont la seule fonction est d’aller chercher l’application réelle, avec ses composants, ses bibliothèques, ses feuilles de style et ses traductions. L’aveu le plus utile vient d’un éditeur lui-même : Intercom a publié en 2019 que son messager, une application React servie en un seul fichier, pesait près de 600 Ko compressés avant optimisation, ramenés à 240 Ko après découpage, et chiffrait le gain à cinq secondes sur une connexion 3G rapide et onze sur une 3G lente.
Le même article décrit une feuille de style de plus de quatre mille règles téléchargée et analysée à chaque visite, y compris quand seul le petit bouton flottant était affiché. L’ingénieur qui a mené ce chantier en tirait une leçon qui vaut pour tous les widgets de cette famille, et qui explique pourquoi la suite de cet article insiste autant sur le chargement à la demande.
Les personnes qui n’interagissent jamais avec le Messenger ne devraient pas avoir à télécharger du code superflu susceptible de ralentir leur expérience du site.
Daniel Husar, ingénieur chez Intercom, dans son article Reducing the Intercom Messenger bundle size by 65%, publié le 8 juillet 2019
Sept ans plus tard, le principe reste l’exception. Intercom précharge désormais son application au survol du bouton plutôt qu’au chargement de la page, mais la plupart des éditeurs chargent encore tout, tout de suite, pour tout le monde. Le chargeur a en outre un effet de bord peu visible : comme il injecte lui-même les fichiers suivants, le navigateur ne peut pas les découvrir à l’avance, et la chaîne de dépendances s’allonge d’un aller-retour à chaque étage.
Ce qu’il faut regarder à la place du poids
Le poids transféré ne dit presque rien du coût réel. Un fichier JavaScript doit être décompressé, analysé, compilé puis exécuté sur le fil unique qui affiche la page et répond aux clics, et c’est ce temps d’exécution qui fige l’interface. Quarante kilooctets de code qui parcourent le DOM, posent des observateurs et calculent des styles peuvent bloquer le thread principal plus longtemps qu’un fichier trois fois plus lourd qui ne fait qu’attendre. Notre guide sur le coût réel d’un script tiers détaille cette mécanique, qui s’applique ici sans exception.
C’est précisément ce que mesure l’indicateur d’impact moyen de third-party-web : le temps d’exécution sur le thread principal attribué à chaque tiers par l’audit de démarrage de Lighthouse, sur environ quatre millions de pages mobiles de l’HTTP Archive. Il ne capte ni les polices, ni le coût de calcul des styles, ni les connexions persistantes, et ces angles morts reviendront plus loin. Mais pour comparer ce que les outils font faire au processeur, c’est la meilleure donnée publique disponible.
Le contexte, des widgets partout
Le Web Almanac 2024 classait les fournisseurs de consentement, la vidéo et le service client comme les trois catégories de tiers les plus présentes sur le web, avec pour représentant le plus fréquent du service client le domaine embed.tawk.to. L’édition 2025 ajoute que plus de 90 % des pages embarquent au moins un tiers, pour une médiane de 79 requêtes tierces par page mobile, en hausse. Le bandeau cookies et la vidéo ont déjà leur guide sur ce blog, pour bien choisir sa CMP et intégrer une vidéo sans ralentir son site.
Le troisième pilier manquait, et il ne se traite pas comme les deux autres : un bandeau de consentement se retire une fois répondu, une vidéo ne se charge que sur les pages qui en ont une, alors qu’un chat est présent sur toutes les pages, pour toutes les visites. Il commence par une idée reçue à démonter.
Pourquoi l’iframe ne vous protège de rien
Beaucoup de widgets de chat s’affichent dans une iframe, et beaucoup d’équipes en déduisent que leur coût reste enfermé dedans. C’est l’idée reçue la plus tenace du sujet. Une iframe isole un contexte de sécurité, pas une expérience utilisateur : les interactions qui s’y produisent entrent dans l’INP du document, et le décalage visuel qu’elle provoque, invisible pour vos outils, reste visible pour l’utilisateur et compté par Google.
Ce que l’on croit qu’une iframe fait
La croyance mérite d’être posée honnêtement, parce qu’elle est à moitié vraie. Une iframe est un document séparé, avec son propre contexte de navigation, ses propres scripts et, dans Chrome, souvent son propre processus. Un bug dans le widget ne peut pas lire vos cookies, et une erreur JavaScript dans la fenêtre de chat ne casse pas votre tunnel de commande. Tout cela est exact, et c’est une isolation de sécurité, pas une isolation de performance perçue. Le visiteur, lui, ne voit qu’une seule page.
L’INP compte ce qui se passe dans les iframes
La documentation de l’Interaction to Next Paint est explicite : les interactions surviennent dans le document principal ou dans les iframes qu’il contient, l’utilisateur ne sait pas ce qui est dans une iframe et ce qui n’y est pas, et l’INP mesuré dans les iframes est donc nécessaire pour refléter l’expérience de la page de premier niveau. Un clic laborieux dans la fenêtre de chat est une interaction lente de votre page, au même titre qu’un clic sur votre bouton d’ajout au panier.
Le seuil de la métrique est de 200 ms au 75e centile, et c’est la pire interaction de la visite qui est retenue, pas la moyenne. Une seule ouverture de chat à 600 ms suffit donc à classer toute la page en mauvaise responsivité. Notre guide sur l’INP et comment l’optimiser explique pourquoi un seul mauvais clic suffit à dégrader la note.
Le CLS des iframes est invisible à vos outils, pas à Google
Le point le plus fort de cet article tient dans une page de web.dev consacrée aux écarts entre CrUX et le RUM. Pour des raisons de sécurité, une page n’a pas accès au contenu de ses iframes, même de même origine. Les métriques de ce contenu ne peuvent être mesurées que par l’iframe elle-même, jamais par les API de la page qui l’héberge.
La suite est écrite noir sur blanc : si l’iframe contient l’élément LCP, ou un contenu qui affecte le CLS ou l’INP vécus par l’utilisateur, votre solution de RUM ne le verra pas, bibliothèque web-vitals de Google comprise. CrUX, mesuré par le navigateur lui-même, n’a pas cette limite et compte ce qui se passe dans les iframes.
La conséquence opérationnelle est déroutante pour qui ne la connaît pas : votre tableau de bord RUM est vert, votre Search Console est rouge, et les deux ont raison. Ils ne mesurent pas le même périmètre. Une fenêtre de chat qui se déplie dans son iframe et pousse le contenu, un bandeau d’avis dont les étoiles arrivent après coup dans leur cadre, produisent un décalage compté dans les Core Web Vitals et absent de vos courbes. Notre guide sur le CLS et comment l’optimiser pose les bases ; le schéma ci-dessous résume ce que l’iframe laisse passer.
L’isolation a elle-même un coût
Même quand son contenu est léger, l’iframe n’est pas neutre. La documentation de Site Isolation de Chromium indique que l’isolation des sites dans des processus séparés coûte environ 10 à 13 % de mémoire supplémentaire sur desktop, et surtout que la mise en page de la page entière n’est plus synchrone, puisque ses cadres peuvent être répartis sur plusieurs processus. Une iframe tierce ajoute donc un processus, une communication inter-processus à chaque redimensionnement, et un rendu qui n’est plus coordonné avec celui de votre page. Sur un mobile d’entrée de gamme, ce n’est pas un détail.
Ce qui ne marche pas non plus
Trois fausses solutions circulent, et il y a de grandes chances que vous les ayez déjà lues ailleurs. L’attribut sandbox est un mécanisme de sécurité qui restreint ce que le document embarqué a le droit de faire ; le widget télécharge et exécute exactement le même code. L’attribut fetchpriority n’existe pas sur <iframe>, il ne s’applique qu’aux images, aux scripts et aux préchargements. Les deux attributs sont donc sans effet sur le coût du widget.
Quant à loading="lazy" sur une iframe, il est plus récent qu’on ne le croit : Firefox ne l’a pris en charge que fin 2023, dans sa version 121, le 19 décembre 2023, Safari depuis la 16.4 selon caniuse, avec cette réserve rarement lue de la documentation MDN : le report n’est appliqué que si JavaScript est activé, par mesure anti-pistage.
Ce dernier attribut reste utile pour une iframe placée sous la ligne de flottaison, un calendrier de réservation en bas de page par exemple. Il ne sert à rien pour un widget de chat, dont l’iframe est positionnée en fixe dans la fenêtre, donc toujours visible, donc jamais différée. Reste alors la question que tout le monde pose en premier : lequel choisir.
Quel widget de chat choisir ?
Celui dont le coût d’exécution est le plus faible, avant toute considération de fonctionnalités, parce qu’aucun réglage de chargement ne rattrape un facteur soixante. Le jeu de données third-party-web du 17 septembre 2026 étage les principaux outils de 33 ms pour Crisp à 3 089 ms pour Freshchat, avec une réserve de méthode : les bases d’observation vont de 1 577 à 176 551 pages.
Le tableau
Le tableau compare les outils de chat les plus répandus sur leur impact moyen, c’est-à-dire le temps d’exécution JavaScript sur le thread principal par page, tel que third-party-web l’agrège depuis les audits Lighthouse mobiles de l’HTTP Archive, avec le nombre de pages sur lesquelles chaque outil a été observé. La troisième colonne est aussi importante que la deuxième : elle dit avec quelle confiance lire chaque ligne.
| Outil de chat | Impact moyen | Pages observées | Catégorie third-party-web |
|---|---|---|---|
| Crisp | 33 ms | 1 577 | Customer Success |
| Tawk.to | 440 ms | 176 551 | Customer Success |
| Smartsupp | 647 ms | 35 566 | Customer Success |
| LiveChat | 1 116 ms | 62 860 | Customer Success |
| HubSpot | 1 226 ms | 313 527 | Marketing |
| Intercom | 1 433 ms | 58 316 | Customer Success |
| Zendesk | 2 157 ms | 111 484 | Customer Success |
| Freshchat | 3 089 ms | 11 972 | Customer Success |
| Drift | 4 394 ms | 4 339 | Marketing |
Deux précautions de lecture s’imposent. D’abord, un outil relevé sur 1 577 pages et un autre sur plus de 111 000 ne se comparent pas avec la même confiance : un facteur soixante reste significatif, mais il ne se lit pas comme un classement sportif, et l’excellent résultat de Crisp ne doit jamais être cité sans son nombre de pages. Ensuite, HubSpot et Drift sont rangés en Marketing parce que leur script porte bien plus qu’un chat : leur impact inclut formulaires, suivi et personnalisation, ce qui explique en partie leur position.
Ce que le tableau veut dire pour vous
Le message central de cet article tient en une phrase, et elle est inconfortable pour une agence d’optimisation : sur cette famille d’outils, le choix de l’éditeur pèse plus lourd que toutes les micro-optimisations que vous pourrez faire ensuite. Différer un script de 2 000 ms d’exécution ne le rend pas moins coûteux, il déplace le coût vers le moment où le visiteur interagit, c’est-à-dire exactement là où l’INP se mesure. La décision la plus rentable se prend avant la signature du contrat, pas après l’intégration.
Le graphique rend l’écart d’échelle plus lisible que le tableau, et fait apparaître une chose que les chiffres bruts cachent : l’outil le plus répandu du marché, Tawk.to, présent sur plus de 176 000 pages, se situe dans le tiers léger. Le volume d’adoption ne suit donc pas le coût, et rien n’oblige à payer cher pour un chat courant. Cette lecture appelle trois questions à poser à l’éditeur, qui ne figurent dans aucun tableau.
Les critères qui ne figurent pas dans le tableau
Le widget peut-il être chargé à la demande, c’est-à-dire expose-t-il une API pour n’appeler son script qu’au premier clic sur un bouton que vous contrôlez ? Propose-t-il un mode sans iframe, ou au contraire une iframe dont les dimensions sont connues à l’avance ? Réserve-t-il son espace dans la page avant d’arriver, ou pousse-t-il le contenu quand il s’affiche ? Un éditeur qui répond oui aux trois vous laisse la maîtrise du coût ; un éditeur qui répond non vous impose le sien.
Ces trois réponses valent d’être obtenues par écrit avant la signature, parce qu’elles conditionnent tout ce qui pourra être fait ensuite : sans API de chargement, pas de façade possible. Nos propres relevés, plus loin, montrent que le classement public ne dit pas tout, mais il reste à faire le tour des autres familles de widgets.
Les avis clients, les enquêtes et la prise de rendez-vous
Le chat n’est que la partie la plus visible de la pile. Les widgets d’avis, les questionnaires, les fenêtres d’intention de sortie et les modules de rendez-vous obéissent à la même mécanique, avec chacun une spécificité qui le rend soit plus sage, soit plus dangereux que le chat. Le jeu de données du 17 septembre 2026 donne, pour les widgets d’avis les plus répandus, des impacts moyens globalement plus modérés, dans cet ordre :
- Trustpilot, 295 ms sur 74 130 pages ;
- Avis Vérifiés, répertorié sous le nom de son éditeur Net Reviews, 326 ms sur 1 984 pages ;
- Trusted Shops, 430 ms sur 33 129 pages ;
- Yotpo, 668 ms sur 48 498 pages ;
- Judge.me, 1 021 ms sur 37 537 pages.
La famille est plus sage que le chat, mais elle a un piège spécifique. Ces widgets sont posés en page d’accueil et en fiche produit, donc exactement là où se joue le LCP, et leur contenu arrive après coup, donc exactement quand se produit le CLS. Un bloc d’étoiles qui se matérialise sous le titre d’une fiche produit décale le prix, le bouton d’achat et la photo, les trois éléments que le visiteur regarde. Notre guide sur le LCP et comment l’optimiser rappelle que tout ce qui s’insère au-dessus de l’image principale retarde ou déplace sa peinture.
La surprise, la prise de rendez-vous
Calendly mesure 4 305 ms d’impact moyen sur 13 872 pages dans le même jeu de données, soit davantage que la quasi-totalité des outils de chat du tableau précédent. C’est le widget que personne ne soupçonne, parce qu’il est perçu comme un simple calendrier, et qu’il est souvent posé par un commercial dans un bloc HTML sans passer par l’équipe technique. Un calendrier embarqué est en réalité une application complète dans une iframe, avec sa gestion des fuseaux, ses disponibilités chargées depuis une API et son propre framework.
Le charger sur une page produit pour un bouton que 2 % des visiteurs utiliseront est l’erreur la plus coûteuse de cette famille.
Les enquêtes et les popups
Un popup qui s’affiche après cinq secondes compte-t-il dans le CLS ? Oui, intégralement. La documentation du Cumulative Layout Shift ne prévoit d’exonération que pour les décalages survenant dans les 500 ms qui suivent une interaction discrète, un tap, un clic ou une frappe. Un déclenchement par minuteur, par profondeur de défilement ou par intention de sortie n’ouvre droit à rien, puisque le mouvement de souris et le défilement ne sont pas des interactions discrètes.
Les exemples ne manquent pas. Un questionnaire de satisfaction qui surgit au bout de dix secondes, une invitation à la newsletter aux deux tiers de la page, une fenêtre de sortie qui se déclenche quand le curseur quitte l’onglet, produisent tous un décalage comptabilisé sans aucune exonération.
Le détail qui montre la maîtrise du sujet est plus fin encore. Même un widget ouvert par un clic produit un décalage comptabilisé si son contenu met plus de 500 ms à arriver, puisque l’exonération expire. Un bouton qui ouvre une fenêtre vide, laquelle se remplit une seconde plus tard en poussant ce qui l’entoure, est un décalage inattendu au sens de la métrique. La parade consiste à réserver l’espace immédiatement, dans les 500 ms, quitte à afficher un squelette, et à laisser le contenu arriver ensuite sans rien déplacer.
Un cas trivial qui illustre tout
Les boutons de partage social sont la version miniature de tout ce qui précède. Dans le jeu de données du 17 septembre 2026, AddToAny mesure 141 ms d’impact moyen et ShareThis 360 ms, pour une fonction que trois liens HTML remplissent à coût nul, sans script, sans cookie et sans connexion tierce. Le bloc ci-dessous est le plus immédiatement copiable de l’article : chaque réseau expose une URL de partage officielle, il suffit de la construire.
<!-- Partage sans script : trois liens, zero tiers, zero cookie -->
<ul class="partage">
<li><a href="https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.exemple.fr%2Farticle%2F"
rel="noopener" target="_blank">Partager sur LinkedIn</a></li>
<li><a href="https://x.com/intent/post?url=https%3A%2F%2Fwww.exemple.fr%2Farticle%2F&text=Titre%20de%20l%27article"
rel="noopener" target="_blank">Partager sur X</a></li>
<li><a href="mailto:?subject=Titre%20de%20l%27article&body=https%3A%2F%2Fwww.exemple.fr%2Farticle%2F">Envoyer par e-mail</a></li>
</ul>
<!-- Sur mobile, l'API native fait mieux que n'importe quel widget -->
<script>
if (navigator.share) {
document.querySelector('.partage').insertAdjacentHTML('beforeend',
'<li><button type="button" id="share-native">Partager</button></li>');
document.getElementById('share-native').addEventListener('click', function () {
navigator.share({ title: document.title, url: location.href });
});
}
</script>
Ce cas est trivial, et c’est pour cela qu’il est instructif : personne ne défendrait 360 ms de thread principal pour trois liens. Le même raisonnement, appliqué à un chat ou à un widget d’avis, se heurte à un seul obstacle, l’absence de mesure. C’est ce que nos audits apportent au classement public, et ils ne le confirment qu’en partie.
Votre site est-il aussi rapide que vos visiteurs l’espèrent ?
Ce que nos relevés ajoutent au classement
Les constats qui suivent viennent de nos audits et de nos interventions d’optimisation, sur des sites de secteurs variés, anonymisés par typologie. Ils ne remplacent pas le tableau précédent, ils le complètent sur ce qu’il ne mesure pas : les polices, le coût de rendu, les connexions persistantes et tout ce qu’un widget charge pour une fenêtre que personne n’ouvre. Chacun est reproductible sur votre site avec les manipulations données plus loin.
L’impact moyen ne mesure ni les polices ni le coût de rendu
Un outil de chat qui figure parmi les plus légers du classement public a été relevé en audit, sur un site de services à la personne, à près de 250 Ko de ressources, dont quatre fichiers de police Noto Sans chargés en priorité haute, et plus d’un millier de sélecteurs CSS injectés dans la page, responsables de temps de calcul de style excessifs à chaque interaction. Sur un autre site, le même outil dépassait 125 Ko et maintenait une connexion WebSocket ouverte en permanence.
L’indicateur public mesure du temps d’exécution JavaScript : il ignore les polices, les styles et les connexions, et un outil peut être exemplaire sur l’un et coûteux sur les trois autres.
La conséquence mérite d’être écrite noir sur blanc, parce qu’elle est rare dans un article qui vient de publier un tableau : le tableau est un point de départ, pas un verdict. Il désigne les outils à écarter d’emblée, ceux dont l’exécution seule dépasse la seconde. Il ne suffit pas à départager les outils légers entre eux, et c’est là que la mesure sur votre propre site devient indispensable.
Le widget qui charge ses propres polices
Le constat est transversal à cette famille d’outils et presque jamais traité. Un outil de voix du client a été relevé à 166 Ko de JavaScript répartis en seize fichiers, plus 74 Ko de polices en deux fichiers TTF, chargés sur toutes les pages d’un site e-commerce de mobilier. Un autre chat chargeait deux fois la même police de 27,7 Ko, servie depuis deux centres de données différents du même réseau de diffusion, parce que deux de ses composants la déclaraient séparément.
Le format TTF, non compressé pour le web là où WOFF2 divise le poids par deux ou trois, mérite d’être relevé au passage : un widget qui embarque du TTF n’a pas été audité par son propre éditeur.
La recommandation maison est simple et presque toujours acceptée par les éditeurs quand on la leur demande : faire hériter le widget de la police du site, par une option de configuration ou par une règle CSS sur son conteneur, plutôt que de le laisser charger la sienne. Le gain est double, quelques dizaines de kilooctets et une requête de moins sur le chemin critique, et une cohérence visuelle que le marketing réclamait de toute façon. Notre article sur les polices et la performance détaille ce que coûte chaque fichier de police supplémentaire.
Le paradoxe de calendrier des widgets d’avis
Sur un site e-commerce de cosmétiques, le widget d’un agrégateur d’avis pesait plus de 100 Ko à télécharger et 360 Ko une fois décompressé, et il arrivait à la fois trop tôt et trop tard. Trop tôt pour les blocs situés en bas de page, hors de la fenêtre initiale, qu’il chargeait et rendait inutilement au chargement.
Trop tard pour les étoiles affichées sous le titre de la fiche produit, qui apparaissaient après coup et produisaient un décalage sur l’élément le plus regardé de la page. Le même script était en avance et en retard, parce qu’il traitait tous ses emplacements de la même façon.
La correction appliquée a tenu en deux gestes, et elle est reprise dans le bloc de réservation d’espace plus loin : chargement asynchrone du script, et réservation de hauteur par min-height sur le conteneur d’origine et sur le conteneur final, les deux étant distincts parce que le widget remplace son point d’ancrage par un élément qu’il crée lui-même. Réserver l’un sans l’autre laisse subsister un décalage au moment de la substitution, et c’est l’erreur la plus fréquente sur ces widgets.
Le widget de réassurance qu’une partie des visiteurs ne voit jamais
Un widget d’avis largement répandu repose sur un script tiers servi depuis un domaine que les listes de blocage publicitaire connaissent bien, ce qui lui vaut d’être bloqué par les bloqueurs de publicité. Sur un site de services à la personne, l’audit a relevé que ce script ne se chargeait pas pour une part importante des visiteurs équipés. On paie donc une latence de connexion tierce et un coût d’exécution pour un élément de réassurance qu’une partie du public ne verra pas, précisément la partie la plus méfiante, celle que la réassurance visait.
Corollaire savoureux relevé dans le même audit : des photos de profil servies depuis une URL contenant le segment /adverts/ étaient bloquées pour la même raison, à cause d’un simple nom de répertoire.
La recommandation maison déplace le débat de la performance vers l’efficacité : remplacer le widget par une image SVG ou PNG de la note et du nombre d’avis, régénérée périodiquement côté serveur depuis l’API de l’éditeur, avec un lien vers la page d’avis complète. Zéro script, zéro connexion tierce, visible par tout le monde, et une image de quelques kilooctets qui ne décale rien puisque ses dimensions sont connues.
La prise de rendez-vous en synchrone
Sur un site B2B de solutions techniques, le module de prise de rendez-vous était intégré par une feuille de style et un script synchrones sur les pages produit, exactement comme le proposait l’extrait fourni par l’éditeur. Le résultat était un goulot d’étranglement qui bloquait l’affichage de la page tant que le domaine tiers n’avait pas répondu. Le simple passage des deux ressources en asynchrone a produit un gain net sur le LCP, sans toucher au widget lui-même.
À rapprocher du chiffre de Calendly plus haut : c’est le widget que personne ne soupçonne, et il est souvent le plus mal intégré.
Ce qu’on charge pour une fenêtre que personne n’ouvre
Trois constats courts, que tout lecteur peut vérifier sur son site en dix minutes dans l’onglet Réseau. Les drapeaux d’une fenêtre de changement de langue, téléchargés alors que la fenêtre est masquée. L’avatar d’une fenêtre de chatbot, chargé alors que la fenêtre est fermée par défaut. Un second service anti-robot chargé sur toutes les pages pour un formulaire de connexion, alors qu’il pouvait être conditionné à l’ouverture de la fenêtre d’inscription, pour ne pas pénaliser 100 % des utilisateurs pour une fonctionnalité qui n’en concerne qu’une fraction.
Dans les trois cas, le coût est payé par tous pour l’usage de quelques-uns, et c’est le motif le plus répandu de toute cette famille.
Le trou de mesure que personne ne voit
Reprenons le fil de la deuxième partie, parce qu’il explique une situation que beaucoup d’équipes vivent sans la comprendre. Un widget lent dans une iframe dégrade l’INP et le CLS mesurés par CrUX, donc les Core Web Vitals, donc ce que voit la Search Console. Il n’apparaît jamais dans un RUM maison bâti sur les API du navigateur, puisque ces API n’ont pas accès au contenu des iframes. Les deux mesures sont exactes, elles ne couvrent pas le même périmètre, et seule celle de Google compte pour le référencement.
La mise en garde symétrique s’impose par honnêteté. Cela ne veut pas dire que le RUM ment, ni qu’il faut l’abandonner : il voit tous les navigateurs là où CrUX ne voit que Chrome, il segmente par page et par parcours là où CrUX agrège sur 28 jours, et il attribue une interaction lente à un élément précis. Il faut simplement savoir laquelle des deux sources répond à quelle question.
Notre comparatif PageSpeed Insights vs. Lighthouse et notre article sur comment se mesure la web performance posent ce cadre ; pour les widgets en iframe, la question du CLS et de l’INP se pose à CrUX, et à lui seul.
Une conséquence pratique en découle pour les éditeurs de widgets eux-mêmes. La documentation de l’INP indique que les sous-cadres peuvent rapporter leurs entrées de mesure au document parent. Un éditeur soucieux de ses clients exposerait donc les métriques de son iframe par postMessage, pour qu’un RUM puisse les intégrer. À notre connaissance, presque aucun ne le fait, et c’est une question à poser lors du choix.
Comment intégrer ces widgets sans ralentir son site ?
En mesurant chaque widget séparément, en ne chargeant à l’arrivée que ce qui est immédiatement utile, et en réservant l’espace de tout ce qui arrive après coup. La technique de la façade, un bouton statique qui charge le widget réel au premier clic, reste la plus efficace, mais Lighthouse a retiré l’audit qui la recommandait le 10 octobre 2025, et aucun éditeur ne la propose nativement.
Mesurer d’abord, un widget à la fois
La méthode tient en vingt minutes et vaut tous les arbitrages d’opinion entre équipes. Bloquer le domaine d’un widget dans le navigateur, recharger la page, relever l’écart sur le LCP et le Total Blocking Time, puis recommencer pour le widget suivant. Il faut mesurer un widget à la fois et non tous ensemble, parce que les coûts ne s’additionnent pas linéairement quand plusieurs scripts se disputent le thread principal, et mesurer sur une page représentative, fiche produit ou article, pas seulement sur la page d’accueil, où les widgets ne sont pas tous présents.
# Dans Chrome DevTools : onglet Network, clic droit sur une requete du widget,
# "Block request domain", puis rechargement avec l'onglet Performance ouvert.
# En ligne de commande, pour un releve reproductible :
lighthouse https://www.exemple.fr/produit/exemple/ --preset=desktop \
--output=json --output-path=./avec-widget.json
lighthouse https://www.exemple.fr/produit/exemple/ --preset=desktop \
--output=json --output-path=./sans-widget.json \
--blocked-url-patterns="*client.crisp.chat*" "*embed.tawk.to*" "*widget.trustpilot.com*"
# Ecart LCP et TBT entre les deux rapports
jq '.audits["largest-contentful-paint"].numericValue, .audits["total-blocking-time"].numericValue' \
avec-widget.json sans-widget.json
Le résultat est un classement chiffré de vos widgets, du plus coûteux au moins coûteux, sur vos pages et avec votre configuration. Il ne dit pas encore ce que vous coûte l’INP en iframe, que seul le terrain révèle, mais il suffit dans la plupart des cas à désigner le widget à traiter en premier. Vient ensuite le choix du traitement, et le plus efficace s’appelle la façade.
La façade, ce qu’elle apporte et ce qu’elle coûte
Faut-il charger son chat seulement au clic ? C’est la bonne approche. Le principe consiste à afficher un faux bouton statique, aux dimensions et aux couleurs du widget réel, et à ne charger le script de l’éditeur qu’au premier clic, en remplaçant le bouton par le vrai. Pour les 95 % de visiteurs qui n’ouvrent jamais le chat, le coût tombe à celui d’un bouton HTML. Le bloc suivant en donne une version générique, qui prévoit le cas du clic pendant le chargement, sans quoi le visiteur clique dans le vide pendant une seconde.
<!-- 1. Le bouton statique : memes dimensions, meme position que le widget reel -->
<button type="button" id="chat-facade" class="chat-facade"
aria-label="Ouvrir le chat">
<svg width="28" height="28" viewBox="0 0 24 24" aria-hidden="true">
<path fill="currentColor" d="M4 4h16v11H7l-3 3z"/>
</svg>
</button>
<style>
.chat-facade { position: fixed; right: 20px; bottom: 20px; width: 60px; height: 60px;
border: 0; border-radius: 50%; background: #2E69E8; color: #fff; cursor: pointer; }
.chat-facade[aria-busy="true"] { opacity: .6; cursor: progress; }
</style>
<script>
(function () {
var btn = document.getElementById('chat-facade');
var loading = false, wantOpen = false;
function loadWidget() {
if (loading) { wantOpen = true; return; } // 3. clic pendant le chargement : on retient l'intention
loading = true;
btn.setAttribute('aria-busy', 'true');
var s = document.createElement('script');
s.src = 'https://widget.exemple-editeur.com/loader.js'; // 2. le script reel, seulement maintenant
s.async = true;
s.onload = function () {
btn.remove(); // 4. le vrai widget remplace la facade
if (window.WidgetApi && window.WidgetApi.open) { window.WidgetApi.open(); }
};
s.onerror = function () { btn.removeAttribute('aria-busy'); loading = false; };
document.head.appendChild(s);
}
btn.addEventListener('click', loadWidget);
// Optionnel : prechauffer la connexion au survol, sans encore charger
btn.addEventListener('pointerenter', function () {
var l = document.createElement('link');
l.rel = 'preconnect'; l.href = 'https://widget.exemple-editeur.com';
document.head.appendChild(l);
}, { once: true });
})();
</script>
Deux mises en garde honnêtes accompagnent cette technique. D’abord, aucun éditeur du marché ne la propose nativement : c’est toujours du développement spécifique, l’appel d’ouverture après chargement dépend de l’API de chaque outil, et la façade doit être tenue à jour quand l’éditeur change son bouton. Ensuite, la recommandation officielle n’existe plus : l’audit Lighthouse qui la promouvait a été supprimé dans Lighthouse 13, le 10 octobre 2025, l’équipe Chrome expliquant qu’elle préférait voir les tiers améliorer leurs produits plutôt que de les contourner. La technique reste bonne, la caution de Google, elle, a disparu, et il faut l’écrire soi-même.
Réserver l’espace, toujours
Le geste le moins coûteux et le plus rentable consiste à définir la position et les dimensions du widget avant son arrivée. Pour un chat en position fixe, c’est presque gratuit, puisqu’il ne participe pas au flux. Pour un widget d’avis inséré dans le contenu, il faut réserver la hauteur du conteneur d’origine et, comme le cas des cosmétiques l’a montré, celle du conteneur que le widget crée à sa place :
/* Chat en position fixe : hors du flux, il ne decale rien s'il garde ses dimensions */
.chat-facade, #widget-chat-container { position: fixed; right: 20px; bottom: 20px;
width: 60px; height: 60px; }
/* Widget d'avis dans le flux : reserver la hauteur AVANT l'arrivee du script */
.avis-ancre { min-height: 28px; } /* le point d'ancrage d'origine */
.avis-ancre .avis-widget-genere { min-height: 28px; } /* le conteneur cree par le widget */
/* Bloc d'avis complet en bas de fiche produit : squelette a la bonne hauteur */
.avis-liste { min-height: 480px; }
.avis-liste:empty { background: linear-gradient(#f3f4f6, #f3f4f6) center / 100% 1px no-repeat; }
/* Contenu isole : le navigateur ne recalcule pas le reste de la page quand le widget change */
.avis-liste, #widget-chat-container { contain: layout paint; }
La propriété contain mérite une ligne d’explication : elle indique au navigateur que ce qui se passe à l’intérieur du conteneur n’affecte pas la mise en page de l’extérieur, ce qui évite qu’un widget qui se redessine dix fois par seconde déclenche dix recalculs de la page entière. Elle ne dispense pas de réserver la hauteur, elle rend la réservation efficace.
Ce qu’il ne faut pas faire
Deux réflexes bien intentionnés aggravent le problème. Le premier consiste à préconnecter tous les domaines tiers dans le <head>. La documentation de preconnect sur web.dev prévient qu’un préchargement de connexion inutile retarde d’autres ressources importantes, que le navigateur ferme toute connexion non utilisée au bout de dix secondes, et qu’une connexion ouverte sans l’attribut crossorigin ne sert pas aux requêtes qui en ont besoin, comme les polices. Lighthouse 13 a d’ailleurs retiré son audit de préchargement pour risque de sur-recommandation. Un widget chargé à la demande n’a besoin d’aucune préconnexion au chargement.
Le second réflexe consiste à charger le widget au premier défilement, ce que proposent plusieurs extensions d’optimisation. Cela retire le script du chargement initial, ce qui améliore le LCP et le TBT en laboratoire, mais cela déplace le pic d’exécution exactement là où l’INP se mesure, au moment où le visiteur commence à interagir. Un script de 2 000 ms exécuté pendant que le visiteur tape dans un champ de recherche produit une interaction lente garantie. Le chargement au clic n’a pas ce défaut, parce que le visiteur attend explicitement quelque chose.
Fermer proprement ce qui reste ouvert
Un chat audité maintenait une connexion WebSocket ouverte en permanence, y compris quand l’onglet passait en arrière-plan, ce qui coûte de la batterie sur mobile et empêche parfois la page d’entrer dans le cache de navigation avant-arrière. Quand l’API de l’éditeur expose la connexion, ou quand vous en contrôlez une vous-même, la correction tient en quelques lignes, et le geste signe un praticien :
// Fermer la connexion persistante quand la page est cachee ou quittee
addEventListener('pagehide', function () {
if (window.WidgetApi && typeof window.WidgetApi.disconnect === 'function') {
window.WidgetApi.disconnect(); // API editeur, quand elle existe
}
});
// Et la rouvrir seulement si le visiteur revient ET rouvre la fenetre
addEventListener('pageshow', function (e) {
if (e.persisted) { /* page restauree depuis le bfcache : rien a faire tant que le chat est ferme */ }
});
Inventorier et supprimer
Le dernier geste est de gouvernance, pas de technique. Lister les domaines appelés par une page représentative prend dix minutes dans l’onglet Réseau, et sur un site de plus de trois ans, une part significative des scripts tiers n’intéresse plus personne : un widget d’enquête posé pour une étude terminée, un chat d’un prestataire qui n’est plus sous contrat, un module de rendez-vous pour une offre retirée du catalogue. Ces coûts survivent aux projets qui les ont justifiés, faute de date de retrait.
Une seule règle empêche la pile de repousser : inscrire une date de fin pour chaque widget posé, au moment où il est posé. Reste une famille toute neuve, qui ne rentre dans aucune des cases précédentes.
Et les chatbots à base d’IA ?
Tout dépend de l’endroit où tourne le modèle. Un assistant dont l’intelligence est côté serveur n’est qu’un widget de chat de plus, avec les coûts habituels et une latence de réponse en sus. Un modèle exécuté dans le navigateur change d’ordre de grandeur : web.dev rappelle qu’un petit modèle génératif comme Gemma 2B atteint 1,3 Go, soit plus de cent fois le poids de la page médiane du web.
Deux architectures, deux coûts très différents
La distinction gouverne tout le reste. Dans le premier cas, l’assistant conversationnel est un widget de chat dont les réponses viennent d’une API : tout ce qui précède s’applique, façade comprise, et le seul coût nouveau est le temps de génération, qui se vit comme une attente et non comme un blocage.
Dans le second cas, le modèle est téléchargé et exécuté sur la machine du visiteur. Le guide de web.dev sur la performance de l’IA côté client donne les repères : 5 Mo est déjà une taille conséquente pour une ressource web, un modèle de vision utile pèse 13 Mo, DistilBERT 67 Mo, et les petits modèles génératifs dépassent le gigaoctet.
Les bonnes pratiques documentées
Le même guide fixe la conduite à tenir, et elle est cohérente avec tout ce que cet article recommande pour les widgets classiques. Ne télécharger le modèle qu’une fois l’intention d’usage avérée, par exemple quand le visiteur commence à taper. Le mettre en cache explicitement par la Cache API plutôt que de compter sur le cache HTTP. Découper le téléchargement en morceaux avec un indicateur de progression, et déplacer la préparation du modèle comme l’inférence dans un web worker pour ne pas bloquer le thread principal.
Vérifier enfin les capacités de la machine avant de décider. La question à se poser n’est pas comment différer le modèle, mais quelle taille de modèle le service justifie.
Le décalage propre au streaming
Un point concret, rarement traité, et directement actionnable. Une réponse d’assistant qui s’écrit mot à mot dans une fenêtre qui grandit produit un décalage à chaque ligne ajoutée si le conteneur n’a pas de hauteur réservée, et ce décalage survient bien après les 500 ms d’exonération du clic qui a envoyé la question.
La parade est la même que pour un widget d’avis : un conteneur de réponse à hauteur fixe ou minimale, un défilement interne plutôt qu’une croissance, et un contenu qui s’ajoute vers le bas sans rien pousser. Ce qui vaut pour l’assistant de demain vaut pour la pile d’aujourd’hui, et c’est par elle qu’il faut commencer.
Que faire concrètement de sa pile de widgets ?
Trois décisions, dans cet ordre. Choisir l’éditeur en regardant son coût d’exécution avant ses fonctionnalités, parce qu’un facteur soixante ne se rattrape pas. Charger à la demande ce qui n’est pas immédiatement utile, façade pour le chat, image statique pour la réassurance, iframe différée pour le calendrier. Inscrire une date de retrait pour chaque widget posé. La première décision domine les deux autres, et c’est la seule qui ne coûte rien en développement.
Le constat maison qui ferme cet article est celui que nous faisons à chaque audit de suivi : un site optimisé se dégrade seul. Il ne faut pas une refonte pour perdre ses Core Web Vitals, il suffit de six mois de widgets empilés, chacun validé par une équipe différente, chacun indolore à l’unité, pour ramener un site rapide à son point de départ. Notre article sur le coût d’un site rapide le dit autrement : la performance n’est pas un état, c’est une gouvernance qui survit aux projets.
Deux familles d’outils manquent volontairement à cet inventaire, les heatmaps et l’enregistrement de session, dont le coût est d’une autre nature, observation continue du DOM et sérialisation, et qui feront l’objet d’un article distinct.
Pour le reste, chiffrer ce que coûte chaque widget, le rapporter à ce qu’il rapporte et décider avec les équipes qui l’ont demandé plutôt que contre elles, c’est ce que produit un audit de performance web ; remplacer, différer ou reconfigurer ceux qui restent relève ensuite d’une optimisation de performance, et le monitoring est ce qui empêche la pile de repousser. Le widget le plus rapide reste celui que personne n’a demandé, et il mérite qu’on se pose la question à chaque fois.