ウェブエンジニア問題集

メタデータとSEO — generateMetadataでtitle・OGPを動的に設定する

検索結果に表示されるタイトルと説明文、SNSでシェアしたときに出るカード(OGP)——これらは集客を左右する重要な要素です。Next.js(App Router)には、これらを型安全に設定する Metadata API が組み込まれています。

この章では、静的な metadata の設定から、記事ごとに内容を変える generateMetadata、そしてOGPやタイトルテンプレートまでを押さえます。

学習者学習者

<head><title><meta> を書きたいんだけど、App Routerだとどこに書くの?

metadata — 静的なメタデータ

page.tsx または layout.tsxmetadata という名前のオブジェクトを export すると、Next.jsが自動で <head> に反映してくれます。<head> を自分で書く必要はありません。

// src/app/about/page.tsx
import type { Metadata } from "next";
 
export const metadata: Metadata = {
  title: "このサイトについて",
  description: "私たちのサービスの理念とチームを紹介します。",
};
 
export default function AboutPage() {
  return <h1>このサイトについて</h1>;
}

よく使うフィールドは次のとおりです。

フィールド説明
titleページのタイトル(検索結果の見出し・タブの文字)
descriptionページの説明(検索結果のスニペット)
keywordsキーワード(現在のSEOでは重要度は低い)
openGraphSNSシェア時のカード情報(OGP)
alternates正規URL(canonical)など
先生先生

titledescription はSEOの基本中の基本。全ページで「そのページ固有の・内容を表す」文言を必ず設定しよう。使い回しはもったいないよ。

検索結果やSNSカードでの見え方を設計するイメージ

generateMetadata — ページごとに動的なメタデータ

ブログ記事のようにページごとにタイトルが変わる場合、静的な metadata では対応できません。そこで generateMetadata 関数を使います。params を受け取り、データを取得して、メタデータを動的に組み立てられます。

構文: async function generateMetadata({ params }): Promise<Metadata>

引数説明
params動的セグメントの値(第6章と同じ。await で取り出す)
searchParamsクエリ文字列(必要な場合)

戻り値: Metadata オブジェクト(titledescription など)

// src/app/blog/[slug]/page.tsx
import type { Metadata } from "next";
 
export async function generateMetadata({
  params,
}: {
  params: Promise<{ slug: string }>;
}): Promise<Metadata> {
  const { slug } = await params;
  const post = await fetch(`https://api.example.com/posts/${slug}`).then((r) => r.json());
 
  return {
    title: post.title,
    description: post.excerpt,
  };
}
 
export default async function BlogPostPage({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  // ...記事本体の描画
}

タイトルのテンプレート — サイト名を自動で付ける

「各ページのタイトル+サイト名」(例:記事タイトル | My Blog)という形にしたいことはよくあります。ルートレイアウトで title.template を設定すると、子ページの title に自動でサイト名が付きます。

// src/app/layout.tsx
export const metadata: Metadata = {
  title: {
    default: "My Blog", // タイトル未設定のページで使う既定値
    template: "%s | My Blog", // %s に各ページのtitleが入る
  },
};
// src/app/about/page.tsx
export const metadata: Metadata = {
  title: "このサイトについて", // → 「このサイトについて | My Blog」になる
};
学習者学習者

全ページのタイトルに毎回「| My Blog」って書かなくていいのは助かる…!

OGP — SNSでシェアされたときのカード

SNSでURLが共有されると、openGraph の情報をもとにカード(画像+タイトル+説明)が表示されます。クリック率に直結するため、特に画像(images)は設定しておきたい項目です。

export const metadata: Metadata = {
  title: "新サービスを公開しました",
  openGraph: {
    title: "新サービスを公開しました",
    description: "詳しくはこちらをご覧ください。",
    images: ["/og/launch.png"], // SNSカードに表示される画像
    type: "article",
  },
};

まとめ

  • page.tsx / layout.tsxmetadataexport すると <head> に自動反映される(<head> は自分で書かない)
  • titledescription はSEOの基本。全ページで固有の文言を設定する
  • ページごとに変わるメタデータは generateMetadataparamsawait して動的生成)
  • ルートレイアウトの title.template%s | サイト名)でサイト名を自動付与できる
  • openGraph.images でSNSシェア時のカード画像を設定。sitemap.ts / robots.ts も活用する

次の章では、フォーム送信やデータ更新を扱う Server Actionsとフォーム を学びます。"use server" を使って、APIルートを書かずにサーバー側の処理を呼び出せるようになります。