Otimização SEO: useHead + useSeoMeta
O MegaShop do Charlie tem um milhão de páginas de produtos, mas o Google indexou apenas 2.000 delas. Quando Alice busca pelo nome de um produto, ela não consegue encontrar nenhuma página do MegaShop. Bob verificou e descobriu que as páginas de produtos carecem de títulos, meta descriptions, tags Open Graph e dados estruturados. O toolchain SEO do Nuxt 3 pode resolver todos esses problemas.
1. O Que Você Vai Aprender
- useHead(): Gerenciar dinamicamente tags title, meta, link, script e style
- useSeoMeta(): Metadados SEO estruturados (OG/Twitter/description)
- Padrões SEO Embutidos e Mecanismos de Sobrescrita do Nuxt 3
- Sitemap e robots.txt: módulo @nuxtjs/sitemap
- SEO Dinâmico da Página de Detalhes do Produto do MegaShop + JSON-LD + Geração Automática de Sitemap
2. Uma História Real de um Arquiteto
(1) Ponto Crítico: De um milhão de páginas, apenas 2.000 são indexadas pelo Google
Charlie verificou o MegaShop usando o Google Search Console e descobriu que de 1 milhão de páginas de produtos, apenas 2.000 haviam sido indexadas. A análise de Bob revelou que todas as páginas de produtos tinham o título "MegaShop," meta descriptions vazias e tags Open Graph ausentes — o que significava que, quando compartilhadas nas redes sociais, apenas o nome do site aparecia, sem informações do produto.
(2) Solução com o Toolchain SEO do Nuxt
O useHead e useSeoMeta do Nuxt 3 permitem que cada página de produto tenha seus próprios metadados SEO:
// pages/products/[id].vue
useSeoMeta({
title: product.value?.name,
ogTitle: product.value?.name,
description: `Buy ${product.value?.name} for $${product.value?.price} USD`,
ogImage: product.value?.image
})
(3) Resultados: Taxa de indexação do Google disparou 40 vezes
Após três meses, o índice do Google saltou de 2.000 para 800.000, e o tráfego de busca orgânica aumentou 340%.
3. Arquitetura do Toolchain SEO
(1) Visão Geral do Toolchain SEO do Nuxt 3
graph TB
A[Nuxt SEO Toolkit] --> B[useHead]
A --> C[useSeoMeta]
A --> D[JSON-LD]
A --> E[@nuxtjs/sitemap]
A --> F[robots.txt]
B --> B1[title / meta / link]
C --> C1[OG / Twitter Card]
D --> D1[Product / Breadcrumb]
E --> E1[Dynamic URL Generation]
F --> F1[Crawler Access Control]
```
---
## 4. Gerenciamento Dinâmico com useHead
### (1) O que o useHead pode gerenciar?
| Tipo de Tag | Atributo | Impacto SEO |
|:---------|:-----|:---------|
| title | Título da Página | 🔴 Alto (Sinal de Ranking) |
| meta name="description" | Descrição da Página | 🔴 Alto (Taxa de cliques) |
| meta property="og:*" | Open Graph | 🟡 Médio (Compartilhamento Social) |
| meta name="twitter:*" | Twitter Card | 🟡 Médio (Compartilhamento Social) |
| link rel="canonical" | URL Canônica | 🔴 Alto (desduplicação) |
| link rel="alternate" | URL Multilíngue | 🟡 Médio (i18n SEO) |
| script type="application/ld+json" | JSON-LD | 🟡 Suportado (Rich Snippets) |
### (1) ▶Exemplo: Uso Básico do useHead
```typescript
// Em qualquer componente ou página
useHead({
title: 'Premium Headphones - MegaShop',
meta: [
{ name: 'description', content: 'Buy Premium Headphones for $299.99 USD. Free shipping.' },
{ name: 'keywords', content: 'headphones, wireless, premium, audio' }
],
link: [
{ rel: 'canonical', href: 'https://megashop.com/products/123' }
]
})
Saída:
// Execução Bem-sucedida
(2) ▶Exemplo: Título dinâmico (computed, reativo)
<script setup lang="ts">
const route = useRoute()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)
// Título dinâmico que atualiza quando o produto carrega
useHead({
title: computed(() => product.value
? `${product.value.name} - MegaShop`
: 'Loading... - MegaShop'
)
})
</script>
Saída:
// Execução Bem-sucedida
(3) ▶Exemplo: Configuração Padrão Global
// nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
title: 'MegaShop - Premium E-Commerce',
titleTemplate: '%s | MegaShop',
meta: [
{ name: 'description', content: 'Over 1 million products shipped worldwide' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ charset: 'utf-8' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
}
}
})
Saída:
// Execução Bem-sucedida
4. SEO Estruturado com useSeoMeta
(1) Comparação entre useSeoMeta e useHead
| Dimensão | useHead | useSeoMeta |
|---|---|---|
| Foco | Gerenciamento Geral do Head | Atalhos Específicos para SEO |
| Estilo de API | Array de Objetos | Pares Chave-Valor |
| OG/Twitter | Requer entrada manual de meta tags | Feito em uma linha |
| Segurança de Tipo | ⚠️ Verificar documentação | ✅ Dicas de tipo completas |
| Desduplicação | ⚠️ Gerenciamento Manual | ✅ Desduplicação Automática |
(1) ▶Exemplo: SEO da Página de Detalhes do Produto
<!-- pages/products/[id].vue -->
<script setup lang="ts">
const route = useRoute()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)
// Metadados SEO estruturados - type-safe
useSeoMeta({
title: () => `${product.value?.name} - Buy Online`,
ogTitle: () => `${product.value?.name} - MegaShop`,
description: () => `Buy ${product.value?.name} for $${product.value?.price} USD. ${product.value?.reviewCount} reviews, ${product.value?.rating} stars. Free shipping worldwide.`,
ogDescription: () => `Premium ${product.value?.name} - $${product.value?.price} USD`,
ogImage: () => product.value?.image || '/images/og-default.jpg',
ogUrl: () => `https://megashop.com/products/${route.params.id}`,
ogType: 'product',
twitterCard: 'summary_large_image',
twitterTitle: () => `${product.value?.name} - MegaShop`,
twitterImage: () => product.value?.image || '/images/og-default.jpg'
})
</script>
Saída:
// Execução Bem-sucedida
(2) ▶Exemplo: SEO da Página Inicial
// pages/index.vue
useSeoMeta({
title: 'MegaShop - Over 1 Million Products',
ogTitle: 'MegaShop - Premium E-Commerce Platform',
description: 'Shop over 1 million products with free worldwide shipping. Electronics, fashion, home & garden at the best prices.',
ogDescription: 'Discover 1 million+ products on MegaShop. Free shipping on orders over $50 USD.',
ogImage: '/images/og-homepage.jpg',
ogUrl: 'https://megashop.com',
ogType: 'website'
})
Saída:
// Execução Bem-sucedida
5. Dados Estruturados JSON-LD
(1) Impacto dos Dados Estruturados nos Resultados de Busca
| Tipo de Dados | Resultados Rich Snippet do Google | Compatível com MegaShop |
|---|---|---|
| Product | Preço/Avaliação/Estoque | ✅ Página de Detalhes do Produto |
| BreadcrumbList | Navegação por Breadcrumbs | ✅ Todas as Páginas |
| Organization | Informações da Empresa | ✅ Página Inicial |
| Website | Caixa de Busca do Site | ✅ Página Inicial |
| Review | Resumo de Avaliações | ✅ Página do Produto |
(1) ▶Exemplo: JSON-LD de Produto
<!-- pages/products/[id].vue -->
<script setup lang="ts">
const route = useRoute()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)
// Dados estruturados JSON-LD para resultados rich do Google
useHead({
script: [
{
type: 'application/ld+json',
innerHTML: computed(() => JSON.stringify({
'@context': 'https://schema.org',
'@type': 'Product',
name: product.value?.name,
image: product.value?.image,
description: product.value?.description,
sku: `MEGA-${product.value?.id}`,
offers: {
'@type': 'Offer',
url: `https://megashop.com/products/${route.params.id}`,
priceCurrency: 'USD',
price: product.value?.price,
availability: product.value?.inStock
? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock'
},
aggregateRating: {
'@type': 'AggregateRating',
ratingValue: product.value?.rating,
reviewCount: product.value?.reviewCount
}
}))
}
]
})
</script>
Saída:
// Execução Bem-sucedida
(2) ▶Exemplo: JSON-LD de Breadcrumb
// composables/useBreadcrumbLd.ts
export function useBreadcrumbLd(items: { name: string; url: string }[]) {
useHead({
script: [{
type: 'application/ld+json',
innerHTML: JSON.stringify({
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
itemListElement: items.map((item, index) => ({
'@type': 'ListItem',
position: index + 1,
name: item.name,
item: item.url
}))
})
}]
})
}
// Uso na página
useBreadcrumbLd([
{ name: 'Home', url: 'https://megashop.com' },
{ name: 'Products', url: 'https://megashop.com/products' },
{ name: 'Premium Headphones', url: 'https://megashop.com/products/123' }
])
Saída:
// Execução Bem-sucedida
6. Sitemap e robots.txt
(1) ▶Exemplo: Instalando @nuxtjs/sitemap
npm install @nuxtjs/sitemap
Saída:
# Comando executado com sucesso
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxtjs/sitemap'],
sitemap: {
hostname: 'https://megashop.com',
gzip: true,
routes: async () => {
// Rotas dinâmicas para 1 milhão de produtos
const products = await $fetch('/api/products/all-ids')
return products.map((id: number) => ({
loc: `/products/${id}`,
lastmod: new Date().toISOString(),
changefreq: 'daily',
priority: 0.8
}))
},
defaults: {
changefreq: 'weekly',
priority: 0.5
}
}
})
(2) ▶Exemplo: robots.txt
// public/robots.txt
User-agent: *
Allow: /
Disallow: /admin/
Disallow: /api/
Disallow: /profile/
Sitemap: https://megashop.com/sitemap.xml
Saída:
Execução Bem-sucedida
(1) Comparação de Estratégias de Sitemap
| Estratégia | Vantagens | Desvantagens | Aplicabilidade |
|---|---|---|---|
| Sitemap de arquivo único sitemap.xml | Simples | ≤ 50.000 URLs | Site pequeno |
| Sitemap Index | Suporta milhões de URLs | Requer divisão | MegaShop |
| Gerar Rotas Dinamicamente | Sobrescrever Novas Páginas Automaticamente | Consultas em Tempo de Build | Páginas de Produtos |
| Geração automática pelo módulo | Zero configuração | Limitado | Sites de pequeno a médio porte |
7. Exemplo Completo: Guia SEO Completo para Páginas de Produtos do MegaShop
<!-- pages/products/[id].vue -->
<template>
<div v-if="product" class="product-page">
<h1>{{ product.name }}</h1>
<p class="price">${{ product.price }} USD</p>
<p>{{ product.reviewCount }} reviews · {{ product.rating }} stars</p>
</div>
</template>
<script setup lang="ts">
const route = useRoute()
const config = useRuntimeConfig()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)
const productUrl = `${config.public.siteUrl}/products/${route.params.id}`)
// SEO Meta
useSeoMeta({
title: () => `${product.value?.name} - MegaShop`,
ogTitle: () => product.value?.name,
description: () => `Buy ${product.value?.name} for $${product.value?.price} USD. Free shipping. ${product.value?.reviewCount} reviews.`,
ogDescription: () => `${product.value?.name} - $${product.value?.price} USD on MegaShop`,
ogImage: () => product.value?.image,
ogUrl: () => productUrl,
ogType: 'product',
twitterCard: 'summary_large_image'
})
// URL Canônica
useHead({
link: [{ rel: 'canonical', href: productUrl }]
})
// JSON-LD
useHead({
script: [{
type: 'application/ld+json',
innerHTML: computed(() => JSON.stringify({
'@context': 'https://schema.org',
'@type': 'Product',
name: product.value?.name,
image: product.value?.image,
offers: {
'@type': 'Offer',
priceCurrency: 'USD',
price: product.value?.price,
availability: product.value?.inStock ? 'InStock' : 'OutOfStock'
},
aggregateRating: {
'@type': 'AggregateRating',
ratingValue: product.value?.rating,
reviewCount: product.value?.reviewCount
}
}))
}]
})
</script>
❓Perguntas Frequentes
useSeoMeta e useHead podem ser usados juntos?Head. useSeoMeta gerencia tags SEO, enquanto useHead gerencia outras tags (canonical/JSON-LD/style).innerHTML do JSON-LD representa um risco de XSS?innerHTML de tags script. No entanto, é recomendável usar JSON.stringify e escapar dados dinâmicos para prevenir injeção.titleTemplate: '%s | MegaShop' no nuxt.config.ts. Na página, use useHead para definir apenas o conteúdo do título, e o template será construído automaticamente.📖Resumo
useHeadé um gerenciador de propósito geral para tagsHead, enquantouseSeoMetafoca em metadados SEO e oferece maior segurança de tipo- SEO Dinâmico: Títulos e descriptions Computed, responsivos; metadados únicos para cada página de produto
- Dados estruturados JSON-LD permitem que o Google exiba rich snippets (preço, avaliação, disponibilidade)
- @nuxtjs/sitemap gera automaticamente um sitemap e suporta um sitemap index contendo milhões de URLs
- robots.txt controla o escopo de acesso dos crawlers e bloqueia os caminhos admin/api/profile
📝Exercícios
- Exercício Básico (Dificuldade: ⭐): Use
useHeadpara definir o título e a meta description da página inicial, então veja o código fonte para verificar. - Exercício Avançado (Dificuldade: ⭐⭐): Use
useSeoMetapara configurar metadados completos de OG e Twitter Card para a página de detalhes do produto, e valide usando o Facebook Sharing Debugger. - Desafio (Dificuldade: ⭐⭐⭐): Implemente geração automática de JSON-LD para páginas de produtos, JSON-LD para breadcrumbs e sitemaps, e valide os dados estruturados usando o Google Rich Results Test.
---|



