import { onINP } from 'web-vitals';
onINP(({ value, entries }) => {
// Găsim cea mai lungă interacțiune din sesiune
const longestEntry = entries.sort((a, b) => b.duration - a.duration)[0];
const targetElement = longestEntry?.target;
// Trimitem datele către endpoint-ul de monitorizare
fetch('/api/analytics/vitals', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
metric: 'INP',
value: value,
elementSelector: targetElement ? getCssSelector(targetElement) : 'unknown'
}),
keepalive: true
});
});
function getCssSelector(el) {
if (!(el instanceof Element)) return 'unknown';
return el.tagName.toLowerCase() + (el.id ? `#${el.id}` : el.className ? `.${el.className.split(' ').join('.')}` : '');
}Salutare. Dacă tot ne batem capul cu SEO și UX în 2026, hai să vorbim direct despre Core Web Vitals, mai ales de când INP (Interaction to Next Paint) a devenit regele absolut al metricilor de interactivitate. Am trecut recent un proiect de e-commerce cu 45.000 de vizitatori unici pe lună prin furcile caudine ale optimizării și am învățat pe pielea mea unde ne mint testele sintetice și unde ne ajută RUM-ul (Real User Monitoring) real.
Lighthouse rulat local e o minciună frumoasă. Îți dă scor 98 pe un Macbook de ultimă generație, dar pe un Android ieftin, rulat pe 4G în metrou, site-ul tău agață la fiecare click.
INP-ul, noul balaur al performanței
LCP-ul (Largest Contentful Paint) și CLS-ul (Cumulative Layout Shift) sunt deja clasice. Le rezolvi cu un format corect de imagine, niște dimensiuni fixe și un font-display: swap. Dar INP e un monstru complet diferit. Măsoară latența tuturor interacțiunilor pe care un utilizator le are cu pagina ta pe parcursul întregii vizite.
Am avut un caz concret unde un simplu dropdown de filtrare bloca thread-ul principal din cauza unui script de tracking nesimțit. În PageSpeed Insights scorul era verde pentru că testul automat nu dădea click pe acel dropdown specific. În producție însă, utilizatorii reali aveau un INP de peste 450ms. Google a observat asta și ne-a penalizat vizibilitatea pe mobil în doar trei săptămâni.
Vercel Analytics vs. RUM custom: Trade-off-ul sincer
Dacă folosești Vercel, probabil ai fost tentat să activezi Speed Insights cu un singur click.
Unde merge bine: Este excelent pentru un overview rapid. Îți arată imediat dacă ai probleme mari pe anumite pagini fără să scrii o linie de cod.
Unde este complet nasol: Este extrem de limitat când vrei să faci debug pe bune și devine foarte scump dacă depășești limitele incluse. Vercel îți va spune: „Ai INP de 380ms pe pagina de produs”. Dar nu îți va spune ce element a declanșat acel delay și ce funcție JavaScript a ținut procesorul blocat.
Pentru a rezolva asta pe bune, am renunțat la Vercel Analytics pe acel proiect și am implementat un RUM custom folosind biblioteca oficială web-vitals de la Google. Am trimis datele direct în backend-ul nostru (sau în Sentry, dacă folosiți așa ceva). Am economisit în jur de 120$ pe lună și, cel mai important, am obținut selectorul CSS exact al elementului care a provocat blocajul.
Cum colectezi datele reale fără să încetinești site-ul
Secretul este să folosești opțiunea keepalive: true din fetch pentru a trimite datele chiar înainte ca utilizatorul să părăsească pagina, fără să blochezi navigarea.
După ce am rulat scriptul de mai jos timp de o săptămână, am descoperit că 80% din problemele de INP veneau de la un widget de chat de la terți care rula un loop infinit pe evenimentul de scroll. Am amânat încărcarea acelui widget cu 3 secunde și scorul INP a scăzut instant sub 150ms (în zona verde).
Tu cum monitorizezi Core Web Vitals în producție? Te bazezi doar pe ce zice Search Console o dată la câteva zile sau ai implementat deja un sistem de RUM în timp real?