Performance & Core Web Vitals

Performance PrestaShop 8 : la checklist Core Web Vitals 2026 (LCP, INP, CLS) avec vrai code PHP et SQL

Performance PrestaShop 8 : la checklist Core Web Vitals 2026 (LCP, INP, CLS) avec vrai code PHP et SQL

Les Core Web Vitals (CWV) sont devenus en 2024 un facteur de ranking direct pour Google, et leur poids dans le classement des pages e-commerce continue d’augmenter en 2026. Sur PrestaShop 8, optimiser les CWV est à la fois un travail SEO et un travail de qualité d’expérience : un LCP qui passe de 4,2 s à 1,8 s, c’est mécaniquement +20-40 % de taux de conversion mobile selon les études Google et nos propres mesures sur les boutiques accompagnées. Pourtant, l’optimisation CWV reste mal comprise. La majorité des marchands lancent un Lighthouse, voient un score rouge, installent un module de cache générique, et constatent que le score ne bouge quasiment pas — parce que les vrais leviers ne sont pas dans le cache, mais dans des détails techniques précis.

Cette checklist détaille les optimisations CWV qui produisent réellement des résultats sur PrestaShop 8 en 2026, avec du vrai code PHP et SQL adapté à l’architecture PrestaShop, pas des conseils génériques copiés depuis une documentation Google.

Les 3 Core Web Vitals 2026 et leurs seuils

Google mesure trois métriques pour évaluer la qualité de chargement et d’interaction d’une page.

LCP (Largest Contentful Paint) mesure le temps écoulé entre le début du chargement et le rendu du plus grand élément visible (typiquement l’image principale d’une fiche produit, ou le texte du hero d’une page catégorie). Seuils : bon en-dessous de 2,5 s, à améliorer entre 2,5 et 4 s, mauvais au-delà de 4 s.

INP (Interaction to Next Paint) a remplacé FID en mars 2024. Il mesure la latence entre une interaction utilisateur (clic, tap, frappe clavier) et le prochain rendu visible. Seuils : bon en-dessous de 200 ms, à améliorer entre 200 et 500 ms, mauvais au-delà de 500 ms.

CLS (Cumulative Layout Shift) mesure les décalages visuels imprévus pendant le chargement (image qui pousse le texte, bandeau qui apparaît tardivement). Seuils : bon en-dessous de 0,1, à améliorer entre 0,1 et 0,25, mauvais au-delà de 0,25.

Pour qu’une page passe en « Bon » dans Search Console, les trois métriques doivent être dans le vert au 75e percentile des chargements réels (les 25 % de visites les plus lentes peuvent être au-dessus, mais les 75 % les plus rapides doivent être bonnes). C’est ce qui rend l’optimisation difficile : votre boutique peut être rapide pour un visiteur en fibre desktop et catastrophique pour un visiteur en 4G dégradée sur Android entry-level — Google calcule le score sur les vrais utilisateurs réels (Field Data via Chrome User Experience Report).

Mesurer les CWV sur votre boutique : Lab Data vs Field Data

Il existe deux types de mesures qu’il faut distinguer.

Lab Data (mesure synthétique). PageSpeed Insights, Lighthouse, WebPageTest. La page est chargée par un robot dans un environnement standardisé (3G simulé, mobile mid-range). Les chiffres sont reproductibles mais ne reflètent pas l’expérience de vos vrais visiteurs. Utile pour le diagnostic et le développement.

Field Data (mesures réelles). Chrome User Experience Report (CrUX), accessible dans Search Console > Améliorations > Core Web Vitals. Ce sont les chiffres que Google utilise pour le ranking. Mesure agrégée des chargements réels de vos visiteurs sur les 28 derniers jours. C’est la métrique qui compte pour le SEO.

L’écart entre Lab Data et Field Data peut être énorme : un site qui a un score Lighthouse de 95 peut avoir des Field Data en rouge si la majorité de ses visiteurs sont sur des appareils plus lents que le profil Lighthouse standard. À l’inverse, un site avec un Lighthouse de 60 peut être correct en Field Data si son audience est principalement desktop.

L’outil à mettre en place dès maintenant. Configurez le Real User Monitoring (RUM) sur votre boutique. Plusieurs options gratuites : la library web-vitals de Google qui s’intègre en quelques lignes de JS et envoie les mesures à GA4, ou des outils comme Cloudflare Web Analytics, SpeedCurve, Calibre. Les mesures RUM sont les plus fidèles à ce que Google voit, et permettent de segmenter par type d’appareil, par pays, par navigateur — ce qui révèle où sont vos vrais problèmes.

LCP : les optimisations qui marchent vraiment

