As skills de SEO assentavam em quatro dependências, nenhuma operacional: SEO Tools API (localhost:3000, pasta inexistente em disco), Ahrefs MCP (nunca esteve em config), gsc e lighthouse (em disabledServers). Os seis passos da /seo-audit e o workflow inteiro da /seo-report apontavam para tooling morto — não eram executáveis. - seo-audit v3.0: ordem por custo (grátis → lote pago → unitário pago), gate de mercado (PT = 2620/pt) e gate de maxPages - seo-report v3.0: cobertura de crawl obrigatória no entregável - ferramentas-api.md: inventário das 24 ferramentas OpenSEO + tabela de migração endpoint a endpoint - implementacao-tecnica.md: striking distance, desperdício e filtro de ruído do GSC em código - seo-specialist v3.0: primary_mcps [openseo], bloco de MCPs desligados, FID → INP nos Core Web Vitals maxPages tem default 50: descomplicar.pt auditado com o default deu 25 URLs e 92 issues sem críticos; com maxPages 600 deu 1337 issues e 9 críticos. Documentado como gate — a fase Search Console dimensiona o crawl. Limitações declaradas nas skills: get_audit_issues devolve contagens sem URLs pela bridge MCP (structuredContent.issues não é entregue) e o whoami não expõe saldo de créditos em self-hosted.
10 KiB
name, description
| name | description |
|---|---|
| seo-audit | Auditoria SEO completa com dados reais via OpenSEO (crawl, Search Console, SERP, backlinks, keywords). Analisa SEO técnico, conteúdo, autoridade e desempenho, e prioriza por retorno. Usar quando "auditoria SEO", "audit", "analisar site", "Core Web Vitals", "Search Console", "striking distance", "porque não tenho tráfego". |
SEO Audit — Auditoria Completa (OpenSEO)
Auditoria SEO com dados reais. Motor único: OpenSEO (seo.descomplicar.pt), que substituiu o stack antigo (SEO Tools API + Ahrefs + GSC MCP + Lighthouse MCP) — ver references/ferramentas-api.md para a tabela de migração.
Regra zero — a ordem é económica, não estética
O OpenSEO tem ferramentas grátis e ferramentas que gastam créditos. Executar pela ordem errada gasta dinheiro a produzir conclusões que as ferramentas grátis já davam.
| Fase | Ferramentas | Custo | Porquê nesta ordem |
|---|---|---|---|
| 1 | get_search_console_performance, inspect_urls |
grátis | Dados de primeira mão. Diz o que já posiciona e quais páginas importam |
| 2 | run_site_audit, get_audit_issues, get_audit_pages |
grátis | Estado técnico. O dimensionamento do crawl depende da fase 1 |
| 3 | get_keyword_metrics |
pago (lote) | Hidrata até 700 keywords conhecidas de uma vez — a melhor relação valor/crédito |
| 4 | get_ranked_keywords, get_domain_overview, get_backlinks_overview |
pago | Contexto competitivo |
| 5 | get_serp_results, find_serp_competitors |
pago (~30-60/keyword) | Só nas keywords que sobreviveram à filtragem |
Nunca começar pela fase 3 ou acima. As fases 1-2 resolvem a maioria das auditorias sem gastar um crédito.
Pré-voo obrigatório (3 verificações, 30 segundos)
1. openseo → whoami → confirma ligação, org, modo
2. openseo → list_projects → obtém projectId E o mercado do projecto
3. confirmar mercado → PT = locationCode 2620, languageCode "pt"
GATE — mercado. Se o projecto estiver em 2840/en (EUA/inglês, que é o default) e o cliente for português, todas as chamadas pagas devolvem dados do mercado errado. Ou se corrige o mercado do projecto, ou se passa locationCode/languageCode explicitamente em cada chamada. Um esquecimento = créditos gastos em lixo.
locationCode: 2620= Portugal — confirmado empiricamente (SERP devolve domínios.pt). Não inventar códigos: se houver dúvida, correr uma query de teste e validar pelos resultados.
Fase 1 — Search Console primeiro (grátis, é o mapa)
openseo → get_search_console_performance
dimensions: ["query"] dateRange: "last_3_months" rowLimit: 1000
openseo → get_search_console_performance
dimensions: ["page"] dateRange: "last_3_months" rowLimit: 1000
Paginar com startRow enquanto o cabeçalho disser more available.
As três armadilhas do GSC
1. Vista por query ≠ vista por página. O GSC anonimiza queries raras, por isso os totais por query são sempre muito menores que os totais por página. A vista por página é a real; usar essa para números globais.
2. O GSC não filtra por posição. striking distance tem de ser filtrado do lado do cliente, depois de puxar as linhas.
3. Há lixo nas queries. Colagens de relatórios do Google Ads, operadores site:, strings com mojibake. Filtrar antes de contar, ou as métricas mentem.
def is_noise(k):
return ('ativado' in k and 'correspond' in k) or k.startswith('-site:') \
or k.startswith('=') or len(k) > 90 or '0,00' in k
O que extrair
| Métrica | Cálculo | Leitura |
|---|---|---|
| CTR global | cliques ÷ impressões (vista por página) | < 1% = problema de captação, não de ranking |
| Distribuição por posição | buckets 1-3 / 4-10 / 11-20 / 21-50 / 51+ | Impressões concentradas em 21+ = visibilidade inútil |
| Branded vs não-branded | queries com o nome da marca vs resto | Se só a marca converte, o SEO não está a trabalhar |
| Striking distance | pos 4-20 e impressões ≥ 25 | É aqui que está o retorno |
| Desperdício | pos > 40 e impressões ≥ 300 | Páginas com procura real enterradas |
O sinal mais accionável de todos
Posição 4-10 com CTR perto de 0%. Não é problema de ranking — o site está na primeira página. É o título e a meta description a não convencerem. Cruzar esta lista com os issues missing-meta-description e title-too-long da fase 2: a intersecção é a lista de trabalho, por ordem.
Fase 2 — Auditoria técnica (grátis)
openseo → run_site_audit
url: "<url>" maxPages: <N> runLighthouse: true
openseo → get_audit_status (poll até "completed")
openseo → get_audit_issues (severity: critical → warning → info)
GATE — maxPages (o erro que cega a auditoria)
maxPages tem default 50. Um site de 600 páginas auditado com o default devolve um relatório limpo e falso: descreve 8% do site e omite exactamente o hub de conteúdo que gera o tráfego.
Regra: maxPages ≥ número de páginas com impressões no GSC (fase 1), com folga de ~25%. Por isso é que a fase 1 vem primeiro — é ela que dimensiona o crawl.
Caso real (descomplicar.pt, 07-2026): auditoria com default 50 → 25 URLs únicos, 92 issues, zero críticos, nenhuma das 119 páginas
/guia-*. Relançada commaxPages: 600→ 1337 issues, 9 críticos. O relatório "limpo" descrevia 4% do site.
Prioridade dos issues
| Severidade | Tipos | Acção |
|---|---|---|
| critical | broken-internal-link, blocked-page, server-error, broken-page |
Corrigir já — sangram autoridade e crawl budget |
| warning | missing-h1, missing-meta-description, duplicate-content, multiple-h1, duplicate-title |
Priorizar pelas páginas com impressões (fase 1) |
| info | title-too-long, noindex-page, slow-response, heading-order-skip |
Lote; só vale a pena onde há procura |
Nunca tratar a lista de issues por ordem de contagem. 300 metas em falta em páginas sem impressões valem menos que 6 em páginas na posição 8. A fase 1 é que ordena a fase 2.
Limitação conhecida — issues sem URL
get_audit_issues e get_audit_pages devolvem apenas contagens agregadas através da bridge MCP. As linhas por URL vivem em structuredContent.issues, que a bridge não entrega; get_audit_pages trunca a listagem em ~25 linhas independentemente do limit.
Contorno: o campo details.mcpMeta.url da resposta traz o link do relatório na UI. Entregar esse link ao humano para os URLs concretos:
https://seo.descomplicar.pt/p/<projectId>/audit?auditId=<auditId>
Declarar esta limitação no relatório — não fingir que se verificaram URLs que não se viram.
Core Web Vitals por página
run_site_audit com runLighthouse: true corre Lighthouse numa amostra (até 20 páginas). Para uma página específica, usar chrome-devtools:
chrome-devtools → lighthouse_audit (SEO, acessibilidade, best practices)
chrome-devtools → performance_start_trace (LCP, INP, CLS reais)
Thresholds 2026: LCP < 2,5s · INP < 200ms · CLS < 0,1 (INP substituiu o FID — se algum documento ainda disser FID, está desactualizado.)
Fase 3 — Hidratar keywords (pago, lote)
openseo → get_keyword_metrics
keywords: [<as keywords em striking distance da fase 1>]
locationCode: 2620 languageCode: "pt"
Até 700 keywords numa só chamada — volume, dificuldade (KD), intenção, CPC, tendência. É a forma barata de priorizar. Só depois disto se decide onde vale a pena competir.
Guardar o que sobreviver: openseo → save_keywords (grátis, idempotente).
Fase 4 — Contexto competitivo (pago)
openseo → get_domain_overview (tráfego orgânico estimado, nº keywords, backlinks)
openseo → get_ranked_keywords (onde o domínio posiciona, por mercado)
openseo → get_backlinks_overview (~50 créditos por domínio)
openseo → get_backlinks_profile (linhas detalhadas: anchors, dofollow, spam)
Fase 5 — SERP (pago, por último)
openseo → get_serp_results (1-10 keywords por chamada, ~30-60 créditos cada)
openseo → find_serp_competitors (quem compete num conjunto de keywords)
Ler a SERP como estrutura, não como lista: se o top-10 estiver cheio de directórios e artigos "melhores X", a intenção é comparativa e uma homepage não entra — é preciso uma página de comparação. Se estiver cheio de homepages de concorrentes, é disputa de marca.
Local/Maps: get_local_serp_results, search_local_businesses, get_google_business_questions.
Custos — o que sabemos e o que não sabemos
whoami não expõe saldo de créditos em modo self-hosted (verificado antes e depois de uma chamada paga: output idêntico). Os ~30-60 créditos/keyword são a estimativa do schema, não uma medição.
Consequência prática: não há medidor no OpenSEO. O contador real vive na conta DataForSEO. Para lotes grandes, confirmar saldo aí primeiro. Nunca reportar custo consumido como facto — reportar como estimativa.
Anti-patterns
- Correr
run_site_auditcom omaxPagespor omissão. Produz relatórios limpos e falsos. - Começar por ferramentas pagas. O GSC é grátis e responde a metade das perguntas.
- Usar totais por query como totais do site (o GSC anonimiza — usar a vista por página).
- Priorizar issues por contagem em vez de por impressões da página afectada.
- Correr chamadas pagas sem confirmar o mercado do projecto.
- Apresentar contagens de issues como se fossem URLs verificados.
- Auditar sem dados reais ou simular métricas.
- Recomendações sem prioridade (crítico/importante/melhoria) e sem esforço estimado.
References
| Ficheiro | Conteúdo |
|---|---|
references/ferramentas-api.md |
Inventário OpenSEO completo + tabela de migração do stack antigo |
references/template-relatorio-auditoria.md |
Template do relatório com todas as secções e tabelas |
Versão: 3.0.0 | Autor: Descomplicar® | Motor: OpenSEO
Healing Log
{"date":"2026-07-30","issue":"Skill dependia de SEO Tools API (localhost:3000), Ahrefs MCP, GSC MCP e Lighthouse MCP — todos inexistentes ou desligados. Nenhum dos 6 passos era executável.","fix":"Reescrita completa sobre OpenSEO, com ordem por custo, gates de mercado e maxPages.","source":"auto"}