Como a melhoria do INP da Fotocasa contribuiu para um crescimento de 27% nas principais métricas

Publicado em 14 de outubro de 2025

A Interaction to Next Paint (INP) é uma métrica essencial das Core Web Vitals para medir a capacidade de resposta. No Fotocasa, o Google Search Console destacou um número significativo de páginas que mudaram para "Precisa de melhorias" e "Ruim" quando a INP substituiu o First Input Delay (FID) em 2024. Este estudo de caso descreve as ferramentas e estratégias usadas para diagnosticar e resolver esses problemas, melhorando substancialmente o INP.

Onde a equipe da Fotocasa começou

Antes da mudança do FID para o INP, quase todas as páginas em computadores e dispositivos móveis estavam dentro do limite "Bom", o que significa que todas as Core Web Vitals da época (LCP, CLS e FID) estavam funcionando bem. No entanto, depois da mudança para a INP, quase todas as páginas passaram para "Precisa melhorar" e algumas até para "Ruim", já que os valores da INP excederam consistentemente 200 milissegundos para a maioria das interações do usuário.

O Google Search Console mostrando a distribuição de URLs da Fotocasa em computadores, com muitas páginas mudando de "Boa" para "Precisa de melhorias" depois que o INP se tornou uma Core Web Vital.
Figura 1. Google Search Console – Distribuição de URLs da Fotocasa em computadores: quando o INP entrar em vigor, muitos URLs antes classificados como "bons" vão passar para a categoria "precisa de melhorias".

Essa mudança fez com que a equipe da Fotocasa percebesse que estava negligenciando um aspecto crucial da experiência do usuário. Enquanto a FID mede apenas o atraso da primeira interação, a INP avalia a capacidade de resposta de todas as interações, considerando o processamento de entrada e os atrasos de apresentação. Essa medição mais ampla é uma proxy muito melhor para a verdadeira interatividade (conforme declarado pelo Google) e destacou oportunidades perdidas.

Embora o Google Search Console forneça dados de performance de campo, ele não oferece insights em tempo real. Os dados são agregados em uma janela de 28 dias, o que dificulta identificar exatamente quais interações estavam causando problemas no momento.

Era necessário acompanhar o INP em tempo real para identificar as interações mais lentas e mais usadas pelos usuários e reproduzi-las de maneira confiável nos ambientes de desenvolvimento da equipe. Também foi importante entender o impacto das mudanças feitas, não apenas quais correções ajudaram, mas também quais ajustes pioraram as coisas sem querer.

Por isso, usamos um conjunto de ferramentas para diagnosticar e resolver os problemas. Os mais importantes foram:

  • O Chrome DevTools, especificamente a guia "Performance".
  • Um sistema RUM (Real User Monitoring, em inglês) personalizado criado pela equipe da Fotocasa no Datadog usando a biblioteca web-vitals.
  • Ferramentas para desenvolvedores do React.

Ferramentas para diagnosticar o problema

Para diagnosticar e depurar problemas de desempenho do INP, usamos as seguintes ferramentas.

Google Chrome DevTools

Uma excelente maneira de detectar e reproduzir problemas relacionados às Core Web Vitals em um aplicativo da Web é usar a guia "Performance" no Google Chrome DevTools. A guia "Performance" mede automaticamente as métricas das Core Web Vitals, oferecendo feedback instantâneo sobre carregamento, interatividade e mudança de layout. Ela é consistente com a forma como essas métricas são informadas a outras ferramentas do Google.

A guia "Performance" no Google Chrome DevTools, mostrando uma linha do tempo com várias métricas de performance, como LCP, FID e CLS, além da atividade da CPU e da rede.
Figura 2. A guia "Performance" no Google Chrome DevTools.

Para identificar e resolver problemas de INP, a equipe da Fotocasa geralmente começava limitando a CPU para simular o desempenho de dispositivos de baixo e médio custo. Isso permitiu que a equipe da Fotocasa observasse o comportamento da página em condições mais restritas. A sessão foi gravada usando o criador de perfil, e os rastreamentos foram analisados com cuidado, com foco na interação do usuário para identificar problemas de desempenho.

