Web Vitals e SEO: como a experiência do usuário afeta o seu site

Antes de falar de Web Vitals, vale lembrar o que é SEO.
SEO, sigla para Search Engine Optimization (Otimização para Motores de Busca), é um conjunto de técnicas para otimizar um site de modo que os Search Crawlers (os robôs de busca de Google, Bing e DuckDuckGo) consigam conhecer e indexar as páginas dele.
Quanto mais otimizado o site, maior a chance de ele aparecer nas primeiras posições dos SERPs (Search Engine Result Pages), os resultados de busca, e de receber mais acessos.
Dá para dividir o SEO em três frentes:
- On-Page: conteúdo, palavras-chave, meta tags (como as OG tags) e estrutura do site.
- Off-Page: estratégias externas, como backlinks vindos de outros sites.
- Técnico: performance, tempo de carregamento, segurança (HTTPS) e dados estruturados.
E os Web Vitals?
O Google criou os Web Vitals em 2020. Eles são um conjunto de métricas que medem, com números, a qualidade da experiência de quem usa um site.
Eles entram no SEO técnico. Ao otimizá-los, o site carrega mais rápido, responde melhor aos cliques e dá uma experiência melhor ao usuário.
O SEO cuida da visibilidade nos buscadores, e os Core Web Vitals cuidam de a página ser rápida e estável quando o visitante chega. Trabalhar as duas coisas juntas aumenta a chance de ranquear bem e de manter o visitante na página.
Core Web Vitals
Os Core Web Vitals são um subconjunto dos Web Vitals. Hoje eles são três métricas:
- CLS, Cumulative Layout Shift
- LCP, Largest Contentful Paint
- INP, Interaction to Next Paint
O Google separa as principais das demais por três motivos:
- Priorização: com as métricas principais definidas, fica claro onde a pessoa desenvolvedora deve começar a otimizar.
- Simplicidade: com poucas métricas, é mais fácil entender quais otimizações fazer.
- Alinhamento com o Google: o Google é o buscador mais usado do mundo e quer entregar boas páginas aos seus usuários. Os Core Web Vitals fazem parte disso, e uma página que passa neles entrega o tipo de experiência que o Google procura.
Cumulative Layout Shift (CLS)
O CLS mede a estabilidade visual de uma página, ou seja, o quanto os elementos se mexem de forma inesperada durante o carregamento. Um CLS alto indica que o layout muda de repente, e quem está lendo acaba clicando no lugar errado.
Para ter uma boa experiência, o site deve manter o CLS em 0,1 ou menos em pelo menos 75% das visitas.
Exemplos de erros de CLS
O primeiro caso, bem comum, é a imagem que carrega depois do resto da página. Ela "empurra" o conteúdo para baixo para abrir espaço. A solução é definir largura e altura na imagem, para o navegador reservar o espaço antes de baixá-la.
<img src="/codigo-ao-ponto.jpg" width="600" height="400" />
O segundo caso são as fontes personalizadas. O navegador precisa baixá-las antes de renderizar o texto corretamente, e isso causa um deslocamento quando a fonte web chega e substitui a fonte de fallback.
Para resolver, pré-carregue a fonte com a tag link e rel="preload", use font-display no @font-face e ajuste as métricas da fonte de fallback com size-adjust.
<!-- Pré-carregar a fonte crítica acima da dobra -->
<link
rel="preload"
href="/fonts/inter.woff2"
as="font"
type="font/woff2"
crossorigin
/>
@font-face {
font-family: "Inter";
src: url("/fonts/inter.woff2") format("woff2");
font-display: swap;
}
/* Fallback com métricas ajustadas para evitar CLS */
@font-face {
font-family: "Inter Fallback";
src: local("Arial");
size-adjust: 107%;
ascent-override: 90%;
descent-override: 22%;
line-gap-override: 0%;
}
body {
font-family: "Inter", "Inter Fallback", sans-serif;
}
O font-display: swap mostra o texto na hora usando a fonte de fallback e troca para a fonte web quando ela carrega. Para a troca não deslocar nada, você ajusta as métricas da fonte de fallback (size-adjust, ascent-override e as demais) para que ela ocupe o mesmo espaço da fonte web.
Se a fonte não for crítica, use font-display: optional. Nesse caso, a fonte web só é usada se carregar em cerca de 100 ms. Se demorar mais, o navegador mantém a fallback nessa navegação, e a troca de fonte deixa de ser fonte de CLS.
O terceiro caso são banners, anúncios e embeds injetados sem espaço reservado. Quando um script de terceiro insere um anúncio depois que a página já renderizou, o conteúdo abaixo é empurrado.
<!-- Ruim: slot de anúncio sem dimensões -->
<div id="ad-slot"></div>
<script>
loadAd("ad-slot");
</script>
<!-- Bom: espaço reservado com min-height ou aspect-ratio -->
<div
id="ad-slot"
style="min-height: 250px; width: 300px; background-color: #f3f4f6;"
>
<!-- Anúncio será injetado aqui -->
</div>
Em embeds responsivos, como vídeos do YouTube, use aspect-ratio no CSS para reservar o espaço proporcional antes do carregamento.
Largest Contentful Paint (LCP)
O LCP mede quanto tempo a página leva para renderizar o maior elemento de conteúdo visível na viewport. Esse elemento pode ser uma imagem, um bloco de texto, um vídeo ou um SVG.
Um LCP bom é de 2,5 segundos ou menos no percentil 75 das visitas reais.
O que conta como LCP
O navegador considera candidatos a LCP:
- Imagens (
<img>,<picture>) - Elementos
<video> - Elementos com imagem de fundo via CSS (
background-image) - Blocos de texto (parágrafos e títulos)
Na maioria das páginas, o LCP é a imagem principal (hero image) ou o título.
Causas comuns de LCP alto
- TTFB alto: o servidor demora para responder à requisição inicial.
- Imagem principal com lazy loading: usar
loading="lazy"na imagem acima da dobra atrasa o LCP. - Recursos que bloqueiam a renderização: CSS ou JS pesado antes do conteúdo crítico.
- Imagem pesada: arquivos grandes em formatos não otimizados.
Como melhorar o LCP
Use fetchpriority="high" na imagem principal para priorizar o download dela.
<img
src="/hero.webp"
fetchpriority="high"
width="1600"
height="900"
alt="Descrição da imagem principal"
/>
Não use loading="lazy" na imagem do LCP. Deixe que ela carregue de imediato (ou use loading="eager" de forma explícita).
Se o navegador não descobre a imagem principal cedo, pré-carregue-a.
<link
rel="preload"
as="image"
href="/hero.webp"
imagesrcset="/hero-400.webp 400w, /hero-800.webp 800w, /hero-1200.webp 1200w"
imagesizes="(max-width: 600px) 100vw, 50vw"
/>
Converta as imagens para AVIF ou WebP e use srcset para servir o tamanho certo a cada dispositivo.
<picture>
<source srcset="/hero.avif" type="image/avif" />
<source srcset="/hero.webp" type="image/webp" />
<img
src="/hero.jpg"
fetchpriority="high"
width="1600"
height="900"
alt="Descrição da imagem principal"
/>
</picture>
Interaction to Next Paint (INP)
O INP mede a responsividade da página. Ele observa a latência de todas as interações (cliques, toques e teclas) durante a visita e reporta o valor da interação mais lenta, desconsiderando casos isolados muito fora da curva.
Um INP bom é de 200 ms ou menos no percentil 75.
O INP substituiu o FID (First Input Delay) como Core Web Vital em março de 2024. O FID media só o atraso da primeira interação. O INP considera todas as interações e mede o tempo completo, do início da interação até a próxima pintura com retorno visual.
O que causa INP alto
- Long tasks: tarefas JavaScript que bloqueiam a thread principal por mais de 50 ms.
- Handlers de input pesados: código que roda a cada clique, tecla digitada ou rolagem.
- Scripts de terceiros: analytics, anúncios e widgets sociais disputando a thread principal.
Como melhorar o INP
Quebre tarefas longas em pedaços menores e use scheduler.yield() para devolver o controle ao navegador entre eles.
// Helper com fallback para navegadores sem scheduler.yield()
function yieldToMain() {
if ("scheduler" in window && "yield" in scheduler) {
return scheduler.yield();
}
return new Promise((resolve) => setTimeout(resolve, 0));
}
async function processJobs(jobQueue) {
for (const job of jobQueue) {
job();
await yieldToMain();
}
}
Use debounce em handlers de input que disparam com frequência.
function debounce(fn, delay) {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => fn(...args), delay);
};
}
input.addEventListener(
"input",
debounce((e) => {
searchAPI(e.target.value);
}, 300)
);
Adie o JavaScript não crítico para depois que a página estiver interativa.
<script src="/analytics.js" defer></script>
<script src="/chat-widget.js" async></script>
TBT
O TBT (Total Blocking Time) não é um Core Web Vital. Ele é uma métrica de laboratório, usada pelo Lighthouse para avaliar a performance em testes controlados.
O TBT soma o tempo em que a thread principal ficou bloqueada por tarefas longas (acima de 50 ms) entre o FCP (First Contentful Paint) e o momento em que a página fica interativa.
Ele serve como indicador do INP quando você não tem dados de campo suficientes. Se o TBT está alto no Lighthouse, é provável que o INP em produção também esteja ruim.
Outras métricas do Web Vitals que não são Core:
- TTFB (Time to First Byte): tempo até o primeiro byte da resposta do servidor.
- FCP (First Contentful Paint): tempo até o primeiro conteúdo ser renderizado.
Elas ajudam no diagnóstico, mas não entram na avaliação de "passou ou não passou" dos Core Web Vitals.
O ciclo de vida das métricas do Web Vitals
As métricas passam por três fases até virarem Core Web Vitals estáveis:
- Experimental: a métrica está em teste e coletando dados. Ainda não é recomendada como indicador de performance em produção.
- Pending: a métrica se mostrou útil e está pronta para substituir uma existente, mas o Google dá um prazo para a comunidade se ajustar.
- Stable: a métrica é oficialmente um Core Web Vital.
A troca do FID pelo INP é o exemplo mais recente. O INP começou como experimental, passou para pending em 2023 e se tornou stable em março de 2024.
Como medir
Existem duas formas de medir os Core Web Vitals:
- Dados de campo: métricas coletadas de usuários reais, pelo Chrome User Experience Report (CrUX). É o que o Google usa na avaliação.
- Dados de laboratório: métricas coletadas em ambiente controlado, pelo Lighthouse ou pelo Chrome DevTools. Servem para diagnóstico e para testar antes de publicar.
O Google avalia os Core Web Vitals no percentil 75 das visitas. Na prática, 75% das experiências reais precisam estar na faixa "boa" para a página passar.
Ferramentas para medir
- PageSpeed Insights: mostra dados de campo (CrUX) e de laboratório (Lighthouse) de uma URL.
- Google Search Console: o relatório de Core Web Vitals mostra quais páginas do site passam ou falham, com base em dados de usuários reais.
- Lighthouse: ferramenta de auditoria do Chrome DevTools. Gera métricas de laboratório, incluindo o TBT.
- Biblioteca web-vitals: pacote npm para coletar as métricas em produção.
import { onLCP, onINP, onCLS } from "web-vitals";
onLCP((metric) => {
console.log("LCP:", metric.value);
});
onINP((metric) => {
console.log("INP:", metric.value);
});
onCLS((metric) => {
console.log("CLS:", metric.value);
});
A biblioteca entrega os valores reais de cada métrica, e você decide o que fazer com eles, por exemplo enviá-los ao seu sistema de monitoramento.
Conclusão
Voltando à pergunta do título: a experiência do usuário afeta o SEO do seu site?
Afeta, mas não tanto quanto o conteúdo. A experiência da página é um sinal de ranqueamento no Google, mas relevância e qualidade do conteúdo pesam mais. Core Web Vitals bons funcionam como critério de desempate entre páginas com conteúdo parecido, e ainda melhoram conversão e retenção.
No Bing, a performance da página também conta, com menos ênfase que no Google. Ele considera velocidade de carregamento e experiência do usuário, mas prioriza a relevância do conteúdo e a autoridade do domínio.
Uma página rápida e estável também converte mais e mantém as pessoas lendo por mais tempo, e isso já justifica o trabalho nos Core Web Vitals.





