Un benchmark n’a de sens que s’il mesure la même chose que ce qu’utiliseront les gens. Si le logiciel testé sait qu’il est en train d’être mesuré et change de comportement, le résultat ne décrit plus le site : il décrit le site en conditions d’examen. C’est ce qui se passe sur de nombreux sites WordPress qui utilisent LiteSpeed Cache lorsque la fonction Guest Optimization est activée, et on peut le prouver en lisant le code source du plugin.
Deux tests, deux sites différents
Le point de départ est un site WordPress sur LiteSpeed Web Server avec LiteSpeed Cache (LSCache), testé avec le profil mobile de Lighthouse : un Moto G Power émulé sur une connexion 4G lente, un banc d’essai volontairement sévère. Sur PageSpeed Insights, la page obtient un score parfait.

La même page, analysée quelques instants plus tard avec Lighthouse directement depuis Chrome DevTools et le même profil mobile, raconte une autre histoire.

| Métrique (mobile) | PageSpeed Insights | Lighthouse dans Chrome |
|---|---|---|
| Performances | 100 | 77 |
| First Contentful Paint | 1,1 s | 3,0 s |
| Largest Contentful Paint | 1,3 s | 4,5 s |
| Total Blocking Time | 0 ms | 170 ms |
| Speed Index | 1,1 s | 3,0 s |
| Cumulative Layout Shift | 0 | 0 |
Deux exécutions de Lighthouse ne donnent jamais le même chiffre : le CPU, la version du navigateur et le throttling introduisent toujours une certaine variabilité. Mais une variabilité de quelques points n’explique pas un LCP qui passe de 4,5 à 1,3 seconde, ni 170 millisecondes de blocage du thread principal qui deviennent zéro. À ce stade, mieux vaut cesser de regarder le cercle vert et ouvrir le code. Toutes les références qui suivent renvoient au dépôt officiel litespeedtech/lscache_wp, version 7.9.1, et chacun peut les vérifier.
Ce n’est pas un simple délai de JavaScript
Une précision nécessaire : retarder le JavaScript n’est pas un mal en soi. Defer, delay, minification, Critical CSS et lazy loading sont des techniques légitimes, utilisées par de nombreux outils d’optimisation, et appliquées aux utilisateurs réels elles peuvent réellement améliorer l’expérience. Le problème apparaît quand le logiciel reconnaît qui est en train de le mesurer et réserve au testeur une version de la page différente de celle que recevra le navigateur d’un visiteur. C’est la différence entre optimiser un site et optimiser le résultat d’un examen.
Comment le plugin reconnaît qui le mesure
La reconnaissance se fait à deux niveaux. Le fichier data/gm_uas.txt contient la liste des User-Agents à toujours traiter comme « Guest » :
Lighthouse
GTmetrix
Google
Pingdom
bot
spider
PTST
HeadlessChrome
Les entrées sont combinées en une expression régulière insensible à la casse : il suffit donc que l’un de ces mots apparaisse dans le User-Agent. La seule entrée Google attrape à la fois PageSpeed Insights et Googlebot. À côté, il y a data/gm_ips.txt, avec les blocs d’adresses à reconnaître quel que soit le User-Agent : parmi les premiers figurent des plages de Google, dont le bloc historique de Googlebot, et deux blocs de GTmetrix. La reconnaissance est donc double : changer de User-Agent ne suffit pas pour y échapper.
Depuis la version 7.7, il y a un changement supplémentaire. Les deux listes, auparavant modifiables depuis le panneau du plugin, sont téléchargées chaque jour depuis les API de QUIC.cloud et l’emportent sur les fichiers fournis avec le plugin, tandis que les options correspondantes sont supprimées de la base de données lors de la mise à jour. En pratique, la liste de ceux qui reçoivent la variante réservée aux testeurs n’est plus décidée par celui qui gère le site, mais par l’éditeur du plugin, qui peut la mettre à jour à tout moment sur toutes les installations.
Deux portes : qui entre en Guest Mode et qui en sort
Le mécanisme comporte deux points de décision distincts. Le premier se trouve dans WordPress, dans la méthode _maybe_guest_mode(), et ne regarde ni le User-Agent ni l’IP : il vérifie seulement la présence du cookie _lscache_vary. Quiconque arrive sans ce cookie, personne ou robot, reçoit la variante Guest.
Le second décide qui reçoit le cookie, c’est-à-dire qui quitte la variante Guest. En bas de la page Guest, le plugin insère un petit script qui appelle guest.vary.php. Là, la méthode update_guest_vary() contient l’étape décisive :
if ( $this->always_guest() ) {
echo '[]';
exit;
}
Si la requête appartient à un testeur reconnu, elle ne reçoit pas le cookie et n’est pas invitée à recharger la page. Tous les autres reçoivent le cookie et une réponse qui indique au navigateur de recharger la page, qui sera désormais servie dans la variante normale. Côte à côte, les deux parcours se présentent ainsi :