A guia "Performance" no Chrome DevTools mostrando o menu suspenso de redução de velocidade da CPU com opções como "Redução de velocidade 4x" e "Redução de velocidade 6x".
Figura 3. A guia "Performance" no Chrome DevTools mostrando o menu suspenso de redução de velocidade da CPU.

Ao identificar gargalos, é especialmente útil examinar as subpartes do INP e as tarefas que o navegador realiza em cada uma delas. Por exemplo, na imagem a seguir, é possível ver que o INP é bastante alto devido a dois recálculos de estilo causados por mudanças no estilo do corpo do documento.

A guia "Performance" do Google Chrome DevTools mostrando uma tarefa longa no criador de perfis, com detalhes indicando dois recálculos de estilo que causam um INP alto.
Figura 4. A guia "Performance" no Chrome DevTools mostrando o criador de perfis preenchido.

A Fotocasa configurou um sistema para rastrear o INP e outras métricas das Core Web Vitals, garantindo que os problemas de desempenho sejam identificados e resolvidos rapidamente. Quando uma métrica ultrapassa um limite específico (com base nos intervalos definidos pelo Google), a atribuição é registrada para que o problema possa ser analisado e resolvido.

Para esse sistema, a biblioteca web-vitals foi usada para capturar essas métricas de usuários reais de uma forma que corresponda com precisão à maneira como elas são medidas pelo Chrome e informadas a outras ferramentas do Google (como o Chrome User Experience Report, o PageSpeed Insights, o relatório de velocidade do Search Console e outras).

Para ter uma visão abrangente e um acompanhamento centralizado, a Fotocasa usou o Datadog para coletar e visualizar os dados, permitindo que a equipe tomasse decisões informadas e orientadas por dados. As métricas personalizadas mantêm a eficiência de custo e permitem rastrear quase todos os usuários no site da Fotocasa.

Painel do Datadog da Fotocasa mostrando várias métricas de performance, incluindo INP, LCP e CLS, ao longo do tempo.
Figura 5. Painel de RUM de desempenho do Datadog da Fotocasa.
Painel do Datadog mostrando gráficos para métricas de atraso de entrada, duração do processamento e atraso de apresentação.
Figura 6. Métricas de latência na entrada, duração do processamento e latência na apresentação.

Esse sistema permite que a equipe da Fotocase monitore rapidamente se as modificações afetam as métricas ou se ocorrem alterações imprevistas, o que pode comprometer os resultados. A métrica INP pode ser dividida em partes, como atraso de entrada, duração do processamento e atraso de apresentação, para identificar precisamente qual parte da interação é a principal responsável por tempos de interação longos.

Um gráfico do Datadog mostrando um pico repentino nos valores de INP, indicando uma anomalia.
Figura 7. Uma anomalia de INP detectada no painel.
Um alarme de monitor no Datadog mostrando uma anomalia de INP detectada.
Figura 8. Uma anomalia de INP detectada no alarme do monitor.

Ao detectar anomalias, como a ilustrada nas figuras 7 e 8, a Fotocasa respondeu imediatamente e usou o OpenSearch, outra ferramenta que ajudou a identificar onde a alteração pode estar ocorrendo. Os dados fornecidos pela biblioteca web-vitals ajudaram a identificar o destino (o elemento DOM potencialmente responsável por um valor de métrica elevado) e ajudam a equipe a se concentrar mais na correção do problema.

Painel do OpenSearch mostrando dados da biblioteca web-vitals, usada para identificar quais elementos do DOM estão afetando a métrica INP.
Figura 9. Painel do OpenSearch para depurar qual destino está afetando a métrica INP.

Além disso, é possível definir vários filtros, como tipo de página, dispositivo ou estado de carregamento, para simplificar cenários e entender melhor como a INP está sendo afetada.

Ferramentas para desenvolvedores do React

