Googlebot e JSON-LD: uma só passagem de unescape
PT-PT

Googlebot e JSON-LD: uma só passagem de unescape

Última verificação: 30 de agosto de 2026
12 min de leitura
Guia
PageSpeed 100/100
500+ projetos WP

A Google deixou de reparar os seus dados estruturados. A extração de JSON-LD aplica agora uma só passagem de unescaping de HTML, por isso um bloco que antes era endireitado em silêncio simplesmente não faz parse e desaparece. Não há erro na Search Console, não há aviso, há apenas um resultado enriquecido que deixa de aparecer. Este texto mostra como medir o seu corpus em poucos minutos em vez de adivinhar, de onde vem essa escrita no WordPress e porque uma auditoria pontual não chega. A nossa própria medição sobre 68 055 blocos está aqui dentro, com o script.

#O que a Google mudou de facto

A declaração é curta e merece citação integral, porque tudo o resto decorre de uma frase:

To bring our parser up to JSON and other standards, we changed our JSON-LD extraction and are now only applying a single pass of HTML unescaping

Gary Illyes acrescentou onde está definida a correção: RFC 8259, a especificação do JSON. Não é uma recomendação de SEO, é a referência a uma norma que qualquer parser de JSON segue.

A consequência prática vem igualmente curta: as entidades com duplo escape, como & ou ✔, deixam de ser desdobradas. Antes o parser fazia uma passagem extra e endireitava aquilo. Agora faz uma passagem e fica com texto que não é JSON válido.

Vale nomear desde já o que falta nesta informação. Não há data de lançamento. Não há ligação para documentação atualizada da Google. A fonte é uma publicação no LinkedIn, noticiada pelo Search Engine Roundtable a 21 de agosto de 2026. Trate-a como um estado descrito pela Google e não como uma especificação que possa colocar diante de um cliente.

#O que é o duplo escape e de onde vem

Veja um caso simples: o nome de empresa «Silva & Filhos» no campo name de um bloco JSON-LD.

escrito comoo que o parser de JSON vêestado
"Silva & Filhos"Silva & Filhosválido, o JSON não exige escapar o E comercial
"Silva & Filhos"Silva & Filhosválido, escape universal
"Silva & Filhos"Silva & Filhosfaz parse, mas o valor está errado
"Silva & Filhos"Silva & Filhosisto é duplo escape

Um E comercial sozinho não rebenta o bloco, porque o JSON não exige escapá-lo. O grave começa nas aspas. Se o template escrever " onde devia estar \", depois de uma passagem sobra " e não umas aspas. A string não fecha e o bloco deixa de ser JSON.

De onde vem isto no WordPress? Quase sempre de processar duas vezes o mesmo valor. O conteúdo passa por esc_html() ao gravar, por um filtro do tema ao apresentar, e acaba num campo JSON-LD que teria escapado bem por si próprio. Cada passo isolado está certo. Compostos, produzem uma escrita que funcionou durante anos apenas porque a Google a endireitava por nós.

#Como verificar o seu corpus em cinco minutos

A regra mais importante: verifica-se o HTML construído, não a fonte do template. Na fonte parece tudo bem, porque o escape é acrescentado na saída. Se publica um build estático, analisa o diretório de saída. Num WordPress clássico, puxa uma amostra de URLs com wget ou curl e analisa o que o servidor respondeu.

A verificação em si são pouco mais de dez linhas. Extraia cada bloco <script type="application/ld+json">, tente fazer parse e procure à parte o padrão de entidade dupla:

const RE = /<script[^>]*type=["']application\/ld\+json["'][^>]*>([\s\S]*?)<\/script>/gi;
let m;
while ((m = RE.exec(html))) {
  const body = m[1];
  if (/&amp;(quot|amp|lt|gt|#\d+);/.test(body)) report("entidade dupla", file);
  try { JSON.parse(body); } catch (e) { report("não faz parse: " + e.message, file); }
}

Dois testes separados, porque apanham coisas diferentes. O JSON.parse falha numa string partida, mas aceita sem problema &amp;amp; dentro de um valor que continua a ser JSON válido e apenas contém lixo. O teste do padrão apanha precisamente esse segundo caso: o bloco faz parse e no resultado enriquecido aparece &amp; onde devia estar um carácter.

Um terceiro teste que vale a pena juntar são as entidades HTML simples nos valores. Não são um erro, mas depois da mudança passam a ser desdobradas exatamente uma vez, pelo que o resultado pode diferir do que conhecia. Mais vale saber que estão lá.

#A nossa medição: 68 055 blocos, zero falhas

Corremos esta análise sobre o nosso próprio corpus a 30 de agosto de 2026, contra uma versão de produção acabada de construir.

métricaresultado
páginas com pelo menos um bloco JSON-LD15 742
blocos JSON-LD no total68 055
blocos que não fazem parse como JSON0
páginas com entidade de duplo escape0
páginas com entidade HTML simples dentro do JSON-LD0

Zero nas três categorias. Não escrevemos isto como gabarolice, mas como informação sobre o que este resultado significa e o que não significa. A nossa stack gera dados estruturados a partir do frontmatter através de componentes Astro e insere-os com o padrão set:html={JSON.stringify(...)}. O JSON.stringify produz JSON válido por definição e o set:html não acrescenta escape de HTML próprio. Por outras palavras: não tivemos zero por sermos cuidadosos, tivemos porque aquele padrão em concreto não tem forma de produzir duplo escape.

Isso importa mais do que o número. Se a sua stack monta o JSON-LD concatenando strings no template, ou através de um plugin que cola um campo de conteúdo dentro de JSON já preparado, o risco é real e o seu resultado será outro. Meça o seu, não copie o nosso.

#Onde parte mais vezes no WordPress

Das auditorias que fazemos em clientes saem três origens recorrentes.

A primeira é um plugin de SEO que preenche description a partir de um campo que já passou por wp_kses ou esc_attr. Costuma partir no apóstrofo e nas aspas, e em português juntam-se ainda as aspas angulares que muitos sistemas editoriais inserem automaticamente.

A segunda é um bloco JSON-LD escrito à mão e colado em header.php ou nas opções do tema, onde os valores entram com echo e sem wp_json_encode. É a variante habitual em temas feitos por medida há alguns anos e a mais difícil de encontrar, porque não aparece em nenhum ecrã de plugin.

A terceira é um construtor de páginas que guarda o conteúdo com entidades HTML já na base de dados. Nessa altura até um gerador de JSON-LD bem escrito recebe texto com &amp; à entrada e codifica-o obedientemente uma segunda vez.

O denominador comum é sempre o mesmo: um valor escapado duas vezes, uma para HTML e outra para JSON, por duas camadas que não sabem uma da outra.

#Como codificar isto bem

A regra é inequívoca porque existe uma norma para ela. Dentro de um valor JSON escapa-se à maneira do JSON e não à maneira do HTML.

Em PHP isso significa wp_json_encode() sobre a estrutura toda, nunca strings montadas à mão. Em JavaScript, JSON.stringify(). Num template Astro, o padrão que usamos:

<script type="application/ld+json" set:html={JSON.stringify(schema)} />

Se precisar mesmo de um carácter capaz de fechar o bloco de script antes do tempo, use um escape universal. & e < são seguros em qualquer parser de JSON e não exigem conhecimento de HTML a quem lê os dados.

O que não fazer: não coloque uma entidade HTML dentro de um valor JSON à espera que alguém a desdobre. Durante anos esse alguém foi a Google. A partir de agora desdobra exatamente uma vez, e qualquer outro consumidor dos seus dados estruturados, do Bing a um assistente de IA, nunca teve essa obrigação.

#Uma auditoria pontual não chega, transforme-a num portão

Esta é a parte que mais se salta. Os dados estruturados não são um texto que se escreve uma vez. São gerados por um template, um plugin ou uma integração, e qualquer atualização pode trazer o escape de volta. Uma auditoria feita hoje fala do build de hoje e de mais nada.

Transformámos a análise num portão que corre depois do build. Lê o diretório de saída, conta blocos, tenta fazer parse de cada um e falha apenas perante um problema real, ou seja, um bloco que não faz parse ou uma entidade dupla. Se o diretório de saída não existir, termina a zero, para não produzir um vermelho falso num ambiente onde ainda ninguém construiu.

Três pormenores decidem se um portão destes vale alguma coisa. Primeiro, tem de ler o artefacto e não a fonte, porque a fonte não prova nada sobre escape. Segundo, tem de contar blocos e mostrar o número, para que alguém repare que cai de sessenta e oito mil para duzentos porque uma integração deixou de os gerar. Terceiro, tem de separar erro de aviso: as entidades HTML simples são reportadas mas não deitam o build abaixo, porque não são uma avaria, são algo que convém saber.

#O que fazer quando a análise encontra alguma coisa

Uma análise dá uma lista de ficheiros, não um diagnóstico. Antes de corrigir seja o que for, descubra que camada produz aquela escrita, porque uma correção no sítio errado volta com a atualização seguinte.

Pegue num URL da lista e veja a resposta crua do servidor, por exemplo com curl -s URL | grep -A5 "application/ld+json". Confirme se o valor danificado vem do título do artigo, da descrição SEO ou de um campo personalizado. Isso aponta a camada mais depressa do que ler código.

Depois decide conforme a origem:

  1. Se o valor vem de um plugin de SEO, verifique se tem dois plugins a gerar o mesmo tipo de schema. Um gerador duplicado causa valores estranhos com mais frequência do que uma falha em qualquer um deles isolado.
  2. Se o bloco está no tema, reescreva-o com wp_json_encode() sobre o array completo. A concatenação manual de strings é aqui o único erro verdadeiro e não admite remendos parciais.
  3. Se as entidades já estão na base de dados porque um construtor de páginas as pôs lá, não corrija no gerador. Descodifique o valor uma vez antes de o passar ao codificador JSON, por exemplo com html_entity_decode() com a flag de aspas e UTF-8 explícito.

O erro clássico é assim:

echo '{"name":"' . esc_html( $title ) . '"}';

O correto é assim:

echo wp_json_encode( array( 'name' => $title ) );

A diferença não está no número de caracteres, está em quem trata do escape. Na primeira versão trata dele uma função de HTML num contexto que não é HTML. Na segunda trata dele um codificador JSON em contexto JSON.

Depois da correção, analise um build novo e não o artefacto antigo. Parece óbvio, e metade dos relatos de «corrigi e continua partido» é uma análise sobre um diretório de saída desatualizado.

#O que perde mesmo se ignorar

Perder schema não dói de imediato, e é isso o pior. Não há queda de posições de um dia para o outro, há um desaparecimento gradual daquilo que destacava o resultado: estrelas de avaliação, dados de produto, uma lista de perguntas frequentes, migalhas de navegação. O efeito vê-se na taxa de cliques e não na posição, e a taxa de cliques desce devagar e é fácil atribuí-la a outra coisa.

O segundo destinatário destes dados é mais recente e menos tolerante. Os motores de resposta leem dados estruturados porque é a via mais barata para estabelecer do que trata uma página sem interpretar o texto todo. No nosso site o tráfego de agentes já é mensurável e não é marginal: na ordem de cem visitas por dia, dois terços através do nosso próprio endpoint MCP. Esses sistemas não têm motivo para reparar o escape alheio. A Google reparou-o durante anos por cortesia para com a web que encontrou. Um consumidor novo dos seus dados nunca teve esse hábito.

A terceira camada é a Search Console, e aqui convém dizer o que não vai ficar a saber. Os relatórios de resultados enriquecidos mostram uma queda de elementos válidos, mas não dizem «este bloco não fez parse por causa de uma entidade dupla». Vê que faltam elementos e terá de descobrir porquê sozinho. É por isso que a análise do seu lado vale esses minutos: dá a causa e não apenas o sintoma.

#O que não sabemos e o que fazer mesmo assim

Não conhecemos a data de lançamento. Não sabemos se a mudança atinge todos os tipos de schema por igual, nem se a Search Console chega a reportar uma entidade perdida em vez de simplesmente deixar de mostrar o resultado enriquecido. Não há documentação atualizada para onde remeter um cliente. São lacunas reais e é melhor dizê-lo do que dar a uma publicação no LinkedIn a categoria de especificação.

Apesar das lacunas, a decisão operacional é simples e não depende de nenhuma das informações em falta. O JSON válido já era válido quando a Google corrigia os erros por si. Analise o seu HTML construído, repare o que não faz parse, troque as entidades HTML dos valores por escapes JSON e ancore o teste no processo para que não volte. Se o resultado der zero, como o nosso, também isso é um resultado: sabe que o seu gerador não tem forma de produzir esta falha e deixa de pensar nisso a cada atualização de plugin.

O maior risco desta história não está na mudança, está em ela ser silenciosa. Não chega nenhum alerta. O resultado enriquecido deixa simplesmente de aparecer e, três meses depois, um relatório mostra uma queda de visibilidade sem causa evidente. Cinco minutos de análise hoje saem mais baratos do que essa investigação.

Próximo passo

Transforme o artigo numa implementação real

Este bloco reforça a ligação interna e conduz o leitor para o passo seguinte mais útil dentro da arquitetura do site.

Quer implementar isto no seu site?

Se a visibilidade no Google e em sistemas de IA importa, posso estruturar conteúdo, FAQ, schema e linkagem interna para SEO, GEO e AEO.

Cluster relacionado

Explorar outros serviços WordPress e base de conhecimento

Reforce o seu negócio com suporte técnico profissional em áreas-chave do ecossistema WordPress.

FAQ do artigo

Perguntas frequentes

Respostas práticas para aplicar o tema na execução real.

SEO-readyGEO-readyAEO-ready5 Q&A
O que mudou exatamente a Google na extração de JSON-LD?#
A Google aplica agora uma só passagem de unescaping de HTML em vez de reparar conteúdo com duplo escape. Nas suas palavras: „we changed our JSON-LD extraction and are now only applying a single pass of HTML unescaping”. As entidades com duplo escape, por exemplo um E comercial escrito como &amp; em vez de &, deixaram de ser desdobradas.
O meu site é afetado?#
Só se um bloco JSON-LD contiver mesmo duplo escape ou não fizer parse como JSON. Isso verifica-se no HTML construído e não na fonte do template. Analisámos 68 055 blocos em 15 742 páginas e encontrámos zero casos, mas é o resultado de uma stack concreta e não uma garantia para a sua.
Como codifico bem um E comercial ou um carácter especial?#
Segundo a RFC 8259, ou seja, com escape padrão de JSON, ou com um escape universal como \u0026. Não com uma entidade HTML e muito menos com uma entidade escapada uma segunda vez. Gary Illyes remete diretamente para a RFC 8259 como definição do escape correto.
A partir de quando vale a mudança?#
A Google não indicou data de lançamento. A declaração surgiu no LinkedIn e o artigo do Search Engine Roundtable tem data de 21 de agosto de 2026. Também não há ligação para documentação atualizada, portanto trate isto como um estado reportado pela Google e não como uma especificação.
Basta uma auditoria pontual?#
Não. Os dados estruturados são gerados por um template, um plugin ou uma integração, e qualquer atualização pode trazer o escape de volta. Vale mais integrar a verificação de cada bloco JSON-LD como um portão depois do build, para que uma regressão falhe em voz alta em vez de apagar o schema em silêncio.

Precisa de FAQ adaptado ao setor e mercado? Criamos uma versão alinhada com os seus objetivos de negócio.

Fale connosco

Artigos Relacionados

Limpeza de conteúdo AI-slop

Diagnóstico YMYL para sites WordPress: como encontrar estatísticas falsas, citações fabricadas, páginas duplicadas de IA, datas erradas e biografias inventadas antes de prejudicarem confiança, conformidade ou citações em IA.