O marketing de afiliados é um modelo comercial legítimo. No WordPress, o problema raramente é o modelo - é a implementação. Plugins de cloaking a injetar CSS e JS em todas as páginas, rel em falta, redirecionamentos em JavaScript e canonicals a apontar para URLs de rede de afiliados são o padrão que vemos em auditorias.
Este guia cobre a camada técnica: rel="sponsored", cloaking de URL sem bloat, redirecionamentos (servidor vs JS), Core Web Vitals, higiene de canonical e divulgação. Não é um tutorial de “como ganhar comissões”. É a checklist que um programador WordPress aplica antes de publicar um post de review com dez links de parceiro.
O padrão rel=“sponsored”
Desde 2019 a Google Search Central documenta que links pagos, de patrocínio e de afiliados devem ser qualificados. O atributo certo é rel="sponsored". rel="nofollow" continua a ser aceite como fallback, mas deixa de ser o sinal específico para relações comerciais.
A documentação de outbound links deixa isto explícito: se o destino é pago ou afiliado, marca-o. Misturar nofollow e sponsored no mesmo rel é permitido; o crawler lê o conjunto. Em sites de review portugueses e brasileiros a falha mais comum que vemos é o oposto - links limpos, sem qualquer qualificação, gerados por um shortcode de plugin que só injeta target="_blank".
<!-- Mau: sem qualificação -->
<a href="https://shareasale.com/r.cfm?u=123">Ver oferta</a>
<!-- Aceitável como fallback -->
<a href="https://shareasale.com/r.cfm?u=123" rel="nofollow">Ver oferta</a>
<!-- Padrão recomendado em 2026 -->
<a href="https://shareasale.com/r.cfm?u=123"
rel="sponsored noopener noreferrer"
target="_blank">Ver oferta</a>noopener e noreferrer não são SEO. São higiene de segurança quando abres o destino noutro separador (target="_blank"). Sem noopener, a página de destino pode aceder a window.opener. Sem noreferrer, o cabeçalho Referer pode vazar o teu URL completo para a rede de afiliados - por vezes desejável para atribuição, por vezes não. Decide de forma consciente; não copies o atributo por hábito.
Onde o atributo se perde
Três sítios frequentes:
- Editores de blocos e shortcodes - o bloco de botão do tema ou um shortcode antigo gera
<a>sem filtro. Audita o HTML renderizado, não o Gutenberg. - Tabelas de comparação - HTML colado à mão nos posts. Um único
relem falta numa tabela com oito CTAs basta para inconsistência. - Widgets e footers - banners de parceiro no
footer.phpou num widget de HTML personalizado. O corpo do artigo pode estar correto e o rodapé a enviar links limpos.
Filtro mínimo em PHP para forçar o atributo em URLs conhecidos de redes:
add_filter('the_content', function (string $content): string {
$networks = ['shareasale.com', 'awin1.com', 'amazon.es', 'amazon.com.br'];
foreach ($networks as $host) {
$content = preg_replace_callback(
'#<a\s([^>]*href=["\'][^"\']*' . preg_quote($host, '#') . '[^"\']*["\'][^>]*)>#i',
static function (array $m): string {
$tag = $m[1];
if (stripos($tag, 'rel=') === false) {
return '<a ' . $tag . ' rel="sponsored noopener noreferrer">';
}
if (stripos($tag, 'sponsored') === false) {
$tag = preg_replace(
'/rel=(["\'])([^"\']*)\1/i',
'rel=$1$2 sponsored$1',
$tag,
1
);
}
return '<a ' . $tag . '>';
},
$content
);
}
return $content;
}, 20);Isto não substitui revisão editorial. É uma rede de segurança para hosts que já controlas.
Cloaking de URL versus cloaking de conteúdo
“Cloaking” no jargão de afiliados costuma significar só isto: transformar https://shareasale.com/r.cfm?u=123&b=456 em https://oteusite.pt/go/hosting. É cloaking de URL - um atalho próprio que redireciona para o destino real.
A Google Search Central, nas spam policies, descreve outro cloaking: mostrar conteúdo diferente ao utilizador e ao Googlebot. Isso é spam. Confundir os dois termos é o erro que leva a implementações perigosas (servir HTML limpo ao bot e página cheia de afiliados ao browser).
Regras práticas:
- Permitido e útil:
/go/produto→ 301/302 para o URL de afiliado, com o mesmo destino para todos os user-agents. - Proibido: HTML sem links de afiliado para o Googlebot e HTML com links para humanos; ou
User-Agenta decidir o destino do redirect. - Cinzento arriscado: páginas de “hop” com pouco texto e um único botão “continuar”. Se a hop page for indexável e thin, o problema deixa de ser o redirect e passa a ser qualidade de página.
Precisas de um plugin de cloaking?
ThirstyAffiliates, Pretty Links e similares resolvem gestão de links no admin. O custo típico: CSS/JS global, queries extra, e por vezes endpoints REST desnecessários em cada request.
Se a tua lista de links cabe numa dezena ou duas, redirecionamentos nativos batem qualquer plugin em latência: o PHP do WordPress nem arranca.
Nginx:
location = /go/hosting {
return 302 https://exemplo-rede.pt/click?id=SEU_ID;
}Apache (.htaccess):
Redirect 302 /go/hosting https://exemplo-rede.pt/click?id=SEU_IDWordPress via CPT leve (sem assets no frontend):
add_action('init', function (): void {
register_post_type('affiliate_link', [
'public' => true,
'publicly_queryable' => true,
'has_archive' => false,
'rewrite' => ['slug' => 'go', 'with_front' => false],
'show_in_rest' => false,
'supports' => ['title'],
'label' => 'Links afiliados',
]);
});
add_action('template_redirect', function (): void {
if (!is_singular('affiliate_link')) {
return;
}
$url = get_post_meta(get_the_ID(), 'destination_url', true);
if (!is_string($url) || $url === '') {
status_header(404);
exit;
}
// 302 por omissão: podes mudar o destino sem pelejar com cache de 301.
wp_redirect(esc_url_raw($url), 302);
exit;
});Zero CSS. Zero JS. O crawler e o browser veem o mesmo destino.
Escolhe 301 quando o mapeamento for permanente (marca consolidada, URL de rede estável). Escolhe 302/307 quando fores trocar de programa com frequência - browsers e proxies cacheiam 301 com agressividade.
Redirecionamentos em JavaScript
Uma variante popular em “landing pages de oferta” é:
<script>
setTimeout(function () {
window.location.href = 'https://rede-afiliados.exemplo/click?id=1';
}, 800);
</script>Ou um botão que só navega depois de um evento click gerado por um handler opaco. Do ponto de vista de SEO técnico isto falha em vários eixos:
- Rastreio - o Googlebot executa JS, mas redirects baseados em timers, gestos ou condições frágeis são menos fiáveis do que um
LocationHTTP. A documentação de crawling/indexing trata redirects HTTP como o mecanismo claro. - Atribuição - ferramentas de analytics e pixels de conversão perdem o referrer ou o timing do hop.
- Acessibilidade - utilizadores com JS desativado, leitores de ecrã ou bloqueadores ficam sem caminho.
- Spam policies - se o JS servir para esconder o destino real ao crawler e revelá-lo só no browser, estás no território de cloaking de conteúdo.
Padrão seguro: o <a href="https://exemplo.pt/go/produto"> (ou caminho relativo correspondente) aponta para o teu redirect HTTP. O JS, se existir, só reforça UX (scroll, modal de divulgação), nunca substitui o href.
Teste rápido: abre /go/produto com curl -I e confirma HTTP/1.1 302 e o cabeçalho Location. Se o curl devolver 200 com um HTML que “só redireciona no browser”, corrige.
Core Web Vitals e page experience
A page experience da Google Search Central inclui Core Web Vitals (LCP, INP, CLS) como sinais de experiência. Sites de afiliados costumam falhar aqui por razões previsíveis:
- LCP - hero com imagem enorme + script do plugin de cloaking + pixel de cada rede no
<head>. - INP - handlers de click em CTAs que passam por três camadas de JS antes do navigate.
- CLS - banners de afiliado injectados tarde, sticky bars de “oferta a expirar”, embeds de comparadores.
Impacto prático medido em projetos WordPress de review: remover um plugin de links que enfileirava ~40 KB de JS unused em todas as rotas baixou o LCP móvel em páginas de artigo sem alterar o conteúdo editorial. O ganho não veio de “otimizar imagens outra vez” - veio de deixar de pagar o custo global do cloaking.
Checklist mínima para stacks de afiliados:
- Carrega pixels e tags de rede só nas rotas onde há conversão a medir (thank-you / outbound hop), não no arquivo do blog.
- Prefere redirect nativo a shortcode que imprime botão com CSS próprio.
- Reserva
loading="lazy"para imagens abaixo da dobra; o LCP candidate não pode ser lazy. - Evita iframes de “widget de melhores ofertas” no topo do artigo - são fábricas de CLS.
- Mede com CrUX / Search Console (page experience) e com um perfil móvel real, não só Lighthouse desktop.
Velocidade não “gera rankings” sozinha. Mas num nicho de afiliados onde dezenas de sites comparam o mesmo produto, perder INP e LCP é entregar a sessão ao concorrente que abre a oferta em menos milissegundos.
Higiene de canonical
A canonicalização na Search Central responde a uma pergunta: qual URL é a versão principal deste conteúdo? Em sites de afiliados a higiene parte-se em padrões repetidos.
Canonical a apontar para o destino de afiliado
Alguns plugins SEO ou temas mal configurados ler o primeiro outbound e escrevem:
<link rel="canonical" href="https://rede-afiliados.exemplo/click?id=99" />Isso diz ao Google que a página “canónica” é a hop da rede - não o teu artigo. Corrige para o permalink do post.
Parâmetros UTM e IDs de clique na canónica
URLs partilhados com ?utm_source=newsletter&ref=partner não devem tornar-se canónicos. A canónica é o URL limpo do artigo. Os parâmetros ficam na barra do browser e no analytics; o <link rel="canonical"> ignora-os.
Paginação e variantes de “melhor X 2026”
Se publicas /melhor-vpn/ e /melhor-vpn-2026/ com texto quase igual e links de afiliado diferentes, escolhe uma canónica ou consolida. Canónicas cruzadas entre variantes “ano” sem diferenciação editorial real diluem o sinal.
Páginas /go/ indexáveis
Os endpoints de redirect não devem competir no índice. Opções:
noindex, followna resposta da hop (se devolver HTML por erro).- Preferível: redirect imediato sem corpo indexável + exclusão no
robots.txtsó se tiveres a certeza de que não precisas que o bot descubra os links internos para/go/(na prática, deixa o bot seguir o 302 e não gastes crawl budget em listagens de CPT).
Verifica no HTML do artigo:
<link rel="canonical" href="https://wppoland.com/pt-pt/guia-tecnico-seo-afiliados/" />O valor deve ser o teu domínio e o slug do conteúdo, nunca a rede de afiliados.
Divulgação e conformidade
A camada SEO (rel="sponsored") não substitui a divulgação ao leitor. Em Portugal e na UE, práticas comerciais desleais e regras de publicidade exigem clareza quando há remuneração. Nos EUA, a FTC tem orientação própria para endorsements; se o tráfego for internacional, trata a divulgação como requisito de produto, não como parágrafo jurídico opcional.
Regras de implementação que funcionam em WordPress:
- Visível antes do primeiro link - o disclaimer no fundo do artigo, depois de oito CTAs, falha o teste de “antes da recomendação”.
- Mesmo idioma do artigo - um disclaimer em inglês num post em português europeu é ruído.
- Reutilizável - bloco reutilizável do Gutenberg ou shortcode, para não haver posts “esquecidos”.
add_shortcode('divulgacao_afiliados', function (): string {
return '<aside class="affiliate-disclosure" role="note">'
. '<p>Este artigo contém links de afiliados. Se comprares através '
. 'deles, podemos receber uma comissão - sem custo extra para ti. '
. 'Isso não altera os critérios técnicos da análise.</p>'
. '</aside>';
});No tema ou num padrão de bloco, coloca [divulgacao_afiliados] no topo dos templates de review. Marca tipograficamente os links no corpo (asterisco, nota de rodapé) se a redação o pedir - mas a caixa inicial continua obrigatória.
Não escondas a divulgação em accordion fechado, texto cinza de 10px ou modal que só aparece depois do clique no CTA. Se o objetivo for “cumprir sem mostrar”, estás a otimizar para a auditoria errada.
Checklist de auditoria antes de publicar
Antes de um post de afiliados sair do draft:
- Ver código-fonte: todos os outbounds comerciais têm
relcomsponsored. curl -Iem cada/go/...usado no texto - status 3xx,Locationcorreto, mesmo destino para um UA de browser e um UA de bot.- Nenhum redirect crítico depende só de JavaScript.
- Canonical do artigo = permalink limpo no teu domínio.
- Lighthouse / campo CrUX: não introduziste um novo script global só para gerir links.
- Divulgação visível acima do primeiro CTA.
- CPT ou mapa de redirects documentado (folha interna) para o próximo programador não instalar um plugin “temporário”.
Erros que ainda vemos em 2026
- Misturar
sponsoredsó na homepage e deixar arquivos de categoria com links limpos gerados por excertos. - 301 para um deep link de campanha que muda todas as semanas, gerando cadeias e destinos 404 na rede.
- Canonical self-reference em HTTPS misturado com
hreflanga apontar HTTP - problema geral de indexação que em sites de afiliados se nota mais porque há mais variantes de URL. - Medir sucesso só por cliques - sem UTM consistentes (
utm_medium=affiliate) no destino final, o SEO técnico fica correto e o reporting comercial continua cego. - Confiar no “modo de conformidade” de um plugin sem abrir o HTML. Audita o output.
Resumo operativo
- Qualifica outbounds comerciais com
rel="sponsored"(enoopener noreferrerquando usastarget="_blank"). - Usa cloaking de URL via redirect HTTP; evita cloaking de conteúdo e JS redirects como mecanismo principal.
- Mantém a stack leve - cada KB de plugin de links compete com LCP e INP na page experience.
- Canonical = o teu artigo; nunca a rede de afiliados nem a URL com UTM.
- Divulgação clara, no idioma do conteúdo, antes do primeiro link pago.
Uma stack de afiliados estável depende mais de redirects bem feitos e de HTML limpo do que do plugin da moda. Se quiseres montar a tua sem arrastar peso para o frontend, vê o que fazemos em desenvolvimento WordPress orientado a desempenho.







