Performance and Core Web Vitals

PrestaShop 8 Performance: The Core Web Vitals 2026 Checklist (LCP, INP, CLS) with Real PHP and SQL Code

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

Core Web Vitals (CWV) became a direct Google ranking factor in 2024, and their weight in e-commerce page rankings continues to rise in 2026. On PrestaShop 8, optimising CWV is both an SEO task and a quality-of-experience task: an LCP moving from 4.2 s to 1.8 s mechanically delivers +20–40% mobile conversion rate, according to Google studies and our own measurements on stores we accompany. Yet CWV optimisation remains poorly understood. Most merchants run a Lighthouse, see a red score, install a generic cache module, and find the score barely moves — because the real levers are not in the cache, but in precise technical details.

This checklist details the CWV optimisations that actually produce results on PrestaShop 8 in 2026, with real PHP and SQL code adapted to PrestaShop architecture — not generic advice copied from Google documentation.

The 3 Core Web Vitals 2026 and their thresholds

LCP (Largest Contentful Paint) measures the time from page load start to the rendering of the largest visible element (typically the main product image on a product page, or the category hero text). Thresholds: good below 2.5 s, needs improvement 2.5–4 s, poor above 4 s.

INP (Interaction to Next Paint) replaced FID in March 2024. It measures the latency between a user interaction (click, tap, keyboard input) and the next visible render. Thresholds: good below 200 ms, needs improvement 200–500 ms, poor above 500 ms.

CLS (Cumulative Layout Shift) measures unexpected visual shifts during loading (image pushing text, late-appearing banner). Thresholds: good below 0.1, needs improvement 0.1–0.25, poor above 0.25.

For a page to reach “Good” in Search Console, all three metrics must be green at the 75th percentile of real loads. This is what makes optimisation difficult: your store can be fast for a desktop fibre visitor and catastrophic for a low-end Android on degraded 4G — Google calculates the score on real users (Field Data via the Chrome User Experience Report).

Measuring CWV on your store: Lab Data vs Field Data

Lab Data (synthetic measurement): PageSpeed Insights, Lighthouse, WebPageTest. The page is loaded by a robot in a standardised environment. Reproducible but doesn’t reflect your real visitors’ experience. Useful for diagnosis and development.

Field Data (real measurements): Chrome User Experience Report (CrUX), accessible in Search Console > Enhancements > Core Web Vitals. These are the numbers Google uses for ranking — aggregated measurements of your visitors’ real loads over the past 28 days.

Set up Real User Monitoring (RUM) now: the Google web-vitals library integrates in a few lines of JS and sends measurements to GA4. RUM measurements are the most faithful to what Google sees, allowing segmentation by device type, country, browser — revealing where your real problems are.

LCP: optimisations that actually work

1. Identify the LCP element precisely

Before anything else, identify which element triggers the LCP on your key pages. Lighthouse indicates it in its report, but the most precise tool is the Chrome Web Vitals Extension which highlights the LCP element in real time on any page. On a PrestaShop product page, the LCP is almost always the main product image.

2. LCP image preloading

On product pages, adding a <link rel="preload"> in the head for the main product image gains 200 to 500 ms on the LCP, because the browser starts downloading the image before it has even parsed the HTML containing it.

Implementation in the product page Twig template:

{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}

The fetchpriority="high" attribute tells the browser this resource is critical and should be prioritised in the download queue.

3. WebP / AVIF conversion with correct dimensions

Serving your product images in WebP reduces their size by 25–35% vs JPEG at equivalent visual quality. AVIF saves a further 20% but with slightly higher browser decoding cost — the 2026 compromise remains WebP for most, AVIF for critical hero images.

Verify that served dimensions match the actual display size: serving a 2000×2000 image displayed at 400×400 wastes bandwidth and increases LCP. Use srcset to offer multiple sizes per viewport.

4. TTFB and server SQL queries

LCP is bounded from below by TTFB (Time To First Byte). Activate PrestaShop profiling (Configuration > Performance > enable debug + profiler mode) and check the Database tab. If you see a query executing 50 times per product page load with 200 ms cumulative time, it’s probably an N+1 query in a poorly coded module. That module must be patched or disabled.

Most frequently guilty modules on stores we audit: review modules querying the average rating for each displayed product without caching, related products modules making one query per recommended product, stock modules recalculating availability on every product display. Our Performance & Core Web Vitals category covers several of these patterns.

INP: the modern performance killer (and the most misunderstood)

INP replaced FID in March 2024 and is now the hardest metric to optimise on PrestaShop. The reason: FID only measured the first interaction; INP measures all interactions and keeps the worst 98th percentile. So a single slow interaction out of 50 (a category filter click that freezes for 500 ms) weighs more than 49 fast interactions.

1. Identify slow interactions

The Chrome Web Vitals Extension displays INP in real time during navigation. Click everywhere on your store (filters, add to cart, popups, FAQ accordions, product swiper) and watch which interactions exceed 200 ms. Typical culprits on PrestaShop: category filters (faceted search) that reload the entire grid via AJAX, add-to-cart triggering heavy hooks, Quick View modal openings, product variant changes (colour, size).