Le LCP est généralement la métrique la plus impactante côté business sur PrestaShop, parce qu’il concerne directement la perception de vitesse au chargement d’une fiche produit. Voici les leviers par ordre d’impact typique.

1. Identifier précisément le LCP element

Avant tout, identifiez quel élément déclenche le LCP sur vos pages clés. Lighthouse l’indique dans son rapport, mais l’outil le plus précis est l’extension Chrome Web Vitals Extension qui surligne en temps réel le LCP element sur n’importe quelle page. Sur une fiche produit PrestaShop, le LCP est presque toujours l’image principale du produit. Sur une catégorie, c’est généralement la première image visible de la grille produit. Sur la home, c’est le hero/slider.

Une fois identifié, c’est ce LCP element qu’il faut prioriser dans l’optimisation — préchargement, conversion en format moderne, dimensionnement, lazy loading désactivé.

2. Préchargement de l’image LCP

Sur les fiches produit, ajouter un <link rel="preload"> dans le head pour l’image principale produit fait gagner 200 à 500 ms sur le LCP, parce que le navigateur démarre le téléchargement de l’image avant même d’avoir parsé le HTML qui la contient.

Implémentation dans le template Twig de la fiche produit (themes/votre-theme/templates/catalog/product.tpl en Smarty, ou le fichier équivalent en Twig pour les thèmes modernes) :

{if isset($product.cover.bySize.large_default.url)}
<link rel="preload" as="image"
      href="{$product.cover.bySize.large_default.url}"
      imagesrcset="..." imagesizes="..." fetchpriority="high">
{/if}

L’attribut fetchpriority="high" est important — il indique au navigateur que cette ressource est critique et doit passer devant les autres dans la queue de téléchargement.

3. Conversion WebP / AVIF avec dimensions correctes

Servir vos images produit en WebP réduit leur poids de 25 à 35 % vs JPEG à qualité visuelle équivalente. AVIF économise encore 20 % de plus mais avec un décodage légèrement plus coûteux côté navigateur — le compromis 2026 reste WebP en majorité, AVIF pour les hero images critiques.

Sur PrestaShop 8, plusieurs modules font la conversion automatique (le natif PrestaShop a une option WebP basique, des modules tiers font mieux avec AVIF et compression adaptative). Vérifiez aussi que les dimensions servies correspondent à l’affichage réel : servir une image 2000×2000 affichée en 400×400 gaspille de la bande passante et augmente le LCP. Utilisez srcset pour proposer plusieurs tailles selon le viewport.

4. TTFB et requêtes SQL serveur

Le LCP est borné en bas par le TTFB (Time To First Byte) : tant que votre serveur n’a pas commencé à envoyer du HTML, le navigateur ne peut rien rendre. Sur PrestaShop, le TTFB peut être plombé par des requêtes SQL non-optimisées dans des hooks lourds.

L’audit à faire : activer le profiling PrestaShop (Configuration > Performance > activer le mode debug + profiler) et regarder l’onglet Database. Si vous voyez une requête qui s’exécute 50 fois par chargement de page produit avec un temps cumulé de 200 ms, c’est probablement une N+1 query dans un module mal codé. Le module en question doit être patché ou désactivé.

Les modules les plus fréquemment coupables sur les boutiques que nous auditons : modules d’avis qui requêtent la note moyenne pour chaque produit affiché sans cache, modules de related products qui font une requête par produit recommandé, modules de stock qui calculent la disponibilité à chaque affichage produit. Notre catégorie Performance & Core Web Vitals couvre plusieurs de ces patterns.

INP : le tueur de performance moderne (et le plus mal compris)

L’INP a remplacé FID en mars 2024 et c’est désormais la métrique la plus difficile à optimiser sur PrestaShop. La raison : FID ne mesurait que la première interaction, INP mesure toutes les interactions et garde le pire 98e percentile. Donc une seule interaction lente sur 50 (par exemple un clic sur un filtre catégorie qui freeze pendant 500 ms) pèse plus que 49 interactions rapides.

1. Identifier les interactions lentes

L’extension Chrome Web Vitals Extension affiche l’INP en temps réel pendant la navigation. Cliquez partout sur votre boutique (filtres, ajout au panier, popups, accordéons FAQ, swiper produit) et regardez quelles interactions dépassent 200 ms. Sur PrestaShop, les coupables typiques sont :

  • les filtres de catégorie (faceted search) qui rechargent toute la grille en AJAX ;
  • les ajouts au panier qui déclenchent des hooks lourds ;
  • les ouvertures de modal de produit (Quick View) ;
  • les changements de variante produit (couleur, taille).

2. Long tasks et yield au main thread

