Portfolio課題を言葉にして、Webというカタチに変える──
そんな仕事をしています。

microCMSのSEO対策チェックリスト|Next.jsでtitle・canonical・OGP・構造化データを実装

microCMSで記事を登録しただけでは、検索結果やSNSで使われるtitle、canonical、OGP、構造化データは完成しません。microCMSは記事データを管理し、Next.jsは取得したデータからHTMLの<head>や公開ページを生成します。SEO設定も、この役割に合わせて両方を設計する必要があります。

どちらか一方だけを確認すると、記事ページのtitleは正しいのに、カテゴリーページにはカテゴリ名が反映されない、といった実装漏れが起きます。当サイトでも、microCMSカテゴリーページの見出しにはカテゴリ名が表示されている一方、<title>にはカテゴリ名が入らず、サイト共通のタイトルが出力されていました。

原因はmicroCMSのデータ不足ではなく、カテゴリーページから共通のMetaコンポーネントへカテゴリ名を渡していなかったことです。pageTitle={name}を追加した後、公開HTMLのtitle、OGP、構造化データに「microCMS」が反映されました。

この記事では、当サイトのmicroCMSとNext.js 15の実装をもとに、記事・一覧・カテゴリーページで確認したいSEO項目をコード例付きで解説します。Googleの生成AI検索を意識したAIOについても、特別なタグを追加するのではなく、Google公式方針に沿って何を整えるべきかをまとめます。

先に結論:microCMSとNext.jsで担当を分ける

microCMSとNext.jsを組み合わせる場合、SEOに必要な情報とHTMLへの出力を分けて考えると、設定漏れを見つけやすくなります。

担当

主な役割

microCMS

記事タイトル、slug、抜粋、アイキャッチ、公開日、カテゴリなどを管理する

Next.js

ページごとのtitle、meta description、canonical、OGP、構造化データをHTMLへ出力する

ビルド・配信環境

記事URLを生成し、サイトマップとrobots.txtを公開する

公開後の確認

公開HTML、HTTPステータス、Search Console、リッチリザルトテストで検証する

SEO設定は「microCMSにフィールドを作れば完了」でも、「Next.jsへ共通のメタタグを一度書けば完了」でもありません。記事、コラム一覧、カテゴリ一覧など、URLを持つテンプレートごとに固有の情報が出力されているか確認します。

確認した環境

この記事では、2026年8月29日時点の次の環境を確認しています。

  • Next.js 15.4.10
  • Pages Router
  • getStaticPathsgetStaticPropsによる静的生成
  • microCMSのリスト形式API
  • 共通のMetaコンポーネントで<head>を生成
  • next-sitemap 4.0.9でサイトマップとrobots.txtを生成

microCMSの記事APIには、タイトル、slug、投稿日、アイキャッチ、カテゴリ、本文、抜粋の各フィールドがあります。記事ページではmicroCMSから取得したデータをgetStaticPropsでpropsへ渡し、MetaコンポーネントからSEO情報を出力しています。

コード例は当サイトで使っているPages Routerを基準にし、公開HTMLの確認で見つけた改善点も反映しています。現行コードの単純な転記ではなく、ページ単位のSEO設定を整える実装例です。App Routerを使う場合の対応は、後半の「App RouterではMetadata APIへ置き換える」で整理します。

1. microCMSにSEOで使うデータを用意する

最初に、ページ固有のSEO情報を作れるフィールドがmicroCMSにあるか確認します。当サイトの記事APIでは、次のデータを使います。

microCMSのフィールド

SEOでの用途

タイトル

<title>og:title、記事見出し、構造化データのheadline

slug

記事URLとcanonical

抜粋

meta description、og:description、構造化データのdescription

アイキャッチ

og:image、構造化データのimage、記事内の画像

投稿日

構造化データのdatePublished、画面上の公開日

カテゴリ

カテゴリーページ、パンくず、関連記事、内部リンク

microCMSが自動で持つrevisedAtは、記事の内容を更新した日時としてdateModifiedに利用できます。表示上の公開日を管理するために独自の投稿日フィールドを使う場合は、publishedAtと混同せず、サイト内で役割を統一します。

