microCMSの記事が反映されない原因|Webhookと再ビルドを実測
VIEW →
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を組み合わせる場合、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日時点の次の環境を確認しています。
getStaticPathsとgetStaticPropsによる静的生成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へ置き換える」で整理します。
最初に、ページ固有のSEO情報を作れるフィールドがmicroCMSにあるか確認します。当サイトの記事APIでは、次のデータを使います。
microCMSのフィールド | SEOでの用途 |
|---|---|
タイトル |
|
slug | 記事URLとcanonical |
抜粋 | meta description、 |
アイキャッチ |
|
投稿日 | 構造化データの |
カテゴリ | カテゴリーページ、パンくず、関連記事、内部リンク |
microCMSが自動で持つrevisedAtは、記事の内容を更新した日時としてdateModifiedに利用できます。表示上の公開日を管理するために独自の投稿日フィールドを使う場合は、publishedAtと混同せず、サイト内で役割を統一します。
抜粋は本文冒頭の機械的な切り取りより、記事の対象と読者が得られる内容を一文で書く方が管理しやすくなります。Googleは検索結果のスニペットを主にページ本文から生成し、ページの説明として適切な場合にmeta descriptionも使用します。各ページに固有で、人が読んで内容を判断できる文章にします。
参考:検索結果のスニペットとmeta description|Google Search Central
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検索のタイトルリンクに影響を与える方法
当サイトのカテゴリーページでは、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設定を共通化しても、記事、一覧、カテゴリ、固定ページの呼び出し方は個別に確認する必要があります。
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になっているpages.devなどの確認環境を指していないutm_sourceなどの計測用パラメータを含んでいないcanonicalとサイトマップで異なるURLを指定すると、どちらを正規URLとして扱いたいのかが不明確になります。内部リンクも同じ正規URLへそろえます。
参考:canonical URLの指定方法|Google Search Central
OGPはSNSやチャットへURLを共有したときのタイトル、説明、画像に使われます。最低限、og:title、og:description、og:url、og: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と周辺の本文から画像の主題を理解します。キーワードの羅列ではなく、画像を見られない人にも意味が伝わる説明にします。
記事ページでは、本文と一致する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構造化データでは、headline、image、datePublished、dateModified、authorなどが記事の理解に使われます。JSON-LDに書くタイトル、日付、画像、著者は、画面上の内容と一致させます。
参考:Next.jsでJSON-LDを実装する方法/Article構造化データ|Google Search Central
当サイトでは、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/検索結果へ出す内容の制御方法
microCMSの入力画面だけでは、Next.jsが最終的に出力したSEO情報を確認できません。記事を公開してビルドが完了した後、公開URLで次の項目を確認します。
200になっている<title>とmeta descriptionがあるog:urlが公開URLと一致しているog:imageがブラウザから取得できるBlogPostingのJSON-LDがあるnoindexが意図せず残っていないコマンドで確認する場合は、公開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/構造化データの仕組みと検証方法
Next.jsのApp Routerでは、next/headではなくMetadata APIを使います。静的なページはmetadata、microCMSから取得した記事ごとに値を変えるページはgenerateMetadataで定義します。
SEO項目 | Pages Router | App Router |
|---|---|---|
title・description |
|
|
canonical |
|
|
OGP |
|
|
robots |
|
|
JSON-LD |
| pageまたはlayout内の |
サイトマップ | 静的ファイルや生成ツール |
|
実装方法は異なっても、「microCMSのデータをページ単位のメタデータへ変換し、公開HTMLで確認する」という考え方は同じです。
参考:Next.jsのgenerateMetadata/Next.jsのMetadataとOG画像
AIOを理由に、AI専用のメタタグや構造化データを追加する必要はありません。Googleは、AI OverviewsやAI Modeなどの生成AI検索でも従来のSEOの基本が有効であり、AEOやGEOもGoogle検索の観点ではSEOとして扱うと説明しています。
技術面では、ページをクロールできる状態にし、正しいtitle、canonical、構造化データ、内部リンクを出力します。コンテンツ面では、読者の質問へ先に答え、公式情報と実際の検証結果を区別し、誰がいつ確認した情報なのかを分かるようにします。
この記事でカテゴリーページの修正前後を示したのも、一般的なチェック項目だけで終わらせず、実装でどこが抜けたのかを検証可能な形で残すためです。AI検索向けに短い回答を大量に作るより、次の要素を一つの記事へ過不足なくまとめます。
Googleは、生成AI検索向けの公式ガイドでも、既存情報の要約だけではない一次体験や独自の分析を重視しています。AIOは文章を不自然に細分化する作業ではなく、人が読みやすく、検索エンジンやAIが根拠を追えるページを作る作業として扱います。
参考:生成AI検索に向けたサイト最適化|Google Search Central/有用で信頼できる人中心のコンテンツ
microCMSの記事を公開する前後に、次の順番で確認します。
og:descriptionがページ内容と一致しているog:urlが同じ公開URLを指しているog:typeがarticleになっているog:imageが絶対URLで取得できるBlogPostingがあり、画面上の情報と一致しているnoindexが残っていない200を返すmicroCMSへの記事入稿をAPI経由で進める場合は、「microCMS公式MCPをCodexで使う方法」で接続、記事取得、下書き作成、更新までの流れを検証しています。入稿を自動化しても、公開HTMLの確認は省略しません。
完了しません。microCMSはタイトル、抜粋、画像などのデータを管理します。検索エンジンが読む<title>、meta description、canonical、OGP、構造化データは、Next.js側でHTMLへ出力します。
Googleがページを再クロールして処理した後に反映されます。Google公式ドキュメントでは、更新の認識に数日から数週間かかることがあると説明されています。公開HTMLの修正を確認した後、必要なページはSearch Consoleから再クロールをリクエストします。
構造化データはページ内容をGoogleへ明示し、対応する検索表示の対象になるための情報です。正しく実装してもリッチリザルトの表示は保証されず、構造化データ自体を検索順位の上昇と同一視しません。本文と一致する正確なデータを入れ、リッチリザルトテストで検証します。
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検索の両方に内容が伝わるサイトを運用できます。
