Files
claude-plugins/marketing/skills/seo-content-optimization/references/structured-data.md
T
ealmeida 2d05873642 marketing: migra superfície SEO para OpenSEO (motor único)
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.
2026-07-30 22:39:40 +01:00

7.0 KiB

/seo-content-optimization - Structured Data e Meta Tags

Meta Tags Essenciais 2026

<!-- Title tag (50-60 caracteres) -->
<title>Keyword Principal | Nome Marca 2026</title>

<!-- Meta description (150-160 caracteres, CTA claro) -->
<meta name="description" content="Descrição apelativa com keyword, benefício claro e CTA subtil. Actualizado 2026.">

<!-- Canonical URL -->
<link rel="canonical" href="https://site.pt/pagina/">

<!-- Open Graph -->
<meta property="og:title" content="Título para Social (60 chars)">
<meta property="og:description" content="Descrição social (65 palavras max)">
<meta property="og:image" content="https://site.pt/og-image.jpg">
<meta property="og:url" content="https://site.pt/pagina/">
<meta property="og:type" content="article">

<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Título Twitter">
<meta name="twitter:description" content="Descrição Twitter">
<meta name="twitter:image" content="https://site.pt/twitter-image.jpg">

<!-- 2026: Article metadata -->
<meta property="article:published_time" content="2026-02-03T10:00:00Z">
<meta property="article:modified_time" content="2026-02-03T15:30:00Z">
<meta property="article:author" content="Nome Autor">

Structured Data (Schema.org) 2026

Organization (Homepage)

{
  "@context": "https://schema.org",
  "@type": "Organization",
  "name": "Nome Empresa",
  "url": "https://site.pt",
  "logo": "https://site.pt/logo.png",
  "sameAs": [
    "https://linkedin.com/company/...",
    "https://facebook.com/...",
    "https://instagram.com/..."
  ],
  "contactPoint": {
    "@type": "ContactPoint",
    "telephone": "+351-XXX-XXX-XXX",
    "contactType": "Customer Service",
    "areaServed": "PT",
    "availableLanguage": ["pt", "en"]
  }
}

Article/BlogPosting (E-E-A-T compliant)

{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "Título do Artigo",
  "author": {
    "@type": "Person",
    "name": "Nome Autor",
    "url": "https://site.pt/autor/nome",
    "jobTitle": "Especialista em...",
    "knowsAbout": ["Área 1", "Área 2"]
  },
  "publisher": {
    "@type": "Organization",
    "name": "Nome Empresa",
    "logo": {
      "@type": "ImageObject",
      "url": "https://site.pt/logo.png"
    }
  },
  "datePublished": "2026-02-03",
  "dateModified": "2026-02-03",
  "image": "https://site.pt/imagem.jpg",
  "wordCount": 1500,
  "inLanguage": "pt-PT"
}
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Pergunta completa?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Resposta completa e detalhada (min 40 palavras para snippets)."
      }
    }
  ]
}

HowTo Schema (rich results 2026)

{
  "@context": "https://schema.org",
  "@type": "HowTo",
  "name": "Como fazer X",
  "description": "Guia completo passo a passo",
  "totalTime": "PT30M",
  "step": [
    {
      "@type": "HowToStep",
      "name": "Passo 1",
      "text": "Descrição detalhada passo 1",
      "image": "https://site.pt/passo1.jpg"
    }
  ]
}

Review/Rating Schema (produtos)

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Nome Produto",
  "brand": { "@type": "Brand", "name": "Nome Marca" },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.8",
    "reviewCount": "127"
  },
  "offers": {
    "@type": "Offer",
    "price": "95.00",
    "priceCurrency": "EUR",
    "availability": "https://schema.org/InStock"
  }
}

Core Web Vitals 2026

Métrica Bom Necessita Melhoria Mau Mudança 2026
LCP < 2.5s 2.5-4s > 4s Threshold < 2.0s Q2
INP < 200ms 200-500ms > 500ms Substituiu FID em Jan 2026
CLS < 0.1 0.1-0.25 > 0.25 Sem mudanças

Optimizações LCP

<!-- Preload imagem hero -->
<link rel="preload" as="image" href="/hero.jpg" fetchpriority="high">

<!-- Lazy loading imagens below-fold -->
<img src="image.jpg" loading="lazy" alt="Descrição">

<!-- Responsive images -->
<img srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"
     sizes="(max-width: 600px) 480px, (max-width: 1000px) 800px, 1200px"
     src="large.jpg" alt="Descrição">

<!-- WebP format -->
<picture>
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="Descrição">
</picture>

Optimizações INP (novo 2026)

// Debounce event handlers
function debounce(func, wait) {
  let timeout;
  return function executedFunction(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => func(...args), wait);
  };
}

// Code splitting
const component = () => import('./HeavyComponent.js');

// Web Workers para tarefas pesadas
const worker = new Worker('worker.js');
worker.postMessage({ task: 'heavy-computation', data });

Optimizações CLS

/* Definir width/height em imagens */
img {
  width: 800px;
  height: 600px;
  aspect-ratio: 4 / 3;
}

/* Reservar espaço para ads */
.ad-container { min-height: 250px; }

/* Font loading */
@font-face {
  font-family: 'Custom Font';
  src: url('/font.woff2') format('woff2');
  font-display: swap;
}

URL Structure Best Practices

CORRECTO:
https://site.pt/categoria/keyword-principal/
https://site.pt/blog/como-fazer-energia-solar-2026/

ERRADO:
https://site.pt/p?id=123&cat=5&lang=pt
https://site.pt/este-url-e-muito-longo-com-muitas-palavras-desnecessarias/

Regras 2026:

  • Máximo 60 caracteres
  • Hífens (não underscores)
  • Lowercase
  • Keyword no início se possível
  • Sem stop words quando possível

Keyword Research

Ferramentas

Ferramenta Uso Métricas Custo
OpenSEO get_keyword_metrics Hidratar até 700 keywords conhecidas Volume, KD, intenção, CPC, tendência pago (lote)
OpenSEO research_keywords Descobrir keywords novas (1-5 seeds) Volume, KD, ideias relacionadas pago (~30-100/seed — estimativa do schema, não medida)
OpenSEO get_search_console_performance O que já posiciona (dados próprios) Cliques, impressões, CTR, posição grátis
OpenSEO get_ranked_keywords Keywords de um domínio (nosso ou concorrente) Posição, volume, tráfego pago
AnswerThePublic Long-tail questions Questões reais de utilizadores grátis
Google Trends Sazonalidade Tendência temporal grátis

Ordem obrigatória: Search Console primeiro (grátis e são dados de primeira mão), só depois as pagas. Mercado PT: locationCode: 2620, languageCode: "pt".

Keyword Difficulty Benchmarks

KD Dificuldade DR Necessário
0-20 Muito Fácil < 20
21-40 Fácil 20-35
41-60 Médio 35-50
61-80 Difícil 50-70
81-100 Muito Difícil > 70

Estratégia: Começar por KD 0-40, escalar para 41-60 após DR > 35.