Une interaction lente est presque toujours causée par une « long task » JavaScript (une fonction qui bloque le main thread plus de 50 ms). Le navigateur ne peut pas répondre aux clics suivants tant que la long task n’est pas finie.

La solution moderne : découper les long tasks avec scheduler.yield() (API native dans les Chromium récents) ou avec un pattern setTimeout(fn, 0) pour rendre la main au navigateur entre les morceaux de calcul. Exemple : si vous avez une boucle qui traite 1000 produits côté front, découpez-la en chunks de 50 avec un yield entre chaque chunk.

async function processProducts(products) {
  for (let i = 0; i < products.length; i += 50) {
    const chunk = products.slice(i, i + 50);
    chunk.forEach(processProduct);
    if ('scheduler' in window && 'yield' in scheduler) {
      await scheduler.yield();
    } else {
      await new Promise(r => setTimeout(r, 0));
    }
  }
}

3. Debounce et throttle sur les inputs

Sur les filtres de recherche, les selects de variante, les inputs de quantité, ne déclenchez pas l’AJAX à chaque keypress. Debounce de 200 à 300 ms avant l’envoi de la requête. Sans ce détail, un visiteur qui tape rapidement génère 10 requêtes AJAX qui toutes saturent le main thread.

4. Code splitting JS et chargement différé

Beaucoup de modules PrestaShop chargent leur JS sur toutes les pages alors qu’ils ne sont utilisés que sur certaines (un module Quick View qui charge sur la home, un module FAQ qui charge sur les fiches catégorie). Auditez votre front/controllers/... et utilisez $this->context->controller->registerJavascript() avec le bon controller en paramètre pour limiter le chargement aux pages où le JS est nécessaire.

Pour les fonctionnalités vraiment lourdes (un slider Swiper, un éditeur WYSIWYG), chargez le JS en lazy via import() dynamique au moment de la première interaction, pas au chargement de la page.

CLS : la stabilité visuelle

Le CLS est généralement la métrique la plus facile à corriger sur PrestaShop, parce que les causes sont peu nombreuses et bien connues.

1. Réservation d’espace pour les images. Toute image dans le HTML doit avoir des attributs width et height explicites (ou un aspect-ratio CSS). Sans ça, l’image fait varier la mise en page quand elle se charge. Sur PrestaShop, les images produit générées par les hooks displayProduct... doivent toutes avoir leurs dimensions. Vérifiez votre code de thème : tout <img src="..." /> sans width et height est suspect.

2. Fontes web et FOIT/FOUT. Si vous utilisez Google Fonts ou des fontes custom, le navigateur peut afficher du texte invisible (FOIT) puis basculer brutalement (FOUT) quand la fonte arrive — ce qui décale tout le contenu. Solution : font-display: optional dans le CSS pour les fontes secondaires, et font-display: swap avec un fallback métrique-compatible (utilisez size-adjust CSS pour matcher la fonte fallback à la fonte custom et éliminer le shift).

3. Bannières et popups différés. Les bandeaux cookie, popups newsletter, top bars qui apparaissent 1 à 3 secondes après chargement sont des sources fréquentes de CLS. Solution : réservez l’espace en CSS dès le départ (avec min-height) si vous savez que la bannière va apparaître, ou faites apparaître la bannière en overlay (position fixed/absolute) qui ne décale pas le contenu existant.

4. Iframes externes et embeds. Les iframes YouTube, Vimeo, Calendly qui chargent en différé décalent le contenu. Réservez systématiquement leur espace avec un wrapper en aspect-ratio: 16/9 ou équivalent.

Optimisations SQL et database PrestaShop spécifiques

Sur PrestaShop, une part importante du TTFB (et donc du LCP) vient des requêtes SQL. Voici les patterns à connaître.

Profiling avec EXPLAIN

Quand le profiler PrestaShop révèle une requête lente (plus de 50 ms), passez-la dans MySQL avec EXPLAIN pour comprendre ce qui se passe. Si vous voyez un type: ALL avec un grand nombre de rows scannées, il manque probablement un index. Si vous voyez Using filesort ou Using temporary, la requête fait du travail inutile et doit être réécrite.

Index manquants typiques sur PrestaShop

Sur les boutiques avec un grand catalogue (5000+ produits) et beaucoup de modules tiers, certains index manquent souvent. Les patterns que nous voyons en audit :

  • Index manquant sur id_product, id_shop dans les tables custom de modules ;
  • Index manquant sur les colonnes utilisées pour les filtres de catégorie (faceted search) ;
  • Index manquant sur id_order, date_add pour les requêtes de stats commandes.

Ajoutez les index manquants directement en SQL via PhpMyAdmin ou via une migration de module. Mesurez avant/après — un seul index bien placé peut diviser un temps de requête par 50.