抜粋は本文冒頭の機械的な切り取りより、記事の対象と読者が得られる内容を一文で書く方が管理しやすくなります。Googleは検索結果のスニペットを主にページ本文から生成し、ページの説明として適切な場合にmeta descriptionも使用します。各ページに固有で、人が読んで内容を判断できる文章にします。

参考:検索結果のスニペットとmeta description|Google Search Central

2. ページごとにtitleとmeta descriptionを出力する

Pages Routerでは、Next.jsのnext/headを使ってページごとの<head>を定義できます。当サイトでは共通のMetaコンポーネントにページタイトルと説明を渡し、サイト名を含むtitleを生成しています。

import Head from 'next/head'

const siteTitle = 'サイト名'

export default function Meta({ pageTitle, pageDesc }) {
  const title = pageTitle ? `${pageTitle} | ${siteTitle}` : siteTitle

  return (
    <Head>
      <title>{title}</title>
      <meta name="description" content={pageDesc} />
      <meta property="og:title" content={title} />
      <meta property="og:description" content={pageDesc} />
    </Head>
  )
}

記事ページでは記事タイトル、カテゴリーページではカテゴリ名を渡します。

// 記事ページ
<Meta pageTitle={post.title} pageDesc={post.content} />

// カテゴリーページ
<Meta pageTitle={category.name} pageDesc={category.metaDescription} />

<title>は共通コンポーネントだけでなく、呼び出し元の全テンプレートを確認することが重要です。Googleは検索結果のタイトルリンクを、<title>、ページ上の主要見出し、og:title、リンクテキストなどから自動生成します。<title>とH1には同じ主題を持たせ、ページ内容を具体的に表します。

文字数だけで一律に切るのではなく、ページの主題を前半に置き、同じtitleを複数ページで使わない設計にします。

参考:Next.jsのHeadコンポーネントGoogle検索のタイトルリンクに影響を与える方法

カテゴリーページだけtitleが共通値になった原因

当サイトのカテゴリーページでは、microCMSからカテゴリ名とmeta descriptionを取得できていました。画面上の見出しにもカテゴリ名が表示されていたため、データ取得は正常です。

修正前の呼び出しは次の状態でした。

<Meta pageDesc={metaDescription} />

共通のMetaコンポーネントは、pageTitleがない場合にサイト名だけをtitleへ使います。そのため、記事ページなどpageTitleを渡しているページは正しく、カテゴリーページだけ共通titleになっていました。

カテゴリ名を渡すように修正します。

<Meta pageTitle={name} pageDesc={metaDescription} />

修正後の公開HTMLを簡略化すると、次のようにカテゴリ名が反映されます。

<title>microCMS | サイト名</title>
<meta property="og:title" content="microCMS | サイト名">

この問題は共通コンポーネントの不具合ではなく、特定のテンプレートから必要な値を渡していなかったことが原因です。SEO設定を共通化しても、記事、一覧、カテゴリ、固定ページの呼び出し方は個別に確認する必要があります。

3. canonicalはクエリ文字列を除いた正規URLにする

canonicalは、重複または似た内容のURLがあるときに、検索結果へ表示したい代表URLを示すための要素です。Googleはrel="canonical"を強いシグナルとして扱い、正規ページ自身にも自己参照canonicalを設定することを推奨しています。

Next.jsでは現在のパスから絶対URLを作れます。計測用パラメータや絞り込み条件をcanonicalへ含めないため、クエリ文字列とハッシュを除外します。

import { useRouter } from 'next/router'

const siteUrl = 'https://saijo-web.com'

