404 Not Found

404 Not Found


nginx

SEO最適化:useHead + useSeoMeta

CharlieのMegaShopには100万商品ページがありますが, Googleにインデックスされているのはわずか2,000ページです。Aliceが商品名で検索してもMegaShopのページが見つかりません。Bobが確認すると, 商品ページにはタイトル, メタディスクリプション, Open Graphタグ, 構造化データがすべて欠けていました。Nuxt 3のSEOツールチェーンがこれらすべての問題を解決できます。

1. 学ぶ内容


2. アーキテクトのある本当の話

(1) 課題:100万ページのうちGoogleにインデックスされているのはわずか2,000

CharlieがGoogle Search ConsoleでMegaShopを確認すると, 100万商品ページのうちわずか2,000しかインデックスされていませんでした。Bobの分析によると, すべての商品ページのタイトルが「MegaShop」で, メタディスクリプションは空, Open Graphタグもないため, SNSでシェアしてもサイト名しか表示されず, 商品情報が表示されません。

(2) Nuxt SEOツールチェーンの解決策

Nuxt 3のuseHeaduseSeoMetaにより, 各商品ページに独自のSEOメタデータを持たせることができます:

TYPESCRIPT
// 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) 結果:Googleインデックス率が40倍に急増

3か月後, Googleのインデックスは2,000から800,000に急増し, オーガニック検索トラフィックは340%増加しました。


3. SEOツールチェーンアーキテクチャ

(1) Nuxt 3 SEOツールチェーンの概要

100%
graph TB
    A[Nuxt SEOツールキット] --> 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[動的URL生成]
    F --> F1[クローラーアクセス制御]

4. useHeadの動的管理

(1) useHeadで管理できるもの

タグ種別 属性 SEOへの影響
title ページタイトル 🔴 高 (ランキングシグナル)
meta name="description" ページ説明 🔴 高 (クリック率)
meta property="og:*" Open Graph 🟡 中 (ソーシャルシェア)
meta name="twitter:*" Twitter Card 🟡 中 (ソーシャルシェア)
link rel="canonical" 正規URL 🔴 高 (重複排除)
link rel="alternate" 多言語URL 🟡 中 (i18n SEO)
script type="application/ld+json" JSON-LD 🟡 中 (リッチスニペット)

(1) ▶ サンプル:useHeadの基本使用

TYPESCRIPT
// 任意のコンポーネントまたはページで
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' }
  ]
})

出力:

TEXT
// 実行成功

(2) ▶ サンプル:動的タイトル (computed, リアクティブ)

VUE
<script setup lang="ts">
const route = useRoute()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)

// 商品読み込み時に更新される動的タイトル
useHead({
  title: computed(() => product.value
    ? `${product.value.name} - MegaShop`
    : 'Loading... - MegaShop'
  )
})
</script>

出力:

TEXT
// 実行成功

(3) ▶ サンプル:グローバルデフォルト設定

TYPESCRIPT
// 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' }
      ]
    }
  }
})

出力:

TEXT
// 実行成功

5. useSeoMeta構造化SEO

(1) useSeoMetaとuseHeadの比較

項目 useHead useSeoMeta
対象 汎用Head管理 SEO専用ショートカット
APIスタイル 配列オブジェクト キー・バリュー
OG/Twitter 手動metaタグ入力が必要 1行で完了
型安全性 ⚠️ ドキュメント確認が必要 ✅ 完全な型ヒント
重複排除 ⚠️ 手動管理 ✅ 自動重複排除

(1) ▶ サンプル:商品詳細ページSEO

VUE
<!-- pages/products/[id].vue -->
<script setup lang="ts">
const route = useRoute()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)

// 構造化SEOメタデータ - 型安全
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>

出力:

TEXT
// 実行成功

(2) ▶ サンプル:ホームページSEO

TYPESCRIPT
// 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'
})

出力:

TEXT
// 実行成功

6. JSON-LD構造化データ

(1) 構造化データが検索結果に与える影響

データ種別 Googleリッチスニペット結果 MegaShopでの対応
Product 価格/評価/在庫 ✅ 商品詳細ページ
BreadcrumbList パンくずナビゲーション ✅ 全ページ
Organization 会社情報 ✅ ホーム
Website サイト検索ボックス ✅ ホーム
Review レビュー概要 ✅ 商品ページ