N+1 queries dans les hooks

Le pattern le plus destructeur en performance PrestaShop : un hook qui s’exécute pour chaque produit affiché et qui fait une requête SQL par produit. Sur une catégorie qui affiche 24 produits, ça fait 24 requêtes additionnelles par chargement.

Détection : profiler PrestaShop > Database. Si vous voyez la même requête répétée N fois avec des paramètres différents, c’est une N+1.

Solution : modifier le module pour batcher les requêtes. Au lieu de faire une requête par produit dans le hook displayProductMiniature, le module doit collecter tous les IDs produits via actionProductListBefore et faire une seule requête WHERE id_product IN (1, 2, 3, ...) qui ramène tous les résultats d’un coup.

Cache PrestaShop : Smarty + cache module

Sur PrestaShop 8, deux niveaux de cache se complètent. Le cache Smarty (compile les templates en PHP) est utilisé en production : vérifiez SMARTY_CONSOLE_FORCE_COMPILE = 0 et SMARTY_CACHE = 1 dans config/defines.inc.php. Le cache module (cache custom dans les modules) est plus puissant : un module bien codé met en cache ses calculs lourds et ne les refait que quand les données changent. Si un module recalcule à chaque page la même chose, c’est un bug à corriger.

Sur les boutiques avec beaucoup de trafic, ajoutez aussi un cache HTTP (Varnish, ou cache LiteSpeed côté hébergement) qui sert les pages produit pré-rendues sans même atteindre PrestaShop. Cela divise le TTFB par 10 sur les requêtes répétées et libère le serveur pour les requêtes vraiment dynamiques.

Le piège des modules tiers

Sur les boutiques que nous auditons, 60 à 80 % des problèmes de CWV viennent de modules tiers mal codés. Le pattern est toujours le même : un module installé pour une fonctionnalité utile (chat live, popup newsletter, badge fidélité, social proof) charge un JS lourd sur toutes les pages, alourdit le LCP et l’INP, et personne ne fait le lien.

L’audit à faire régulièrement :

  • Désactivez tous les modules tiers et lancez Lighthouse → c’est votre baseline « PrestaShop pur ».
  • Réactivez les modules un par un en relançant Lighthouse à chaque fois.
  • Identifiez les modules qui font sauter le score de plus de 5 points → ce sont vos coupables.
  • Pour chaque coupable : soit vous trouvez un réglage qui le rend plus léger, soit vous le remplacez par une alternative mieux codée, soit vous décidez que la fonctionnalité ne vaut pas la dégradation.

Critère de choix d’un module nouveau en 2026 : avant d’installer, vérifiez que le module ne charge ses assets que sur les pages où il est utilisé (pas sur toutes les pages), qu’il fait du SQL batché (pas de N+1), qu’il propose un cache configurable, et qu’il a un changelog récent (un module non maintenu depuis 18 mois sur PrestaShop 8 est suspect).

Plusieurs des modules de notre catalogue ont été développés avec ces contraintes en tête, comme le module DataFirefly SideCart qui charge son JS uniquement sur les pages où il s’affiche, ou le module DataFirefly Cross-Sell dont les analytics partent en AJAX hors du chemin critique pour ne pas impacter le LCP — sujet abordé dans notre article sur le cross-sell qui contribue au panier moyen.

Conclusion : un travail continu, pas un projet ponctuel

L’optimisation Core Web Vitals sur PrestaShop 8 est rarement un travail de quelques jours qu’on fait une fois et qu’on oublie. C’est un travail continu : chaque nouveau module ajouté peut casser le score, chaque mise à jour PrestaShop peut introduire des régressions, chaque évolution de Google (l’arrivée de l’INP en mars 2024 par exemple) peut redistribuer les priorités.

Le bon réflexe est de mettre en place un monitoring permanent (Search Console + RUM via web-vitals.js + GA4) et de checker les métriques en routine, pas seulement quand un problème devient visible. Une dégradation détectée en semaine 1 se corrige en quelques heures ; la même dégradation détectée en semaine 8, après que vous avez ajouté trois autres modules dans l’intervalle, devient un audit complet de plusieurs jours.

Pour aller plus loin, parcourez nos catégories Performance & Core Web Vitals et Tutoriels PrestaShop pour les sujets techniques connexes. Et si vous identifiez des modules de votre stack actuel qui plombent les CWV sans apporter de valeur correspondante, plusieurs modules de notre catalogue ont été pensés pour être performance-first par construction — le SideCart, le Cross-Sell, et l’ensemble de la gamme DataFirefly partagent le même engagement : pas de JS sur les pages où le module n’est pas affiché, pas de N+1, pas de dépendances externes inutiles.