2. Long tasks and yielding to the main thread

A slow interaction is almost always caused by a JavaScript “long task” (a function blocking the main thread for more than 50 ms). The modern solution: break long tasks with scheduler.yield() (native API in recent Chromium) or with a setTimeout(fn, 0) pattern:

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 and throttle on inputs

On search filters, variant selects, quantity inputs: don’t trigger AJAX on every keypress. Debounce 200–300 ms before sending the request. Without this, a fast-typing visitor generates 10 AJAX requests all saturating the main thread.

4. JS code splitting and deferred loading

Many PrestaShop modules load their JS on all pages when they’re only used on some. Audit your controllers and use $this->context->controller->registerJavascript() with the right controller parameter to limit loading to the pages where the JS is needed. For genuinely heavy features, load JS lazily via dynamic import() at the moment of first interaction, not at page load.

CLS: visual stability

1. Reserve space for images. Every image in the HTML must have explicit width and height attributes (or a CSS aspect-ratio). Without them, the image shifts the layout when it loads. Every <img src="..." /> without width and height is suspect.

2. Web fonts and FOIT/FOUT. If you use Google Fonts or custom fonts, the browser may display invisible text (FOIT) then brutally switch (FOUT) when the font arrives. Solution: font-display: optional in CSS for secondary fonts, and font-display: swap with a metric-compatible fallback using size-adjust CSS.

3. Deferred banners and popups. Cookie banners, newsletter popups, top bars appearing 1–3 seconds after load are frequent CLS sources. Either reserve the space in CSS from the start, or make banners appear as overlays (fixed/absolute position) that don’t push existing content.

4. External iframes and embeds. YouTube, Vimeo, Calendly iframes that load deferred shift content. Systematically reserve their space with an aspect-ratio: 16/9 wrapper.

SQL and database optimisations specific to PrestaShop

Profiling with EXPLAIN

When the PrestaShop profiler reveals a slow query (more than 50 ms), run it through MySQL with EXPLAIN. If you see type: ALL with a large number of rows scanned, there’s probably a missing index. If you see Using filesort or Using temporary, the query is doing unnecessary work.

Typical missing indexes on PrestaShop

On stores with large catalogues (5000+ products) and many third-party modules: missing index on id_product, id_shop in module custom tables; missing index on columns used for category filters (faceted search); missing index on id_order, date_add for order stats queries. A single well-placed index can divide a query time by 50.

N+1 queries in hooks

The most destructive pattern in PrestaShop performance: a hook executing for each displayed product making one SQL query per product. On a category displaying 24 products, that’s 24 additional queries per load. Detection: PrestaShop profiler > Database. If you see the same query repeated N times with different parameters, it’s an N+1.

Solution: modify the module to batch queries. Instead of making one query per product in the displayProductMiniature hook, collect all product IDs via actionProductListBefore and make a single WHERE id_product IN (1, 2, 3, ...) query.

PrestaShop cache: Smarty + module cache

On PrestaShop 8, two cache levels complement each other. Smarty cache (compiles templates to PHP) is used in production: verify SMARTY_CONSOLE_FORCE_COMPILE = 0 and SMARTY_CACHE = 1 in config/defines.inc.php. Module cache is more powerful: a well-coded module caches its heavy calculations and only redoes them when data changes.

On high-traffic stores, add an HTTP cache (Varnish, or LiteSpeed cache on the host) that serves pre-rendered product pages without even reaching PrestaShop — dividing TTFB by 10 on repeated requests.

The third-party module trap

On stores we audit, 60–80% of CWV problems come from poorly coded third-party modules. The pattern is always the same: a module installed for a useful feature (live chat, newsletter popup, loyalty badge, social proof) loads heavy JS on all pages, worsening LCP and INP, and nobody makes the connection.

The audit to run regularly: disable all third-party modules and run Lighthouse → that’s your “pure PrestaShop” baseline. Re-enable modules one by one re-running Lighthouse each time. Identify modules that drop the score by more than 5 points → those are your culprits.

Several modules in our catalogue were built with these constraints in mind, like the DataFirefly SideCart module (JS loaded only on pages where it displays) and the DataFirefly Cross-Sell module (analytics fire via AJAX outside the critical LCP path) — topic covered in our article on cross-sell contributing to average order value.

Conclusion: ongoing work, not a one-off project

Core Web Vitals optimisation on PrestaShop 8 is rarely a few-day project done once and forgotten. Every newly installed module can break the score; every PrestaShop update can introduce regressions. The right reflex is to set up permanent monitoring (Search Console + RUM via web-vitals.js + GA4) and check metrics routinely. A degradation detected in week 1 fixes in a few hours; the same degradation detected in week 8 becomes a full multi-day audit.

For further reading, browse our Performance & Core Web Vitals and PrestaShop tutorials categories.