export default function Meta() {
  const router = useRouter()
  const canonicalPath = router.asPath.split(/[?#]/)[0]
  const canonicalUrl = new URL(canonicalPath, siteUrl).toString()

  return (
    <Head>
      <link rel="canonical" href={canonicalUrl} />
      <meta property="og:url" content={canonicalUrl} />
    </Head>
  )
}

公開後は、HTML上のcanonicalが次の条件を満たすか確認します。

  • https://から始まる絶対URLになっている
  • 公開ページ自身のURLを指している
  • プレビューURLやpages.devなどの確認環境を指していない
  • utm_sourceなどの計測用パラメータを含んでいない
  • サイトマップに載せるURLと一致している

canonicalとサイトマップで異なるURLを指定すると、どちらを正規URLとして扱いたいのかが不明確になります。内部リンクも同じ正規URLへそろえます。

参考:canonical URLの指定方法|Google Search Central

4. OGPは記事タイトル・説明・画像・URLをそろえる

OGPはSNSやチャットへURLを共有したときのタイトル、説明、画像に使われます。最低限、og:titleog:descriptionog:urlog:imageをページ固有の値で出力します。

<Head>
  <meta property="og:title" content={title} />
  <meta property="og:description" content={description} />
  <meta property="og:url" content={canonicalUrl} />
  <meta property="og:type" content="article" />
  <meta property="og:image" content={imageUrl} />
  <meta name="twitter:card" content="summary_large_image" />
</Head>

記事にアイキャッチがある場合は、microCMSの画像URLとwidth、heightを共通のMetaコンポーネントへ渡します。画像がない記事だけ共通OGP画像へフォールバックさせると、記事固有の画像を優先できます。

<Meta
  pageTitle={post.title}
  pageDesc={post.content}
  pageImg={post.eyecatch?.url}
  pageImgW={post.eyecatch?.width}
  pageImgH={post.eyecatch?.height}
/>

本文内の画像には、画像の内容と本文中の役割が分かるaltを設定します。Googleは画像そのものに加え、altと周辺の本文から画像の主題を理解します。キーワードの羅列ではなく、画像を見られない人にも意味が伝わる説明にします。

参考:Google画像検索のSEOベストプラクティス

5. 記事ページにはBlogPostingの構造化データを入れる

記事ページでは、本文と一致するBlogPostingのJSON-LDを出力します。構造化データは検索順位を直接上げるための記述ではなく、ページが記事であること、タイトル、画像、公開日、更新日、著者を検索エンジンへ明示するためのデータです。

const blogPosting = {
  '@context': 'https://schema.org',
  '@type': 'BlogPosting',
  mainEntityOfPage: canonicalUrl,
  headline: post.title,
  description: post.content,
  image: post.eyecatch?.url,
  datePublished: post.publishDate || post.publishedAt,
  dateModified: post.revisedAt,
  author: {
    '@type': 'Person',
    name: '西條輝',
    url: 'https://saijo-web.com/about',
  },
}

<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{
    __html: JSON.stringify(blogPosting).replace(/</g, '\\u003c'),
  }}
/>

Next.js公式ドキュメントは、JSON-LDへ外部データを入れる際のXSS対策として、JSON.stringifyした文字列の<をUnicode表現へ置き換える方法を案内しています。microCMSのタイトルや抜粋も外部データなので、値をそのまま文字列連結しません。

GoogleのArticle構造化データでは、headlineimagedatePublisheddateModifiedauthorなどが記事の理解に使われます。JSON-LDに書くタイトル、日付、画像、著者は、画面上の内容と一致させます。

参考:Next.jsでJSON-LDを実装する方法Article構造化データ|Google Search Central

6. サイトマップとrobots.txtをビルド後に確認する

当サイトでは、next buildの後にnext-sitemapを実行し、サイトマップとrobots.txtを生成しています。

{
  "scripts": {
    "build": "next build && next-sitemap"
  }
}
// next-sitemap.config.js
module.exports = {
  siteUrl: 'https://saijo-web.com',
  generateRobotsTxt: true,
}

2026年8月29日に公開ファイルを確認したところ、sitemap-0.xmlにはmicroCMSカテゴリーページと記事ページのURLが掲載され、robots.txtからサイトマップを参照できる状態でした。

サイトマップには、検索結果へ表示したいcanonical URLだけを含めます。Googleへのサイトマップ送信はクロールとインデックス登録の保証ではありませんが、サイト内の重要なURLを検索エンジンへ伝える手段になります。

robots.txtはクロール範囲を制御するファイルです。検索結果へ出したくないページには、robots.txtのDisallowだけで対応せず、ページをクロール可能にしたうえでnoindexを出力するか、認証でアクセスを制限します。下書きプレビューや管理用ページは、本番公開前に扱いを決めておきます。

参考:サイトマップの作成と送信|Google Search Central検索結果へ出す内容の制御方法

7. microCMS公開後は生成されたHTMLを確認する

microCMSの入力画面だけでは、Next.jsが最終的に出力したSEO情報を確認できません。記事を公開してビルドが完了した後、公開URLで次の項目を確認します。

  1. HTTPステータスが200になっている
  2. HTMLソースに固有の<title>とmeta descriptionがある
  3. canonicalとog:urlが公開URLと一致している
  4. og:imageがブラウザから取得できる
  5. 記事ページにBlogPostingのJSON-LDがある
  6. JSON-LDのタイトル、URL、日付、著者が画面上の情報と一致している
  7. robotsのnoindexが意図せず残っていない
  8. サイトマップに公開URLが含まれている

コマンドで確認する場合は、公開HTMLから対象タグを検索できます。

curl -sL https://example.com/column/article-slug \
  | grep -E '<title|description|canonical|og:|application/ld\+json|robots'

構造化データはGoogleのリッチリザルトテスト、クロールとインデックスの状態はSearch ConsoleのURL検査で確認します。Search Consoleでは、Googleが取得したページ、インデックス登録の状態、構造化データのエラーも確認できます。

SSGでは、microCMSでの公開後にNext.jsの再ビルドが終わるまで、新しい記事URLや更新内容は公開サイトへ反映されません。反映されない場合の切り分けは「microCMSの記事が反映されない原因とWebhookの確認手順」で詳しくまとめています。

参考:Search Consoleの利用方法|Google Search Central構造化データの仕組みと検証方法

App RouterではMetadata APIへ置き換える

Next.jsのApp Routerでは、next/headではなくMetadata APIを使います。静的なページはmetadata、microCMSから取得した記事ごとに値を変えるページはgenerateMetadataで定義します。

SEO項目

Pages Router

App Router

title・description

next/head

metadataまたはgenerateMetadata

canonical

<link rel="canonical">

alternates.canonical

OGP

<meta property="og:*">

openGraph

robots

<meta name="robots">

robots

JSON-LD

<script type="application/ld+json">

pageまたはlayout内の<script>

サイトマップ

静的ファイルや生成ツール

app/sitemap.jsまたはsitemap.xml

実装方法は異なっても、「microCMSのデータをページ単位のメタデータへ変換し、公開HTMLで確認する」という考え方は同じです。

参考:Next.jsのgenerateMetadataNext.jsのMetadataとOG画像

AIOでもSEOの基本と一次情報を優先する

AIOを理由に、AI専用のメタタグや構造化データを追加する必要はありません。Googleは、AI OverviewsやAI Modeなどの生成AI検索でも従来のSEOの基本が有効であり、AEOやGEOもGoogle検索の観点ではSEOとして扱うと説明しています。

技術面では、ページをクロールできる状態にし、正しいtitle、canonical、構造化データ、内部リンクを出力します。コンテンツ面では、読者の質問へ先に答え、公式情報と実際の検証結果を区別し、誰がいつ確認した情報なのかを分かるようにします。

この記事でカテゴリーページの修正前後を示したのも、一般的なチェック項目だけで終わらせず、実装でどこが抜けたのかを検証可能な形で残すためです。AI検索向けに短い回答を大量に作るより、次の要素を一つの記事へ過不足なくまとめます。

  • 読者が最初に知りたい結論
  • 対象環境とバージョン
  • 実際に起きた問題と原因
  • 再利用できるコード例
  • 公式ドキュメントへのリンク
  • 公開後に確認する方法
  • 著者、公開日、更新日

Googleは、生成AI検索向けの公式ガイドでも、既存情報の要約だけではない一次体験や独自の分析を重視しています。AIOは文章を不自然に細分化する作業ではなく、人が読みやすく、検索エンジンやAIが根拠を追えるページを作る作業として扱います。

参考:生成AI検索に向けたサイト最適化|Google Search Central有用で信頼できる人中心のコンテンツ

公開前に使うSEOチェックリスト

microCMSの記事を公開する前後に、次の順番で確認します。

microCMSの入力内容

  • □ タイトルが記事の主題を具体的に表している
  • □ slugが確定し、既存記事と重複していない
  • □ 抜粋が記事固有の説明になっている
  • □ アイキャッチが記事内容と一致している
  • □ 投稿日とカテゴリが正しい
  • □ 本文中の外部情報に一次情報へのリンクがある

Next.jsの出力

  • □ 記事、一覧、カテゴリ、固定ページごとに固有のtitleがある
  • □ meta descriptionとog:descriptionがページ内容と一致している
  • □ canonicalとog:urlが同じ公開URLを指している
  • □ 記事のog:typearticleになっている
  • og:imageが絶対URLで取得できる
  • □ 記事ページにBlogPostingがあり、画面上の情報と一致している
  • □ 非公開ページ以外にnoindexが残っていない

ビルド・公開後

  • □ 公開URLが200を返す
  • □ HTMLソースにtitle、description、canonical、OGP、JSON-LDがある
  • □ サイトマップにcanonical URLが載っている
  • □ robots.txtからサイトマップを参照できる
  • □ リッチリザルトテストで構造化データを検証した
  • □ Search ConsoleのURL検査でクロール可能な状態を確認した
  • □ スマートフォン表示とCore Web Vitalsを確認した

microCMSへの記事入稿をAPI経由で進める場合は、「microCMS公式MCPをCodexで使う方法」で接続、記事取得、下書き作成、更新までの流れを検証しています。入稿を自動化しても、公開HTMLの確認は省略しません。

よくある質問

microCMSだけでSEO設定は完了しますか?

完了しません。microCMSはタイトル、抜粋、画像などのデータを管理します。検索エンジンが読む<title>、meta description、canonical、OGP、構造化データは、Next.js側でHTMLへ出力します。

titleを修正すれば検索結果もすぐ変わりますか?

Googleがページを再クロールして処理した後に反映されます。Google公式ドキュメントでは、更新の認識に数日から数週間かかることがあると説明されています。公開HTMLの修正を確認した後、必要なページはSearch Consoleから再クロールをリクエストします。

構造化データを入れれば検索順位は上がりますか?

構造化データはページ内容をGoogleへ明示し、対応する検索表示の対象になるための情報です。正しく実装してもリッチリザルトの表示は保証されず、構造化データ自体を検索順位の上昇と同一視しません。本文と一致する正確なデータを入れ、リッチリザルトテストで検証します。

AIO用にFAQを増やす必要はありますか?

AI検索だけを目的にFAQを増やす必要はありません。本文を読んだ後にも残る具体的な疑問がある場合に追加します。記事の結論、検証環境、根拠、更新日を明確にする方が、読者と検索システムの双方に内容が伝わります。

microCMSとWordPressで、SEO実装や公開方法を含む運用範囲がどのように変わるかは、microCMSとWordPressの比較・実装記事で整理しています。

SSG構成で公開後の内容が反映されない場合は、Webhookと再ビルドの確認手順もあわせて確認してください。

まとめ

microCMSとNext.jsのSEO対策では、コンテンツデータとHTMLへの出力を分けて確認します。microCMSでタイトル、slug、抜粋、画像、日付を管理し、Next.jsでtitle、meta description、canonical、OGP、BlogPostingをページごとに生成します。

当サイトでカテゴリーページだけtitleが共通値になった原因は、カテゴリ名を共通のMetaコンポーネントへ渡していなかったことでした。共通化したSEOコンポーネントが正しくても、テンプレートごとのpropsが欠ければ固有のメタデータは出力されません。

公開前はmicroCMSの入力内容、公開後は生成されたHTML、サイトマップ、robots.txt、構造化データを確認します。この一連の確認を記事・一覧・カテゴリ・固定ページへ適用すれば、ページ単位の実装漏れを防ぎながら、通常の検索と生成AI検索の両方に内容が伝わるサイトを運用できます。

#
執筆者 | 西條輝
1995年生まれ。
Web業界は8年目です。それ以前は、実製品の品質管理などを5年ほど担当していました。
生成AIの進歩で「作ること自体のハードル」は下がったからこそ、現場の課題を丁寧に言葉にし、Webというカタチに落とし込むことが、これからますます重要になると感じています。
X(Twitter)
お問い合わせはこちら

Related Blog