Resposta curta
"Nenhuma tag de retorno" (em inglês, no return tags ou missing return links) quer dizer que a página A aponta pra página B como versão em outro idioma, mas a B não aponta de volta pra A. O Google é claro: se duas páginas não apontarem uma para a outra, as tags são ignoradas. A correção é colocar o mesmo conjunto de tags hreflang em todas as versões, cada uma listando a si mesma e todas as outras, com URL absoluta, código de idioma válido (como pt-BR) e um x-default. Site só em português do Brasil não precisa de hreflang.
O que é hreflang, em linguagem simples
Hreflang é um aviso que você dá ao Google dizendo: "esta página tem irmãs em outros idiomas ou pra outros países, e aqui está o endereço de cada uma". Com isso, quem pesquisa em Portugal recebe a versão pt-PT, quem pesquisa no México recebe a versão es-MX, e quem pesquisa no Brasil recebe a pt-BR.
Duas coisas que o hreflang não faz, segundo a própria documentação do Google:
- Não diz ao Google em que idioma a página está. O Google detecta o idioma pelo conteúdo visível, com algoritmos. Ele não usa o hreflang nem o atributo
langdo HTML pra isso. - Não junta as versões como se fossem uma só. As versões localizadas só são tratadas como cópias quando o conteúdo principal não é traduzido (por exemplo, quando só o menu e o rodapé mudam de idioma).
Quando precisa (e quando não precisa)
O Google recomenda indicar as versões alternativas em três situações:
- O conteúdo todo é traduzido pra vários idiomas (português e inglês de cada página, por exemplo).
- O conteúdo é no mesmo idioma, mas muda por região: preço em reais pro Brasil e em euros pra Portugal, frete diferente, termos locais.
- Só o modelo (menu, rodapé) é traduzido e o conteúdo principal fica num idioma só, como em fóruns.
Não precisa se o site tem uma versão só, em português do Brasil. Sem irmãs em outro idioma ou país, não há o que declarar. Colocar hreflang="pt-BR" sozinho, apontando pra própria página, não indica nenhuma alternativa ao Google.
Outra regra que vem antes do hreflang: cada idioma precisa ter a sua própria URL (/en/, en.seusite.com ou outro domínio). O Google desaconselha trocar o idioma por cookie ou pela configuração do navegador na mesma URL, porque o Googlebot costuma rastrear a partir dos EUA e manda as requisições sem o cabeçalho Accept-Language. Na prática, ele só enxerga uma das versões.
As 3 formas de declarar, com exemplos completos
O Google aceita três formas, e diz que elas são equivalentes: tags no HTML, cabeçalho HTTP ou sitemap. Dá pra usar as três ao mesmo tempo, mas não há benefício na Pesquisa, e manter três implementações dá mais trabalho. Escolha uma.
Nos exemplos, o site tem a mesma página em português do Brasil, português de Portugal e inglês, e uma página de escolha de idioma como padrão.
1. Tags no <head> do HTML
É a mais comum. O bloco abaixo vai idêntico no <head> das três versões:
<head>
<title>Tênis de corrida | Loja</title>
<link rel="alternate" hreflang="pt-BR" href="https://seusite.com/br/tenis-de-corrida" />
<link rel="alternate" hreflang="pt-PT" href="https://seusite.com/pt/tenis-de-corrida" />
<link rel="alternate" hreflang="en" href="https://seusite.com/en/running-shoes" />
<link rel="alternate" hreflang="x-default" href="https://seusite.com/" />
</head>As tags precisam estar dentro de um <head> bem formado. Se um script, um <div> ou um <img> perdido aparecer antes delas, o navegador pode fechar o <head> mais cedo e as tags caem no <body>. O Google também pede pra não misturar hreflang com outros atributos, como media, na mesma tag <link>.
2. Cabeçalho HTTP Link
Serve pra arquivos que não são HTML, como PDFs. Cada versão do arquivo responde com o mesmo cabeçalho, listando todas, inclusive ela mesma, separadas por vírgula e com a URL entre < e >:
Link: <https://seusite.com/br/catalogo.pdf>; rel="alternate"; hreflang="pt-BR", <https://seusite.com/pt/catalogo.pdf>; rel="alternate"; hreflang="pt-PT", <https://seusite.com/en/catalog.pdf>; rel="alternate"; hreflang="en"O cabeçalho vai numa linha só: o padrão HTTP atual (RFC 9112) proíbe quebrar um cabeçalho em várias linhas.
3. Sitemap com xhtml:link
Bom pra sites grandes, porque não pesa no HTML. Cada versão ganha o seu próprio <url>, e cada <url> lista todas as versões, inclusive a do próprio <loc>. Não esqueça o namespace xmlns:xhtml na abertura:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://seusite.com/br/tenis-de-corrida</loc>
<xhtml:link rel="alternate" hreflang="pt-BR" href="https://seusite.com/br/tenis-de-corrida"/>
<xhtml:link rel="alternate" hreflang="pt-PT" href="https://seusite.com/pt/tenis-de-corrida"/>
<xhtml:link rel="alternate" hreflang="en" href="https://seusite.com/en/running-shoes"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://seusite.com/"/>
</url>
<url>
<loc>https://seusite.com/pt/tenis-de-corrida</loc>
<xhtml:link rel="alternate" hreflang="pt-BR" href="https://seusite.com/br/tenis-de-corrida"/>
<xhtml:link rel="alternate" hreflang="pt-PT" href="https://seusite.com/pt/tenis-de-corrida"/>
<xhtml:link rel="alternate" hreflang="en" href="https://seusite.com/en/running-shoes"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://seusite.com/"/>
</url>
<url>
<loc>https://seusite.com/en/running-shoes</loc>
<xhtml:link rel="alternate" hreflang="pt-BR" href="https://seusite.com/br/tenis-de-corrida"/>
<xhtml:link rel="alternate" hreflang="pt-PT" href="https://seusite.com/pt/tenis-de-corrida"/>
<xhtml:link rel="alternate" hreflang="en" href="https://seusite.com/en/running-shoes"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://seusite.com/"/>
</url>
</urlset>A ordem dos <xhtml:link> não importa, mas manter a mesma ordem em todos facilita achar erro. Esses elementos filhos não contam no limite de URLs do sitemap. E vale a regra geral: um sitemap só pode listar URLs do diretório onde ele está hospedado. O resto sobre o arquivo está no guia de sitemap XML.
As regras que valem pras três formas
- Cada versão lista a si mesma, além de todas as outras. O conjunto de tags é o mesmo em todas.
- Os links são de ida e volta. Se A cita B, B tem que citar A. O Google explica o motivo: sem isso, qualquer pessoa poderia declarar uma página de outro site como "versão alternativa" da sua.
- URL absoluta, com https. Use
https://seusite.com/en/, nunca//seusite.com/en/nem/en/. - As versões podem estar em domínios diferentes.
seusite.com.breseusite.ptpodem se citar normalmente. - Código válido: idioma no padrão ISO 639-1, país opcional no ISO 3166-1 Alfa 2, separados por hífen.
Códigos de idioma e país pra quem é do Brasil
O primeiro código é sempre o idioma. O segundo, opcional, é o país. O Google não aceita país sozinho e não deduz o idioma a partir do país.
| Código | Pra quem | Quando usar |
|---|---|---|
pt-BR | Português, usuários no Brasil | Quando você tem também uma versão pra Portugal |
pt-PT | Português, usuários em Portugal | Versão com preço em euro, termos de Portugal |
pt | Português, qualquer país | Quando há uma versão só em português |
es | Espanhol, qualquer país | Versão única em espanhol |
es-MX | Espanhol, usuários no México | Versão com preço em peso mexicano |
en | Inglês, qualquer país | Versão única em inglês, ou a genérica |
en-US | Inglês, usuários nos EUA | Versão com preço em dólar e frete pros EUA |
x-default | Quem não bate com nenhuma versão | Seletor de idioma ou versão principal |
Maiúscula importa? Não. O Google diz que o valor do hreflang não diferencia maiúsculas de minúsculas: pt-br e pt-BR funcionam igual. A forma pt-BR, com o país em maiúscula, é só a convenção do padrão ISO, e é a que a gente recomenda por ser mais fácil de ler. O que quebra é o separador: o padrão é hífen, então pt_BR (com sublinhado, o formato de "locale" do WordPress e de muitas bibliotecas) não segue o formato do Google.
Se você tem várias versões no mesmo idioma pra países diferentes, o Google recomenda ter também uma genérica. Com es-MX e es-AR, por exemplo, coloque um es pros outros países de língua espanhola. Pode ser uma das próprias páginas regionais.
Erro por erro: o que a ferramenta diz e como corrigir
1. "Nenhuma tag de retorno" (links de retorno ausentes)
É o primeiro da lista de erros comuns na documentação do Google. A versão em português cita a inglesa, mas a inglesa não cita a portuguesa. Muitas vezes acontece porque a tradução foi publicada depois, ou porque o template de um idioma é diferente do outro.
<!-- errado: em https://seusite.com/br/tenis-de-corrida -->
<link rel="alternate" hreflang="pt-BR" href="https://seusite.com/br/tenis-de-corrida" />
<link rel="alternate" hreflang="en" href="https://seusite.com/en/running-shoes" />
<!-- em https://seusite.com/en/running-shoes: nenhuma tag hreflang -->Corrija colocando o mesmo bloco nas duas:
<!-- certo: igual nas duas páginas -->
<link rel="alternate" hreflang="pt-BR" href="https://seusite.com/br/tenis-de-corrida" />
<link rel="alternate" hreflang="en" href="https://seusite.com/en/running-shoes" />
<link rel="alternate" hreflang="x-default" href="https://seusite.com/br/tenis-de-corrida" />Duas causas menos óbvias do mesmo erro: a página de destino redireciona (o retorno sai de outra URL, não da que você citou), ou o retorno cita a URL com uma diferença pequena, como barra no fim, http no lugar de https ou www a mais. Pra ferramenta, isso é outra página. Se o site tem idiomas demais pra manter tudo, o Google aceita omitir alguns, mas pede que as versões novas tenham ida e volta pelo menos com o idioma principal do site.
2. Falta a autorreferência
A página lista as irmãs, mas esquece dela mesma. A regra do Google é "cada versão de idioma precisa listar a si mesma, além de todas as outras".
<!-- errado: em /br/, só cita a outra -->
<link rel="alternate" hreflang="en" href="https://seusite.com/en/" />
<!-- certo -->
<link rel="alternate" hreflang="pt-BR" href="https://seusite.com/br/" />
<link rel="alternate" hreflang="en" href="https://seusite.com/en/" />3. Código de idioma ou país inválido
Os enganos que mais aparecem pra quem é do Brasil:
| Errado | Por quê | Certo |
|---|---|---|
br | Sozinho é código de idioma, e br é bretão | pt-BR |
pt_BR | Sublinhado em vez de hífen | pt-BR |
en-UK | UK é reservado; o Google ignora essa parte | en-GB |
uk (pra Reino Unido) | uk é o código do ucraniano | en-GB |
es-419 | Não está na ISO 3166-1 Alfa 2, o Google não aceita | es ou um por país (es-MX, es-AR) |
jp | jp é país; o idioma é ja | ja ou ja-JP |
en-EU | EU não é país; o Google ignora | Um código por país, ou só en |
Pra chinês, o Google aceita a escrita no padrão ISO 15924: zh-Hans (simplificado) e zh-Hant (tradicional), com país opcional, como zh-Hans-US.
4. Sem x-default
O x-default diz qual página mostrar pra quem não bate com nenhuma versão: alguém no Japão, com navegador em japonês, num site que só tem português e inglês. Ele foi pensado pra páginas de escolha de idioma ou país e pra páginas iniciais que redirecionam sozinhas, mas pode apontar pra qualquer versão, normalmente a principal. Não leva código de idioma e entra no mesmo bloco das outras tags, em todas as versões:
<link rel="alternate" hreflang="x-default" href="https://seusite.com/" />O Google recomenda o x-default, não obriga. A falta dele não invalida o resto, mas deixa a escolha da versão padrão nas mãos do Google.
5. URL relativa ou sem protocolo
<!-- errado -->
<link rel="alternate" hreflang="en" href="/en/running-shoes" />
<link rel="alternate" hreflang="en" href="//seusite.com/en/running-shoes" />
<!-- certo -->
<link rel="alternate" hreflang="en" href="https://seusite.com/en/running-shoes" />6. Hreflang apontando pra redirect, 404 ou noindex
O hreflang serve pra mandar a pessoa pra uma página que o Google possa mostrar. Se a URL citada redireciona, dá erro ou tem noindex, ela não é essa página: o redirect leva pra outro endereço, o 404 não existe e o noindex pede pra não entrar no índice. Por isso as ferramentas de auditoria tratam esses casos como erro de hreflang: o Screaming Frog tem os avisos Non-200 Hreflang URLs e Noindex Returns Links, e o Ahrefs tem Hreflang to broken page.
A correção é citar sempre a URL final, que responde 200 e é indexável. Se uma tradução foi removida, tire ela do bloco em todas as versões. Pra achar redirects na lista, o verificador de redirect mostra cada salto. Pra noindex escondido, o guia de noindex sem querer mostra onde ele costuma vir.
7. Hreflang apontando pra URL que não é canônica
Você cita /en/running-shoes?utm_source=menu, mas o canonical dessa página aponta pra /en/running-shoes. Ou cita a versão com www, e o canonical é sem. O Screaming Frog chama isso de Not Using Canonical. A correção é citar no hreflang exatamente a URL do canonical de cada versão. O Google pede ainda que você não coloque a versão http das páginas no hreflang quando existe a https.
8. Tags fora do <head>
Plugin de chat, pixel ou script de teste A/B injetado no topo pode fechar o <head> antes da hora. O Google sugere colar o HTML renderizado num validador pra confirmar que os <link> estão dentro do <head>. O Screaming Frog aponta esse caso como Outside <head>.
Hreflang e canonical: cada versão aponta pra si mesma
Este é o erro que mais derruba hreflang que "parece certo". O canonical diz qual URL é a principal entre duplicadas. Se a versão em inglês tiver canonical pra versão em português, você está dizendo que a inglesa é só uma cópia, e ela tende a sumir do índice. Aí o hreflang aponta pra uma página que o Google não usa.
<!-- errado: em /en/running-shoes -->
<link rel="canonical" href="https://seusite.com/br/tenis-de-corrida" />
<!-- certo: cada versão é canônica de si mesma -->
<link rel="canonical" href="https://seusite.com/en/running-shoes" />
<link rel="alternate" hreflang="pt-BR" href="https://seusite.com/br/tenis-de-corrida" />
<link rel="alternate" hreflang="en" href="https://seusite.com/en/running-shoes" />A documentação de canonização do Google diz que, ao usar hreflang, a canônica deve estar no mesmo idioma (ou no melhor substituto, se não houver página nesse idioma). Ela também diz que o Google prefere, na hora de escolher a canônica, URLs que fazem parte de um conjunto hreflang com ida e volta. E um detalhe de sintaxe: rel="canonical" com atributo hreflang não é usado na canonização. Pra versões alternativas, use rel="alternate".
Há um caso em que o canonical entre versões faz sentido: duas URLs no mesmo idioma com conteúdo praticamente igual, como seusite.pt/ e seusite.com/pt/. Aí o Google pede que você escolha uma preferida com canonical e use o hreflang pra indicar a versão regional. Pra conferir o canonical de cada versão, use a ferramenta verificar canonical.
Onde esse erro aparece hoje
Muito tutorial antigo manda abrir o relatório Segmentação internacional do Search Console. Ele não existe mais. A página de ajuda do Google diz que o relatório foi descontinuado e que o Google continua usando as tags hreflang, mas que a segmentação por país do Search Console foi considerada de pouco valor e não é mais compatível. A página de ajuda não indica um relatório que tenha substituído esse.
Por isso, hoje o aviso de "nenhuma tag de retorno" vem de ferramentas de auditoria que rastreiam o site, cada uma com o seu nome:
| Ferramenta | Nome do erro de retorno | Outros avisos de hreflang |
|---|---|---|
| Screaming Frog | Missing Return Links | Non-200 Hreflang URLs, Not Using Canonical, Missing Self Reference, Missing X-Default, Incorrect Language & Region Codes |
| Ahrefs (Site Audit) | Missing reciprocal hreflang (no return-tag) | Hreflang annotation invalid, Self-referencing hreflang annotation missing, Hreflang to broken page, More than one page for same language in hreflang |
Se a mensagem aparece traduzida como "nenhuma tag de retorno", é o mesmo problema nas duas. A comparação entre as ferramentas está em Varrida x Screaming Frog e Varrida x Ahrefs.
Como fazer em cada plataforma
Next.js (App Router)
Use alternates.languages no metadata ou no generateMetadata. O Next gera as tags <link rel="alternate" hreflang> no <head>. Com metadataBase no layout raiz, dá pra usar caminhos relativos, e o Next monta a URL absoluta. A chave x-default é aceita nos tipos do Next:
import type { Metadata } from "next";
const PATHS = { "pt-BR": "/br/tenis-de-corrida", "pt-PT": "/pt/tenis-de-corrida", en: "/en/running-shoes" };
type Props = { params: Promise<{ lang: keyof typeof PATHS }> };
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { lang } = await params; // "pt-BR", "pt-PT" ou "en"
return {
alternates: {
canonical: PATHS[lang],
languages: { ...PATHS, "x-default": PATHS["pt-BR"] },
},
};
}Repare que o canonical muda com o idioma (cada versão aponta pra si mesma) e o bloco de idiomas é o mesmo em todas. No app/sitemap.ts, o campo equivalente é alternates.languages em cada entrada. Atenção: o exemplo da documentação do Next lista só os outros idiomas; inclua também o idioma da própria URL, que é o que o Google pede. Uma última conferência: em páginas com generateMetadata dinâmico, o Next pode enviar os metadados depois, no fim do <body>, e diz que o Googlebot interpreta isso corretamente. Como o Google pede as tags no <head>, confira com curl onde elas saem no seu site. Pra forçar tudo no <head>, o Next documenta a opção htmlLimitedBots: /.*/ no next.config, que desliga esse envio atrasado (a resposta pode ficar mais lenta).
WordPress: WPML e Polylang
WPML. A documentação diz que o WPML insere as tags hreflang automaticamente e atualiza quando você muda o site. Pra apontar uma região (por exemplo, pt-BR em vez de só pt), vá em WPML › Settings › Languages, clique em Edit na linha do idioma e preencha o campo hreflang. O próprio WPML avisa que tenta ajustar o formato, mas não consegue alertar se o código for inválido, então confira com a tabela acima. A documentação não diz se o WPML gera o x-default sozinho: veja no código-fonte se ele aparece.
Polylang. Também gera as tags sozinho, usando o locale do WordPress e trocando o sublinhado por hífen (pt_BR vira pt-BR). Segundo o Polylang, o x-default só sai na página inicial, e só quando ela redireciona pro idioma, o que depende da opção de URL em Languages › Settings › URL modifications. Pra ter x-default nas outras páginas, o Polylang mostra um filtro em PHP (pll_rel_hreflang_attributes).
Nos dois casos, a causa mais comum de "nenhuma tag de retorno" é página sem tradução ligada: o plugin só gera o par quando as duas versões estão conectadas como tradução uma da outra.
Shopify Markets
A central de ajuda da Shopify diz que, com os mercados configurados com domínios e idiomas, as tags hreflang são geradas automaticamente, incluindo um x-default pro domínio principal. Cada versão de mercado recebe um canonical pra si mesma, e o sitemap inclui as URLs de cada mercado com as anotações hreflang. O redirecionamento automático por país vale pra clientes, mas exclui os robôs dos buscadores. Existe uma opção pra desligar o hreflang automático nas preferências da loja virtual (Online Store › Preferences, no admin em inglês), e a Shopify avisa que desligar pode prejudicar o SEO. Se o app de tradução também gera hreflang, você pode acabar com tags duplicadas: confira no código-fonte.
Como conferir com curl
Pra ver o bloco de uma página (o tr junta as linhas, porque muita gente quebra a tag em várias):
curl -s https://seusite.com/br/tenis-de-corrida | tr -d '\n' | grep -io '<link[^>]*hreflang[^>]*>'Pra testar o retorno de cada versão citada, com o código de status:
links() { curl -sL "$1" | tr -d '\n' | grep -io '<link[^>]*hreflang[^>]*>'; }
URL="https://seusite.com/br/tenis-de-corrida"
links "$URL" | grep -o 'href="[^"]*"' | cut -d'"' -f2 | while read -r alt; do
code=$(curl -s -o /dev/null -w "%{http_code}" "$alt")
if links "$alt" | grep -qF "href=\"$URL\""; then volta="volta ok"; else volta="SEM RETORNO"; fi
echo "$code $volta $alt"
doneCada linha precisa mostrar 200 e volta ok. Um 301 diz que você está citando uma URL que redireciona; SEM RETORNO é exatamente o erro das ferramentas. O script compara a URL ao pé da letra, então uma barra a mais no fim também aparece como falta de retorno, e é bom que apareça.
Pra cabeçalho HTTP, canonical e noindex das versões:
curl -sI https://seusite.com/br/catalogo.pdf | grep -i '^link:'
curl -s https://seusite.com/en/running-shoes | tr -d '\n' | grep -io '<link[^>]*canonical[^>]*>'
curl -sI https://seusite.com/en/running-shoes | grep -i 'x-robots-tag'Pra sitemap, conte quantos xhtml:link existem e confira se o namespace está declarado:
curl -s https://seusite.com/sitemap.xml | grep -o '<xhtml:link' | wc -l
curl -s https://seusite.com/sitemap.xml | grep -o 'xmlns:xhtml="[^"]*"'Se o número de xhtml:link não for o número de URLs vezes o número de versões, alguma entrada está incompleta. Pra validar o resto do arquivo, use o validador de sitemap.
Checklist final
- Cada idioma ou país tem a sua URL.
- Todas as versões têm o mesmo bloco, e cada uma cita a si mesma.
- Toda URL citada é absoluta, https, responde 200, não tem noindex e é a canônica.
- Cada versão tem canonical pra si mesma, no próprio idioma.
- Os códigos são ISO: idioma primeiro, país depois, com hífen.
- Existe um
x-default. - Você usa uma forma só (HTML, cabeçalho ou sitemap).
O hreflang costuma quebrar sem ninguém perceber: uma tradução nova que não ganhou o par, um deploy que trocou o template. A varredura grátis da Varrida lê o hreflang de cada página e avisa quando falta o x-default, junto com canonical, redirects e noindex. A ida e volta entre as versões, confira com o script de curl acima.