PageSpeed Insights part toujours d’un profil vierge, arrive depuis une adresse de Google et déclare un User-Agent contenant Chrome-Lighthouse : il est servi en Guest et y reste pendant tout le test. Le Chrome du développeur, lui, a déjà le cookie ou le reçoit à la première visite : Lighthouse lancé depuis DevTools mesure donc la variante normale, celle que voit quiconque a déjà visité le site, c’est-à-dire la plupart des utilisateurs.
Le coût pour l’utilisateur réel : la page se charge deux fois
Le Guest Mode est présenté comme le moyen de rendre la première visite extrêmement rapide. Mais le premier vrai visiteur reçoit la page Guest, le navigateur l’affiche, le script contacte guest.vary.php, reçoit le cookie et recharge toute la page, cette fois dans la variante normale. Le coût réel de la première visite est la somme des deux chargements.
Le plugin lui-même le reconnaît implicitement : dans le <head>, il insère un script qui, après le rechargement, réécrit document.referrer avec la valeur enregistrée auparavant. Sans ce correctif, les outils d’analytics verraient le site lui-même comme source de chaque visite et le trafic organique disparaîtrait des rapports. Le testeur, qui ne recharge jamais, ne paie aucun de ces coûts.
Ce qui change dans la variante réservée aux testeurs
Quand Guest Optimization est activée, la constante LITESPEED_GUEST_OPTM est définie et, dans src/optimize.cls.php, la configuration JavaScript choisie par l’administrateur est remplacée :
$this->cfg_js_defer = $this->conf( self::O_OPTM_JS_DEFER );
if ( defined( 'LITESPEED_GUEST_OPTM' ) ) {
$this->cfg_js_defer = 2;
}
La valeur 2 correspond au mode delay, et non au simple defer. Et c’est exactement la situation créée par les préréglages officiels « Advanced » et « Aggressive », ceux que l’on recommande pour la plupart des sites : Guest Mode et Guest Optimization activés, JavaScript réglé sur 1, c’est-à-dire defer, pour tous les autres. Un administrateur qui applique le préréglage en un clic se retrouve, sans le savoir, avec deux sites : le testeur obtient du delay, l’utilisateur du defer.
Le JavaScript n’est que la partie la plus visible. Dans la variante Guest, le plugin impose aussi la minification et la combinaison du CSS et du JavaScript, la suppression de Google Fonts, le lazy load des images et des iframes, la suppression des solutions de repli <noscript> et des placeholders pour les images. Surtout, il ignore les exclusions d’URL et de rôles que l’administrateur a configurées précisément parce que certaines optimisations cassent quelque chose : pour le testeur, elles sont appliquées malgré tout. Le testeur n’ouvre pas les menus et ne remplit pas les formulaires : il ne remarquera donc jamais ce qui s’est cassé.
Des scripts qui ne démarrent que si quelqu’un interagit
En mode delay, une balise script ordinaire est réécrite ainsi :
<!-- avant -->
<script src="/wp-content/themes/theme/app.js"></script>
<!-- après -->
<script data-optimized="1" type="litespeed/javascript"
data-src="/wp-content/themes/theme/app.js"></script>
litespeed/javascript n’est pas un type que le navigateur exécute, et l’adresse du fichier ne figure plus dans src : la requête réseau ne démarre tout simplement jamais. La même chose arrive aux scripts inline et aux iframes, donc aux vidéos intégrées, aux cartes et aux publicités. Dans les fichiers JavaScript servis, en outre, la chaîne DOMContentLoaded est remplacée par un événement défini par le plugin, émis seulement après le chargement des scripts retardés.
Ce qui réactive tout, c’est le loader js_delay.js, qui écoute des événements comme mouseover, click, keydown, wheel et touchstart. Dans le code source, il y a aussi un minuteur de sécurité qui aurait chargé les scripts au bout de 70 millisecondes dans tous les cas, mais il est commenté. Sans interaction, le JavaScript retardé n’est donc jamais exécuté. Or Lighthouse ne bouge pas la souris et ne touche pas l’écran : pendant la fenêtre de mesure, le coût de ce code n’entre jamais dans le calcul. Un Total Blocking Time de zéro ne signifie pas que le JavaScript est devenu gratuit, mais qu’il n’a pas été exécuté pendant le test.
Comment le vérifier sur votre site
Deux requêtes suffisent. La première simule le testeur, sans cookie et avec Lighthouse dans le User-Agent ; la seconde simule un visiteur de retour, avec le cookie vary :
curl -s -A "Mozilla/5.0 (Linux; Android 11; moto g power (2022)) Chrome-Lighthouse" \
https://www.votresite.fr/ | grep -c 'type="litespeed/javascript"'
curl -s -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/128.0.0.0" \
-b "_lscache_vary=1" https://www.votresite.fr/ | grep -c 'type="litespeed/javascript"'
Si la première commande renvoie des dizaines d’occurrences et la seconde zéro, vous avez les deux variantes sous les yeux. Pour obtenir de PageSpeed Insights un chiffre qui représente les utilisateurs réels, il faut désactiver Guest Optimization, ou appliquer à tout le monde le même niveau d’optimisation que celui réservé aux testeurs. Le score baissera : c’est le vrai chiffre.
Pourquoi c’est un problème pour l’entreprise
La documentation de LiteSpeed elle-même avertit que Guest Optimization peut masquer de vrais problèmes et suggère de la désactiver pour obtenir une évaluation exacte des outils de test. C’est un aveu important, mais le plus grand dommage est organisationnel. Un 77 fait poser des questions : pourquoi le LCP est à 4,5 secondes, quel script bloque le thread principal, si le thème est trop lourd. Un 100 dit que le travail est terminé. Le client voit 100, l’agence voit 100, et celui qui devrait approuver davantage d’heures d’optimisation n’en voit pas la raison. Le problème reste, mais plus personne ne le cherche.
Pendant ce temps, les données qui comptent continuent de dire la vérité. Les Core Web Vitals que Google utilise comme signal de classement ne viennent pas de Lighthouse, mais du Chrome UX Report, c’est-à-dire des navigateurs d’utilisateurs réels : ceux qui ont le cookie, sur la variante normale. Ce n’est pas un hasard si un même rapport PageSpeed Insights peut afficher un 100 en laboratoire à côté de données de terrain insuffisantes. Et comme Google et les plages de Googlebot figurent dans les listes, le robot d’exploration reçoit lui aussi la variante dont le JavaScript est neutralisé : un point à évaluer avec attention pour les sites qui génèrent du contenu côté client.
Ce que nous ne disons pas
LiteSpeed Web Server et son cache côté serveur sont des outils efficaces, au même titre que le FastCGI cache de Nginx ou Varnish : servir du HTML prêt sans démarrer PHP ni la base de données est une excellente technique. De même, minification, Critical CSS, lazy load, defer et delay sont des outils valables. Ce que nous contestons, c’est une variante de la page pour laquelle le testeur peut être reconnu, ce qui fait observer au benchmark des conditions différentes de celles des utilisateurs. Il faut ajouter que, pour profiter du cache de LiteSpeed Web Server sur WordPress, le plugin LSCache est en pratique nécessaire pour l’invalidation des pages : séparer le serveur du plugin n’est pas toujours possible dans les faits.
En résumé
Le mécanisme est documenté par le code source : des listes de User-Agents et d’IP de testeurs mises à jour par l’éditeur, un cookie refusé uniquement à ceux qui sont reconnus, une variante dans laquelle le JavaScript est forcé en mode delay et chargé seulement après une interaction qui n’a pas lieu pendant un audit automatisé. Le résultat est un 100 sur PageSpeed Insights et un 77 dans Chrome sur la même page, avec un utilisateur réel qui, à la première visite, paie même deux chargements.
La comparaison avec le Dieselgate est inévitable, même si les conséquences ne sont pas comparables : là aussi, le logiciel reconnaissait le banc d’essai et changeait de comportement. Notre règle est simple : un site rapide n’a pas besoin de savoir qui le teste. Il doit être rapide pour PageSpeed Insights, pour Lighthouse et surtout pour une personne qui ouvre le site sur son propre téléphone. Quand le banc d’essai et la route racontent des histoires différentes, nous croyons la route.
L’analyse complète, avec toutes les références aux fichiers sources et aux méthodes, est publiée sur Managed Server.