(1) ▶ サンプル:商品JSON-LD

VUE
<!-- pages/products/[id].vue -->
<script setup lang="ts">
const route = useRoute()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)

// Googleリッチ結果向け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,
        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>

出力:

TEXT
// 実行成功

(2) ▶ サンプル:パンくずJSON-LD

TYPESCRIPT
// 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
        }))
      })
    }]
  })
}

// ページでの使用
useBreadcrumbLd([
  { name: 'Home', url: 'https://megashop.com' },
  { name: 'Products', url: 'https://megashop.com/products' },
  { name: 'Premium Headphones', url: 'https://megashop.com/products/123' }
])

出力:

TEXT
// 実行成功

7. サイトマップとrobots.txt

(1) ▶ サンプル:@nuxtjs/sitemapのインストール

BASH
npm install @nuxtjs/sitemap

出力:

TEXT
# コマンド実行成功
TYPESCRIPT
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/sitemap'],

  sitemap: {
    hostname: 'https://megashop.com',
    gzip: true,
    routes: async () => {
      // 100万商品の動的ルート
      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) ▶ サンプル:robots.txt

TEXT
// public/robots.txt
User-agent: *
Allow: /
Disallow: /admin/
Disallow: /api/
Disallow: /profile/

Sitemap: https://megashop.com/sitemap.xml

出力:

TEXT
実行成功

(1) サイトマップ戦略の比較

戦略 メリット デメリット 適用規模
単一ファイルsitemap.xml シンプル ≤ 50,000 URL 小規模サイト
サイトマップインデックス 数百万URLに対応 分割が必要 MegaShop
動的ルート生成 新ページを自動反映 ビルド時クエリが必要 商品ページ
モジュール自動生成 ゼロ設定 制限あり 中小規模サイト

8. 総合例:MegaShop商品ページの完全SEOガイド

VUE
<!-- 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
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>

❓ よくある質問

Q useSeoMetauseHeadは一緒に使えますか?
A はい, 同じHeadインスタンスを操作します。useSeoMetaはSEOタグを管理し, useHeadは他のタグ (canonical/JSON-LD/style)を管理します。
Q 100万商品ページのサイトマップはどう扱えばよいですか?
A サイトマップインデックスを使用して複数のサブサイトマップに分割します (各50,000 URL以内)。@nuxtjs/sitemapモジュールは自動分割をサポートしています。
Q JSON-LDのinnerHTMLはXSSリスクがありますか?
A Nuxt 3はscriptタグのinnerHTMLにセキュリティ対策を適用します。ただし, JSON.stringifyを使用し, 動的データをエスケープしてインジェクションを防ぐのが最善です。
Q CSRモードでSEOメタデータは機能しますか?
A 検索エンジンのクローラーはCSRでレンダリングされたmetaタグをサポートしていません。SEOが必要なページではSSR, ISR, またはSSGを使用する必要があります。CSRページのmetaタグはクライアント側ハイドレーション後にのみ表示されます。
Q titleTemplateの使い方は?
A nuxt.config.tsでtitleTemplate: '%s | MegaShop'を設定します。ページのuseHeadではtitleの内容だけを設定すれば, テンプレートが自動的に構築されます。
Q ogImage画像にサイズ要件はありますか?
A Facebookは1200x630px, Twitterは1200x600px (summary_large_image)を推奨しています。小さすぎる画像は表示されない場合があります。

📖 まとめ


📝 練習問題

  1. 基本問題 (難易度:⭐):useHeadを使ってホームページのタイトルとメタディスクリプションを設定し, ソースコードを表示して確認してください。
  2. 応用問題 (難易度:⭐⭐):useSeoMetaを使って商品詳細ページにOGとTwitter Cardメタデータを完全に設定し, Facebook Sharing Debuggerで検証してください。
  3. チャレンジ (難易度:⭐⭐⭐):商品ページのJSON-LD自動生成, パンくずJSON-LD, サイトマップを実装し, Google Rich Results Testで構造化データを検証してください。

---|

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%