A paginação do seu blog provavelmente esconde posts do Google

pagination

Um blog com sessenta posts, doze por página, tem cinco páginas. A primeira página lista doze posts; os outros quarenta e oito ficam atrás da paginação. Se o rastreador de um buscador não consegue segui-la, seus posts antigos só são alcançáveis pelo sitemap e pelos links que vêm de outros lugares, e um buscador tem pouco motivo para ranquear um post para o qual nada aponta.

A maioria das paginações de blog é feita de um jeito que os rastreadores não conseguem seguir, ou diz a eles que nem tentem. Encontrei um desses erros no meu próprio blog enquanto o reconstruía este mês. São quatro erros comuns; para cada um, o que fazer em vez disso, e no final uma checklist.

Erro 1: “Carregar mais” sem URLs

Um botão “Carregar mais” ou uma rolagem infinita que busca a próxima página com JavaScript é agradável de usar e invisível para os rastreadores. A documentação do Google diz que, em geral, ele rastreia apenas as URLs no href de elementos <a>, que seus rastreadores não clicam em botões e que a Pesquisa Google não rola a página nem interage com ela de outro jeito.

Se o único jeito de chegar ao post 13 é clicar em “Carregar mais”, para um rastreador o seu blog não tem nenhum link para o post 13.

Em vez disso: dê a cada página uma URL, /blog?page=2 ou /blog/page/2, e aponte para ela com um <a href> de verdade. O botão “Carregar mais” pode continuar existindo por cima: renderize os links de paginação no HTML e deixe o JavaScript interceptar o clique e acrescentar a próxima página ali mesmo. Os rastreadores seguem o link; as pessoas usam o botão.

Erro 2: paginação feita de botões

O mesmo problema em outro formato:

tsx
<button onClick={() => setPage(page + 1)}>Próxima</button>

Ele muda o que a página mostra sem mudar a URL. Os rastreadores não conseguem segui-lo, o visitante não consegue compartilhar a página três nem voltar a ela, e o botão Voltar do navegador passa direto por ela.

Em vez disso: paginação é navegação, então faça com links. Num framework com renderização no servidor, isso também significa que a página de ?page=2 é renderizada no servidor, com os posts no HTML, que é o que o rastreador lê.

Erro 3: todas as páginas com a canonical na primeira

Este parece um bom hábito de SEO, e por isso aparece em todo lugar:

HTML
<!-- em /blog?page=2, /blog?page=3, ... -->
<link rel="canonical" href="https://example.com/blog" />

Uma tag canonical diz: “esta página é uma cópia; a original está ali”. A página dois não é cópia da página um: ela lista outros posts. Dizer o contrário a um buscador é um convite para ele tirar a página dois do índice, e com ela os únicos links para esses posts.

As orientações do Google sobre paginação dizem exatamente isso: não use a primeira página de uma sequência como página canônica; dê a cada página a sua própria URL canônica.

Meu próprio blog tinha esse bug. Até esta versão, todas as páginas do blog em kookee.dev, incluindo ?page=2, declaravam /blog como canonical. Agora cada página sem filtro aponta a canonical para si mesma: a página um para /blog, a página dois para /blog?page=2.

Em vez disso: uma canonical autorreferente em cada página da sequência.

Erro 4: noindex nas páginas depois da primeira

A versão mais antiga do mesmo instinto: tirar do índice as páginas de listagem “rasas” com noindex, follow, para que os posts sejam indexados e as listas não.

O problema está no follow. John Mueller, do Google, já disse que uma página que fica em noindex por tempo suficiente sai do índice por completo, e os links dela deixam de ser seguidos; então noindex, follow acaba funcionando como noindex, nofollow. E esses links são o caminho até os seus posts antigos.

Em vez disso: deixe as páginas serem indexadas. Uma página de listagem com doze títulos e resumos de posts não é conteúdo raso, e uma busca pelo tema de um post tem muito mais chance de cair no próprio post do que na lista que aponta para ele. A documentação do Google também diz que as páginas de uma sequência podem ter o mesmo título e a mesma descrição, então não há problema de título duplicado para resolver.

E os filtros?

Tags, categorias, busca e ordenação multiplicam as suas URLs: /blog?tag=react&page=3&q=hooks também é uma página. Nem todas precisam estar no índice, e um rastreador que percorre todas as combinações gasta o tempo dele no seu site do jeito menos útil possível.

Duas opções sensatas:

  • Aponte a canonical das páginas filtradas para a lista sem filtro. É o que eu faço: /blog?tag=react e /blog?tag=react&page=2 declaram /blog como canonical, enquanto as páginas sem filtro apontam para si mesmas. Todo post continua alcançável pela sequência sem filtro, e as combinações não atrapalham.

  • Dê caminhos próprios aos filtros que você quer ranquear. Se uma página de tag é uma landing page por si só, trate-a como uma: em /blog/tag/react, com canonical autorreferente e paginação própria, e deixe os filtros por query string para todo o resto.

As orientações do próprio Google também aceitam noindex em páginas filtradas e reordenadas. Qualquer que seja a escolha, aplique-a aos filtros, e não à paginação da lista principal.

rel="next" e rel="prev"

O Google anunciou em 2019 que não usa mais esses atributos. A documentação dele observa que outros buscadores ainda podem usá-los, mas eles não substituem os links na página.

Quais páginas linkar

Uma barra de paginação com todos os números de página não escala, e uma só com “Anterior” e “Próxima” transforma a página quarenta numa caminhada de quarenta cliques. O meio-termo comum: a primeira página, a última e uma de cada lado da atual, com reticências em cada intervalo.

Plain Text
‹ Anterior   1  …  6  [7]  8  …  15   Próxima ›

O link para a última página leva pessoas e rastreadores direto aos posts mais antigos, e a sequência pode ser percorrida a partir de qualquer ponta. Mesmo assim, a paginação não garante que o rastreador chegue a tudo; para isso existe o sitemap: liste nele todos os posts, com um lastmod tirado da última vez em que o post mudou de forma significativa.

Dois detalhes de acessibilidade cabem no mesmo componente:

  • Envolva a barra num <nav> com um rótulo como “Paginação” e marque a página atual com aria-current="page".

  • Nas pontas, renderize “Anterior” e “Próxima” como texto desativado, e não como links para lugar nenhum ou para a página em que você já está.

Checklist

  • Cada página da lista tem a sua própria URL, e os posts dela estão no HTML renderizado no servidor.

  • A paginação é feita de links <a href>. Um botão “Carregar mais”, se houver, complementa esses links em vez de substituí-los.

  • Cada página da lista sem filtro tem uma canonical autorreferente. A página dois não aponta a canonical para a página um.

  • Nada de noindex nas páginas da lista principal.

  • As páginas filtradas e ordenadas apontam a canonical para a lista sem filtro, ou estão em noindex, ou ganharam caminhos próprios, se você quer que elas ranqueiem.

  • O sitemap lista todos os posts.


O componente Pagination do Kookee para React renderiza esse padrão como links: a primeira e a última página, uma de cada lado da atual, reticências, navegação com rótulo e pontas desativadas. Ele funciona a partir de um Server Component e antes de o JavaScript carregar, e getPaginationItems devolve a mesma janela de páginas para a sua própria marcação. Veja Criar um blog com os componentes React para uma página de lista completa com filtros por tag e busca.