Optimizare viteză magazin online — Core Web Vitals explicați

Un magazin online lent pierde 40% din vizitatori la 3 secunde și 7% conversie pentru fiecare secundă în plus. Core Web Vitals sunt metricile cu care Google măsoară experiența reală a utilizatorului. Le explicăm pe fiecare, cu cauze concrete și fixuri aplicabile azi.

Magazinul tău se încarcă greu? Vezi serviciul nostru de optimizare sau cere audit gratuit.

Ce sunt Core Web Vitals

Core Web Vitals sunt trei metrici standardizate de Google care măsoară experiența reală a utilizatorului (NU estimări de laborator). Datele provin din browserul real al vizitatorilor — Chrome Raportează (CrUX). Din iunie 2021 sunt factor de ranking confirmat: site-urile verzi primesc un avantaj în SERP, cele roșii sunt penalizate.

Cele trei metrici acoperă trei dimensiuni distincte: încărcare (LCP), interactivitate (INP) și stabilitate vizuală (CLS). Toate trebuie verzi pentru a trece pragul Google.

LCP — Largest Contentful Paint (încărcare)

Definiție: timpul până când cel mai mare element vizual din viewport se randează complet. Într-un magazin online, elementul dominant este de obicei imaginea hero, slider-ul principal sau titlul paginii.

Tinte Google: sub 2,5 secunde (verde). 2,5s-4s (portocaliu). peste 4s (roșu).

Cauze comune de LCP slab

  • Imagine hero neoptimizată: 3-5 MB JPEG/PNG, fără format modern (WebP/AVIF), fără dimensiuni responsive.
  • Resurse render-blocking: CSS extern ne-critic, fonturi Google sincrone, JS în head fără defer.
  • TTFB ridicat: serverul răspunde în peste 600ms. Vezi și optimizarea bazei de date.
  • Layout-uri client-rendered: conținutul principal apare doar după execuție JS (SPA fără SSR/SSG).

Fixuri LCP

  • Preload imaginea LCP: <link rel="preload" as="image" href="/hero.webp" fetchpriority="high">
  • Formate moderne: WebP (cu fallback JPEG) sau AVIF. Reducere 30-70% față de JPEG.
  • Responsive: srcset + sizes pentru a servi imaginea potrivită pe fiecare device.
  • Critical CSS inline: CSS-ul necesar above-the-fold direct în <style>, restul încărcat asincron.
  • CDN pentru imagini: Cloudflare Images, Cloudinary, imgix — redimensionare + conversie la cerere.

INP — Interaction to Next Paint (interactivitate)

Definiție: latența medie a tuturor interacțiunilor utilizatorului (click, tap, tastatură) cu pagina, pe parcursul vizitei. A înlocuit FID în martie 2024 și este mult mai strict.

Tinte Google: sub 200ms (verde). 200ms-500ms (portocaliu). peste 500ms (roșu).

Cauze comune de INP slab

  • Task-uri JS lungi: bucle care blochează thread-ul principal peste 50ms (parsare JSON mare, render listă de sute de produse).
  • Third-party scripts: chat-uri, popups, pixels marketing care ascultă click-uri pe document.
  • Re-render-uri grele: React/Vue care re-randează tot arborele la fiecare modificare de stare.
  • Event handleri pe body/window: ascultă fiecare mișcare de mouse și execută logică scumpă.

Fixuri INP

  • Yield la main thread: sparge task-uri lungi cu setTimeout, requestIdleCallback, sau scheduler.yield().
  • Partytown: mută third-party scripts (GA, Meta Pixel) într-un Web Worker — nu mai blochează main thread-ul.
  • Debounce/throttle: pe handleri de scroll, resize, input.
  • Virtualizare liste: randează doar elementele vizibile (react-window, vue-virtual-scroller) pentru liste peste 100 itemi.
  • Memoizare: useMemo, React.memo, computed properties pentru a evita re-render-uri inutile.

CLS — Cumulative Layout Shift (stabilitate vizuală)

Definiție: suma tuturor deplasărilor vizuale neașteptate pe parcursul vizitei. CLS mare = conținutul „sare” sub deget, vizitatorul lovește butonul greșit, frustrare.

Tinte Google: sub 0,1 (verde). 0,1-0,25 (portocaliu). peste 0,25 (roșu).

Cauze comune de CLS slab

  • Imagini/fără dimensiuni: fără width + height, browser-ul nu rezervă spațiu, conținutul sare după încărcare.
  • Fonturi care apar târziu: fără font-display: swap, textul se redenmensează când fontul se încarcă.
  • Bannere/cookies care apar după 2s: popup-uri, bannere, newsletter modals care împing conținutul.
  • Anunțuri și embed-uri fără rezervare spațiu: iframe-uri YouTube, widget-uri recenzii.

