Verifique a consistência e a reciprocidade do hreflang
Os grupos hreflang só funcionam de forma confiável quando cada página participante declara o mesmo conjunto completo de alternativas, incluindo uma autorreferência.
Executar grátis
Este verificador compara mapeamentos coletados em várias páginas e revela grupos incompletos sem acessar nenhuma URL. Ele forma o conjunto esperado com todas as URLs de origem e destino, confere cada origem e informa exatamente quais links faltam em cada página. O resultado é determinístico e adequado para lançamentos, migrações e controles recorrentes de SEO.
Por que grupos recíprocos completos são importantes
Uma anotação hreflang não é apenas uma recomendação de mão única entre duas páginas. Ela descreve a participação em um grupo de páginas equivalentes por idioma ou região, e cada página deve publicar o mesmo conjunto de destinos, inclusive ela própria. Se a página em inglês cita as alternativas francesa e alemã, mas a francesa cita somente a inglesa, o grupo está incompleto, embora várias tags isoladas pareçam corretas. Os mecanismos de busca podem ignorar relações sem confirmação, exibir a versão linguística errada ou enfraquecer o sinal regional pretendido. A revisão manual fica pouco confiável à medida que o grupo cresce, pois o número de relações aumenta rapidamente. Em um grupo de quatro páginas, cada uma precisa declarar os quatro destinos: são dezesseis relações entre origem e destino. Este verificador transforma a comparação visual em um teste exato de conjuntos. A consistência só é confirmada quando cada página representada declara todas as páginas do grupo, deixando explícitas as omissões e autorreferências ausentes.
Como preparar e interpretar os mapeamentos
Envie um registro para cada declaração hreflang observada. page_url identifica a página que contém a tag, language registra o valor da tag e target_url indica o destino. Inclua registros de todas as páginas que devem integrar o grupo. O verificador deriva o grupo esperado da união das URLs de origem e destino. Assim, se uma página for citada pelas páginas irmãs, mas não fornecer declarações próprias, ela continuará no conjunto esperado e será indicada como ausente em todos os destinos. As URLs são comparadas como textos exatos após a remoção de espaços externos; portanto, sua coleta deve usar a forma absoluta canônica emitida pelas páginas. A saída traz um resumo por página e uma lista de conflitos. Uma página incompleta inclui missing_urls com os destinos exatos a acrescentar. consistent só será verdadeiro quando a lista de conflitos estiver vazia. Declarações duplicadas não criam uma falsa completude, porque os destinos são comparados como um conjunto.
Uso em lançamentos, migrações e auditorias recorrentes
O melhor momento para verificar a reciprocidade é antes que os rastreadores encontrem uma publicação multilíngue. Exporte as declarações hreflang das páginas renderizadas, converta-as em registros e interrompa a publicação quando consistent for falso. Você detectará ramificações de template que omitem a página atual, lançamentos regionais que atualizam somente o novo mercado e migrações em que uma localidade ainda emite URLs antigas. A verificação também funciona após a inclusão ou retirada de idiomas. Como o algoritmo não faz solicitações de rede, ele não prova que o destino responde, é canônico ou possui conteúdo equivalente; isso exige rastreamento e análise editorial separados. Sua promessa é específica: verificar se cada página representada lista todas as demais e também a si própria. As solicitações à API usam o preço-base publicado de US$ 0,002, enquanto o navegador executa localmente a mesma comparação pura. Guarde os conflitos com as evidências da implantação para associar cada correção a uma origem e a um destino precisos.
Casos de uso
Validar um lançamento multilíngue
Confira se cada nova localidade e cada página irmã existente publicam o conjunto completo de alternativas antes do lançamento.
Auditar uma migração de plataforma
Compare os mapeamentos dos novos templates e encontre páginas que perderam autorreferências ou links de retorno durante a migração.
Proteger um pipeline de SEO
Transforme um grupo inconsistente em uma falha determinística com as relações exatas ausentes entre origem e destino.
Perguntas frequentes
O que torna um grupo hreflang consistente?
Cada URL representada precisa declarar todas as URLs do grupo, inclusive ela própria. O resultado só será verdadeiro quando todas as relações existirem.
O verificador acessa as páginas?
Não. Ele apenas compara os mapeamentos fornecidos e não verifica status HTTP, tags canônicas nem conteúdo.
Como páginas de origem ausentes são detectadas?
O grupo esperado reúne URLs de origem e destino. Uma URL presente apenas como destino é indicada como página sem declarações.
Declarações duplicadas são conflitos?
Elas não alteram a completude. Os destinos são comparados como conjunto, mas a contagem mantém todos os registros enviados.
As variantes de URL são normalizadas?
Não. As URLs são comparadas exatamente após retirar espaços externos. Normalize esquema, host, caminho e barra final antes do envio.
Quanto custa uma solicitação à API?
Cada solicitação usa o preço-base publicado de US$ 0,002. A comparação não utiliza rede nem modelos.
Para desenvolvedores — acesso via API
Tudo nesta página está disponível via API. Esta seção é para equipes que querem integrar a ferramenta aos próprios sistemas; quem não precisa disso pode simplesmente usar a ferramenta acima.
Endpoint
Autenticação por token Bearer. Um único POST coloca a tarefa na fila; o resultado chega por webhook ou link assinado.
Chame do seu código
curl -X POST https://api.kit.forhosting.com/seo/hreflang-conflict-check \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"mappings":[{"page_url":"https://example.com/en","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/en","language":"fr","target_url":"https://example.com/fr"},{"page_url":"https://example.com/fr","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/fr","language":"fr","target_url":"https://example.com/fr"}]}'const res = await fetch("https://api.kit.forhosting.com/seo/hreflang-conflict-check", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"mappings": [
{
"page_url": "https://example.com/en",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/en",
"language": "fr",
"target_url": "https://example.com/fr"
},
{
"page_url": "https://example.com/fr",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/fr",
"language": "fr",
"target_url": "https://example.com/fr"
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/seo/hreflang-conflict-check",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"mappings": [
{
"page_url": "https://example.com/en",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/en",
"language": "fr",
"target_url": "https://example.com/fr"
},
{
"page_url": "https://example.com/fr",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/fr",
"language": "fr",
"target_url": "https://example.com/fr"
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/seo/hreflang-conflict-check", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"mappings":[{"page_url":"https://example.com/en","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/en","language":"fr","target_url":"https://example.com/fr"},{"page_url":"https://example.com/fr","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/fr","language":"fr","target_url":"https://example.com/fr"}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"mappings":[{"page_url":"https://example.com/en","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/en","language":"fr","target_url":"https://example.com/fr"},{"page_url":"https://example.com/fr","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/fr","language":"fr","target_url":"https://example.com/fr"}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/seo/hreflang-conflict-check", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Exemplo de requisição
{
"mappings": [
{
"page_url": "https://example.com/en",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/en",
"language": "fr",
"target_url": "https://example.com/fr"
},
{
"page_url": "https://example.com/fr",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/fr",
"language": "fr",
"target_url": "https://example.com/fr"
}
]
}Exemplo de resposta
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "seo.hreflang_conflict_check",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}A API é assíncrona: cada chamada devolve um task_id na hora. Se preferir polling, consulte o status a até 1 requisição por segundo.
Preço
Preço publicado, sem tokens nem créditos escondidos. Tarefa que falha não é cobrada.
Erros
| HTTP | Código | O que significa |
|---|---|---|
401 | unauthorized | Token ausente ou inválido. Confira o header Authorization. |
402 | insufficient_balance | Saldo insuficiente para esta tarefa. Faça uma recarga e tente de novo. |
404 | unknown_type | Esse tipo de tarefa não existe. Confira o campo type no catálogo. |
429 | rate_limited | Muitas requisições em pouco tempo. Espere um instante e tente de novo. |