As ferramentas para desenvolvedores do React foram usadas para melhorar os recursos de depuração do Fotocasa, que oferece um recurso avançado para destacar visualmente os componentes que foram renderizados novamente.

Para ativar esse recurso, acesse a guia Profiler. Clique na engrenagem no lado direito da barra superior, acesse a guia Geral e marque a caixa de seleção Destacar atualizações quando os componentes forem renderizados. Com essa opção ativada, os componentes são destacados quando são renderizados novamente, fornecendo uma representação visual dinâmica.

O painel de configurações nas Ferramentas para Desenvolvedores do React, com a caixa de seleção "Destacar atualizações quando os componentes forem renderizados" marcada.
Figura 10. O criador de perfil configura as Ferramentas para Desenvolvedores do React.

Como descobrir a causa de uma nova renderização

Depois de identificar um componente que foi renderizado novamente, a próxima pergunta é: "Por que isso aconteceu?" O React DevTools responde a isso com uma dica útil na visualização do gráfico de chamas.

Para acessar essas informações, grave uma sessão do criador de perfil. Ao analisar a saída do criador de perfil, você encontra informações úteis:

  • No canto superior direito, o número de commits do React é exibido.
  • O gráfico de chamas representa visualmente a árvore de componentes, com cinza indicando componentes que não foram renderizados novamente. Cada barra representa um momento em que a árvore de componentes do React mudou e quando uma mudança correspondente foi confirmada no DOM.
  • Ao passar o cursor sobre cada componente no gráfico de chamas, o motivo da nova renderização vai aparecer no subtítulo Por que isso foi renderizado?.

Os motivos para uma nova renderização de um componente podem incluir:

  • Esta é a primeira vez que o componente foi renderizado.
  • O contexto mudou
  • Hooks mudaram
  • Props changed
  • Estado alterado
  • O componente pai renderizado
O criador de perfil das Ferramentas para desenvolvedores do React mostrando um gráfico de chamas, com uma dica aberta em um componente explicando que ele foi renderizado novamente porque "Hooks changed".
Figura 11. O painel de renderização no criador de perfis das Ferramentas para desenvolvedores do React.

Como descobrir o tempo de renderização

As cores no gráfico de chamas transmitem informações significativas. Cores como vários tons de azul indicam que um componente exigiu um tempo de renderização relativamente curto em comparação com outros componentes. Por outro lado, cores como laranja e vermelho significam que um componente teve mais tempo de renderização.

O criador de perfil das Ferramentas para desenvolvedores do React mostrando um gráfico de chamas em que as cores indicam o tempo de renderização, com tons de azul representando tempos mais curtos e tons de laranja/vermelho representando tempos mais longos.
Figura 12. Tempo de renderização, conforme mostrado no criador de perfis das Ferramentas para desenvolvedores do React.

Como a equipe da Fotocasa corrigiu o problema

Remover renderizações desnecessárias

As renderizações ocorrem sempre que o React precisa atualizar a interface com novos dados. Isso geralmente vem de uma ação do usuário, uma resposta da API ou outros eventos importantes que exigem uma atualização da interface. Como cada renderização executa JavaScript, muitas delas de uma só vez, especialmente em uma grande árvore de componentes, podem bloquear a linha de execução principal e causar problemas de desempenho.

Há dois tipos de renderização:

  • Renderizações necessárias: quando um componente realmente precisa ser atualizado porque possui ou usa dados novos.
  • Renderizações desnecessárias: quando um componente é atualizado sem nenhuma mudança significativa, geralmente devido ao gerenciamento de estado ineficiente ou ao tratamento inadequado de propriedades.

Alguns renderizações desnecessárias geralmente não são um grande problema, já que o React é rápido o suficiente para que os usuários geralmente não percebam. No entanto, se eles ocorrerem com muita frequência ou em uma árvore de componentes pesada, poderão prejudicar a experiência do usuário e afetar negativamente o INP da página.