Fixuri CLS

  • Dimensiuni mereu pe img: <img width="800" height="600"> — browser-ul rezervă aspect ratio.
  • Min-height pe containere: pentru bannere, sliders, player-uri video: aspect-ratio: 16/9.
  • Preconnect la fonturi: <link rel="preconnect" href="https://fonts.gstatic.com"> + font-display: swap.
  • Reservă spațiu pentru ads: container cu dimensiune fixă, ad-ul încarcă în interior.
  • Popup-uri fixed/overlay: nu împing conținutul, plutesc deasupra.

Imagini — cea mai mare oportunitate

În 80% din magazinele pe care le audităm, imaginile reprezintă 60-80% din greutatea paginii. Optimizarea lor singură poate scoate LCP-ul de la 4s la 2s.

  • Format: AVIF > WebP > JPEG/PNG. <picture> cu fallback: <source srcset="img.avif" type="image/avif"> + <source srcset="img.webp" type="image/webp"> + <img src="img.jpg">.
  • Compresie: 80-85% calitate pentru fotografii, 90% pentru produse. Sub 80% artefacte vizibile.
  • Lazy load: loading="lazy" pe toate imaginile sub fold. NICIODATĂ pe imaginea LCP — folosește fetchpriority="high".
  • Responsive: generează 3-5 dimensiuni per imagine (400w, 800w, 1200w, 1920w), servește prin srcset.
  • Host pe CDN: Cloudflare Images, Cloudinary. Redimensionare la cerere prin URL.

JavaScript blocking — taie din bundle

Bundle-uri JS peste 200KB gzipped sunt o problemă. Fiecare KB executat pe main thread întârzie INP și LCP.

  • Tree-shaking: importă doar ce folosești. import { debounce } from 'lodash' nu import _ from 'lodash'.
  • Code-splitting: route-level chunks cu React.lazy / Vue async components. Dashboard-ul nu se încarcă pe homepage.
  • Defer toate scripturile: <script defer> pe tot ce nu e critic. Nu pune JS în head fără defer.
  • Audit apps Shopify: multe teme au 10-20 apps care încarcă JS propriu. Dezinstalează-le pe cele nefolosite.
  • Partytown pentru analytics: GA4, Meta Pixel, Hotjar — toate în Web Worker, nu pe main thread.

Fonturi — unii sutimi de secundă

  • Max 2 familii: una pentru titluri, una pentru text. Fiecare familie = încă 1 request + delay.
  • font-display: swap: arată textul imediat cu font fallback, apoi swap la fontul real. Elimină FOIT (flash of invisible text).
  • Preload: <link rel="preload" as="font" type="font/woff2" crossorigin> pentru fontul principal.
  • Subset: încarcă doar caracterele folosite pe site (latin-ext pentru RO/EN). Reduce woff2 de la 100KB la 20KB.

Tool-uri de măsură

  • PageSpeed Insights (pagespeed.web.dev): raport combinat Lab (Lighthouse) + Field (CrUX). Free, esențial.
  • Lighthouse (Chrome DevTools): audit local pe orice pagină. Modul mobile/desktop separat.
  • WebPageTest (webpagetest.org): waterfall detaliat din multiple locații. Pentru audit aprofundat.
  • Google Search Console — Core Web Vitals: raport agregat pe toți vizitatorii reali. Arată câte URL-uri sunt verzi/portocalii/roșii.
  • Chrome UX Report (CrUX): date publice pe origin (dacă site-ul are trafic suficient).

Caz concret — before/after

Magazin WooCommerce, 15.000 vizitatori/lună, conversie 1,2%. Plângere: „se încarcă greu pe mobil”.

Diagnostic inițial (PageSpeed mobile):

  • LCP: 6,8s (roșu) — imagine hero 4,2MB JPEG, fără preload
  • INP: 480ms (portocaliu) — 14 apps Shopify-style, 1,2MB JS
  • CLS: 0,32 (roșu) — imagini fără dimensiuni, fonturi fără swap

Intervenții (3 săptămâni):

  • Conversie imagini la WebP + responsive (hero de la 4,2MB la 180KB)
  • Redis object cache + indexi pe tabelele WooCommerce
  • Lazy load + dimensiuni pe toate imaginile, fetchpriority="high" pe hero
  • Defer JS, Partytown pentru GA, eliminat 6 apps redundante
  • Cloudflare CDN + image resize la cerere

Rezultat (după 30 zile):

  • LCP: 2,1s (verde) — îmbunătățire 69%
  • INP: 160ms (verde) — îmbunătățire 67%
  • CLS: 0,04 (verde) — îmbunătățire 87%
  • Conversie: 1,9% (+58%). Trafic organic: +14% în 60 zile.

Continuă lectură