TITLE

Next.jsのSEO ― App RouterのMetadata APIで正しく設定する

投稿日:2026.06.14

CATEGORY

  • Web開発
Next.jsのSEO ― App RouterのMetadata APIで正しく設定する

next/headを手書きする時代から変わった

Pages Routerの時代、Next.jsでメタタグを設定するには各ページでnext/headを使ってHTMLタグを手書きするのが一般的でした。App Routerが登場した後、Next.js 13.2.0からMetadata APIが追加され、メタタグの管理方法が大きく変わりました。

この記事では、App RouterのMetadata APIを中心に、SEOに必要な設定を実装者向けに解説します。内容はNext.js公式ドキュメント(App Router前提)に基づいています。

Metadata APIの基本構造

App RouterのMetadata APIでは、layout.tsxまたはpage.tsxからmetadataオブジェクト(静的な場合)またはgenerateMetadata関数(動的な場合)をexportします。

静的なmetadata

import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'ページタイトル',
  description: 'ページの説明文',
}

動的なgenerateMetadata

URLパラメータやデータベースの値に応じてメタタグを変えたい場合はgenerateMetadataを使います。

import type { Metadata } from 'next'

type Props = {
  params: Promise<{ slug: string }>
}

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { slug } = await params
  // DBやAPIからデータを取得してメタタグを生成
  return {
    title: `記事タイトル - ${slug}`,
  }
}

重要な制約: metadatagenerateMetadataServer Component専用です。'use client'を付けたClient Componentでは使えません。また、同一セグメント(同じpage.tsx)で両方を同時にexportすることはできません。

最低限設定すべき5つの項目

1. metadataBase

metadataBaseはルートのlayout.tsxに設定します。OGP画像URLやcanonicalに相対パスを使う場合、この設定がないとエラーになります。

export const metadata: Metadata = {
  metadataBase: new URL('https://example.com'),
}

本番環境のURLを環境変数で管理するのが一般的です。

metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL ?? 'https://example.com'),

2. title

titleにはtemplatedefaultを使うことで、サイト共通のタイトル書式を一箇所で管理できます。

// app/layout.tsx(ルート)
export const metadata: Metadata = {
  title: {
    template: '%s | サイト名',
    default: 'サイト名',
  },
}

// app/blog/[slug]/page.tsx
export const metadata: Metadata = {
  title: '記事タイトル',  // → "記事タイトル | サイト名" になる
}

テンプレートを使わずそのままのタイトルにしたい場合はabsoluteを使います。

title: { absolute: 'このタイトルそのまま使う' }

3. description

meta descriptionはページごとにユニークな内容を設定します。Googleが書き換える場合がありますが、設定しておくことで検索結果の表示を意図に近づけられます。

4. canonical(alternates)

同一コンテンツが複数URLで表示される場合にcanonoical URLを指定します。

export const metadata: Metadata = {
  alternates: {
    canonical: '/blog/this-article',
  },
}

metadataBaseが設定されていれば、相対パスが絶対URLに自動解決されます。

多言語対応が必要な場合はhreflangもalternates.languagesで設定できます。

5. openGraph

OGPはSNSでシェアされた時の表示に影響します。

export const metadata: Metadata = {
  openGraph: {
    title: 'OGP用タイトル',
    description: 'OGP用説明文',
    images: [{
      url: '/og-image.png',  // metadataBaseが必要
      width: 1200,
      height: 630,
    }],
  },
}

画像URLには絶対URLが必要です。metadataBaseを設定してあれば相対パスで書けます。

よくある落とし穴

openGraphは「deep merge」ではない

子セグメントでopenGraphを部分的に設定すると、親のopenGraphの全フィールドが上書き消去されます

// 親(app/layout.tsx)
export const metadata: Metadata = {
  openGraph: {
    siteName: 'サイト名',
    images: [{ url: '/default-og.png' }],
  },
}

// 子(app/blog/page.tsx) — 意図しない結果になる
export const metadata: Metadata = {
  openGraph: {
    title: 'ブログ一覧',
    // siteName と images が消える!
  },
}

共通フィールドを引き継ぎたい場合は、spread演算子で明示的に展開します。

import { sharedOpenGraph } from '@/lib/metadata'

export const metadata: Metadata = {
  openGraph: {
    ...sharedOpenGraph,
    title: 'ブログ一覧',
  },
}

Client ComponentではMetadata APIは使えない

インタラクティブなUIと同じファイルにメタタグを設定したい場合は、Server Componentとして別ファイルに切り出すか、layout.tsxで設定します。

viewportとthemeColorの非推奨化

Next.js 14以降、viewportthemeColorはMetadata APIのmetadataオブジェクトでは非推奨になりました。代わりにgenerateViewportを使います。

import type { Viewport } from 'next'

export const viewport: Viewport = {
  themeColor: '#ffffff',
  width: 'device-width',
  initialScale: 1,
}

動的OG画像の生成

appディレクトリにopengraph-image.tsxを配置すると、ImageResponseを使って動的なOGP画像を生成できます。記事ごとにタイトルを入れたOGP画像を自動生成する場合に便利です。

// app/blog/[slug]/opengraph-image.tsx
import { ImageResponse } from 'next/og'

export default async function Image({ params }: { params: { slug: string } }) {
  return new ImageResponse(
    <div style={{ display: 'flex', fontSize: 40 }}>
      {params.slug}
    </div>
  )
}

Google Search Console所有確認の設定

GSCでサイトの所有確認をメタタグで行う場合はverificationを使います。

export const metadata: Metadata = {
  verification: {
    google: 'xxxxxxxxxx',  // GSCで発行されたコード
  },
}

Pages Routerとの違い

Pages Routerを使っているプロジェクトでは、Metadata APIは使えません。Pages Routerでは引き続きnext/headを使ってメタタグを設定します。app/sitemap.tsなどのファイル規約もApp Router専用です。Pages RouterプロジェクトをApp Routerに移行する際は、next/headの記述をMetadata APIに置き換える作業が必要になります。

ここまでをまとめると

App RouterのMetadata APIを使うことで、メタタグの設定を宣言的・型安全に管理できます。実装時に特に意識すべき点は次のとおりです。

  • metadataBase: ルートlayoutに必ず設定する。OGP画像とcanonicalの相対パス解決に必要
  • title.template: サイト名の付与ルールを一箇所で管理する
  • openGraph: 子セグメントで設定すると親フィールドが消える。共通値はspreadで引き継ぐ
  • viewport / themeColor: Next.js 14以降はgenerateViewportを使う
  • Client Component: 'use client'のファイルではMetadata APIは使えない

keywordsメタタグはGoogleが無視するため、設定しても検索順位への影響はありません。その時間を、コンテンツの質やCore Web Vitalsの改善に充てる方が実効性があります。

出典

AI

AI導入やシステム開発の ご相談を承っています。

お気軽にお問い合わせください