Esse foi o caso da equipe da Fotocasa. Eles perceberam que o site tinha muitas renderizações desnecessárias. Esses eventos ocorreram em dois cenários principais:

  • Durante o carregamento da página: aumentar o número de tarefas longas na linha de execução principal e atrasar a primeira interação, o que afetou negativamente o INP da página.
  • Durante as interações do usuário: aumentar o tempo de processamento da maioria das interações, o que também prejudicou o INP.

Muitas renderizações desnecessárias acabaram sendo otimizadas no site da Fotocasa. Uma das maiores otimizações realizadas foi na página de pesquisa. Houve três renderizações desnecessárias no carregamento da página. Depois que eles foram removidos, os seguintes resultados foram observados:

  • Menos tarefas longas (consulte a figura abaixo)
  • Menos tempo total de bloqueio (compare as figuras 14 e 15)
Dois snapshots da linha de execução principal do Chrome DevTools. O snapshot de cima mostra mais tarefas longas antes das otimizações, enquanto o de baixo mostra menos tarefas longas depois da remoção de renderizações desnecessárias.
Figura 13. Snapshot da linha de execução principal com e sem renderizações desnecessárias.
Um relatório de performance móvel do Lighthouse mostrando um tempo total de bloqueio de 1.080 ms, indicando problemas de performance causados por renderizações desnecessárias.
Figura 14. O relatório de performance para dispositivos móveis do Lighthouse mostrando renderizações desnecessárias.
Um relatório de performance para dispositivos móveis do Lighthouse mostrando um tempo total de bloqueio significativamente reduzido após a remoção de novas renderizações desnecessárias.
Figura 15. O relatório de performance para dispositivos móveis do Lighthouse sem renderizações desnecessárias.

Colocation de estado

O posicionamento inadequado do estado do React pode deixar um aplicativo mais lento e fazer com que a interface pareça não responder. Quando o estado de um componente muda, os componentes filhos são renderizados novamente por padrão, a menos que um recurso de escape seja usado (por exemplo, memo).

Como explicado na seção anterior, as renderizações não são ruins por natureza, mas renderizar a página inteira devido a uma atualização de estado específica pode levar a interações mais lentas, já que as atualizações do DOM ocorrem após a renderização.

Por exemplo, na página de pesquisa, há uma caixa de diálogo que mostra todos os filtros quando um botão é clicado.

A barra de filtros na página de pesquisa do Fotocasa, mostrando um botão para abrir uma caixa de diálogo com todos os filtros.
Figura 16. Barra de filtros do Fotocasa.

O estado que controla o estado aberto da caixa de diálogo, nesse caso, foi colocado na página de pesquisa. Quando esse estado mudou, toda a página foi renderizada novamente, causando um INP ruim, principalmente em dispositivos mais lentos, como visto quando o controle da CPU foi usado no DevTools:

Limitação da CPU INP
Desacelerar 4x 440 milissegundos (precisa de melhorias)
Desacelerar 6x 832 milissegundos (ruim)

Mudar o estado o mais próximo possível do componente que aciona a mudança resolve esse problema. Nesse caso específico, o estado pode ser colocado no componente de botão dos filtros. Assim, quando o estado mudar, apenas o botão será renderizado novamente.

Limitação da CPU INP
Desacelerar 4x 64 milissegundos (bom)
Desacelerar 6x 232 milissegundos (precisa de melhorias)

Remover estados desnecessários

Os estados não podem conter informações redundantes ou duplicadas. Se isso acontecer, pode levar a renderizações desnecessárias e causar problemas.

Por exemplo, na barra de filtros da Fotocasa, há um texto que representa o número de filtros aplicados a uma determinada pesquisa:

A barra de filtros do Fotocasa mostrando um botão chamado "Filtros" com um número indicando a contagem de filtros aplicados.
Figura 17. Botão e contador de filtros do Fotocasa.

O número de filtros aplicados é calculado com base no estado do aplicativo. No entanto, isso não apenas resultou em uma nova renderização desnecessária de todo o componente, mas, em alguns casos, também levou a uma mudança de layout, já que esse componente é renderizado do lado do servidor:

const [filtersCount, setFiltersCount] = useState(DEFAULT_COUNTER)

useEffect(() => {
  const counter = filters
    ? Object.keys(filters)
        ?.reduce(reducerCounter, [])
        ?.filter((param) => searchParams?.[param]).length
    : DEFAULT_COUNTER

  setFiltersCount(counter)
}, [searchParams]);

Para resolver esse problema, o valor foi derivado do objeto de filtros usando uma variável em vez de usar o estado:

const counter = filters
    ? Object.keys(filters)
        ?.reduce(reducerCounter, [])
        ?.filter((param) => searchParams?.[param]).length
    : DEFAULT_COUNTER;

Reduzir renderizações caras

Quando uma interação ocorre em um aplicativo React, ela normalmente aciona uma mudança de estado. Como explicado anteriormente, quando o estado de um componente muda, ele é renderizado novamente com todos os filhos.

Se uma dessas funções de renderização de componentes for lenta, isso afetará negativamente o INP da página, já que provavelmente uma tarefa longa será gerada, e o DOM vai levar mais tempo para ser atualizado.

A equipe da Fotocasa tentou minimizar ao máximo os cálculos demorados na função de renderização dos componentes. O Chrome DevTools e o React Developer Tools foram muito úteis para detectar operações de renderização lentas.

Atrasar a execução do código

Além de otimizar a função de renderização dos componentes, outras funções foram otimizadas para minimizar tarefas longas o máximo possível. No entanto, algumas tarefas não puderam ser otimizadas porque dependiam de código de terceiros.

Um exemplo foi o Analytics. Nesse caso, foi decidido atrasar a execução do código de análise e priorizar as atualizações do DOM quando ocorriam interações do usuário. Para isso, a equipe da Fotocasa usou uma biblioteca chamada idlefy, que também garantiu que o código de análise continuasse sendo executado mesmo se o navegador fosse fechado imediatamente depois.

Cultura de performance

O trabalho de desempenho não é um esforço único, mas algo que precisa ser considerado em todos os recursos lançados para produção. Todos na equipe precisam estar alinhados. Caso contrário, as regressões nas Core Web Vitals são quase inevitáveis.

Para ficar por dentro disso, a equipe da Fotocasa compartilhou ativamente conhecimento e estabeleceu uma estrutura clara para identificar problemas de performance com base nos dados de RUM do Datadog da Fotocasa, incluindo como reproduzi-los. Alertas para as Principais métricas da Web, especialmente o INP, foram configurados no sistema RUM para notificar a equipe da Fotocasa diretamente no Slack. Essa abordagem manteve o desempenho em mente e ajudou a detectar problemas antes que eles se tornassem regressões.

Resultados

Para melhorar o INP no Fotocasa, foi preciso combinar otimizações técnicas e mudanças culturais. Ao eliminar renderizações desnecessárias, otimizar o posicionamento de estado, reduzir renderizações caras e adiar códigos não críticos, a equipe da Fotocasa conseguiu mover todas as páginas de computador de "precisa de melhorias" para "boa" e melhorou significativamente as páginas para dispositivos móveis, atualizando quase todas as páginas "ruins" e "precisa de melhorias" para "boa".

O Google Search Console mostrando as Core Web Vitals da Fotocasa para computadores após melhorias no INP.
Figura 18. O Google Search Console mostrando as Core Web Vitals da Fotocasa para computadores após melhorias no INP.

Essas mudanças melhoraram a experiência geral do usuário da Fotocasa e, junto com outras iniciativas, geraram um aumento de 27% nos anúncios de contato e de lead por telefone, fortalecendo diretamente as principais métricas de negócios da empresa.

O monitoramento em tempo real com o Datadog permitiu que a equipe da Fotocasa validasse as melhorias do INP, detectasse rapidamente anomalias e evitasse regressões. Além dessas conquistas, a Fotocasa também conseguiu incorporar a performance da Web à cultura de desenvolvimento, garantindo que a INP e as Core Web Vitals continuem sendo uma prioridade em todas as versões.