構造化データ(JSON-LD)の書き方
構造化データは、ページの内容を機械が誤解しないように書き添えるメタ情報です。JSON-LD での基本的な書き方を FAQPage・Article・Organization・BreadcrumbList の 4 つに絞って解説し、リッチリザルトが縮小した現在でも書く価値がどこにあるのかを整理します。
構造化データとは何ですか?なぜ必要ですか?
ページの内容を schema.org の語彙で機械可読に書き直したものです。HTML には「この文字列が著者名で、こちらが公開日だ」という情報がありません。構造化データはその対応関係を明示し、機械が推測せずに済むようにします。
HTML のタグが表しているのは見た目の構造だけです。<p>山田太郎</p> という記述からは、それが著者なのか、取材相手なのか、登場人物なのかは分かりません。人間は前後の文脈で判断できますが、機械は推測するしかなく、推測は外れます。
構造化データは、この曖昧さを消すためのものです。author と書いてあれば、それは著者です。推測の余地がありません。AI が引用元を選ぶとき、誰がいつ書いたのかが分かることは重要な判断材料になります。そこを推測に委ねる必要はありません。
期待できる効果と、期待してはいけないこと
| 項目 | 実態 |
|---|---|
| 検索順位が上がる | 上がりません。Google はランキング要因ではないと説明しています |
| リッチリザルトの表示資格 | 得られます。ただし型ごとに状況が異なります(後述) |
| 検索エンジンの内容理解 | 改善します。特に日付・著者・発行元の解釈が確実になります |
| AI の内容理解と引用 | 改善が期待できます。ただし各社の基準は非公開で、保証はありません |
JSON-LD・Microdata のどれで書けばいいですか?
JSON-LD です。Google が推奨しており、HTML のマークアップから完全に独立しているため、デザイン変更で壊れません。既存サイトが Microdata で正しく動いているなら、移行のために書き換える必要はありません。
| 記法 | 書き方 | 評価 |
|---|---|---|
| JSON-LD | script タグに JSON をまとめて書く | 推奨。HTML と分離でき、生成も差し替えも容易 |
| Microdata | HTML の各要素に itemprop 属性を足す | 動作はする。デザイン変更で属性が失われる事故が多い |
| RDFa | HTML の各要素に property 属性を足す | 動作はする。新規採用の理由は乏しい |
JSON-LD が優れているのは、マークアップと切り離せる点です。Microdata は属性を HTML に埋め込むため、テンプレートを触った誰かが div を 1 つ消しただけで構造化データが壊れます。しかも壊れたことに誰も気づきません。 JSON-LD なら 1 か所にまとまっており、レビューも差分確認も容易です。
FAQPage はどう書きますか?
mainEntity に Question を配列で並べ、各 Question に name(質問文)と acceptedAnswer(回答)を必ず入れます。この 2 つのどちらかが欠けると、Q&A として認識されません。
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "サイト診断は無料ですか?",
"acceptedAnswer": {
"@type": "Answer",
"text": "完全無料です。登録もログインも不要で、回数制限もありません。"
}
},
{
"@type": "Question",
"name": "診断対象のサイトに負荷はかかりますか?",
"acceptedAnswer": {
"@type": "Answer",
"text": "ほとんどかかりません。1 回の診断で送るリクエストは最大 12 件、同時接続は 4 本までに制限しています。"
}
}
]
}nameには質問文をそのまま入れる — 「料金について」ではなく「サイト診断は無料ですか?」と、質問の形で書きますacceptedAnswer.textには画面と同じ回答を入れる — 要約したり、画面に無い内容を足したりしてはいけません- 回答に HTML を含めてもよい —
<p>や<a>は使えます。ただし JSON なので、引用符とバックスラッシュのエスケープが必要です - 全ページに貼らない — FAQ が実際に書かれているページにだけ置きます
そして構造化データを書く前に、画面側が Q&A の形になっているかを確認してください。JSON-LD は画面にある内容を機械可読にするものであって、画面に無いものを生やす手段ではありません。詳しくはAI に回答として引用される文章の構造で扱います。
Article はどう書きますか?
headline が必須で、実務上は author・datePublished・dateModified・publisherまでを必ず入れます。AI は「誰がいつ書いたか」を引用の判断材料にするため、日付と著者が欠けている記事は不利になります。
{
"@context": "https://schema.org",
"@type": "TechArticle",
"headline": "構造化データ(JSON-LD)の書き方",
"description": "FAQPage・Article・Organization を JSON-LD で実装する手順。",
"inLanguage": "ja",
"url": "https://example.com/guide/structured-data",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://example.com/guide/structured-data"
},
"datePublished": "2026-07-17T09:00:00+09:00",
"dateModified": "2026-07-17T09:00:00+09:00",
"author": {
"@type": "Organization",
"name": "JIT株式会社",
"url": "https://www.itlibra.com"
},
"publisher": {
"@type": "Organization",
"name": "JIT株式会社",
"url": "https://www.itlibra.com"
}
}| プロパティ | 必須 | 書き方の注意 |
|---|---|---|
| headline | 必須 | 記事タイトル。h1 と一致させる |
| author | 実質必須 | 個人なら Person、組織なら Organization。url も付ける |
| datePublished | 実質必須 | ISO 8601。タイムゾーン付きで書く |
| dateModified | 実質必須 | 実際に更新したときだけ更新する |
| publisher | 推奨 | 発行元。個人ブログでも書ける |
| mainEntityOfPage | 推奨 | この記事の正規 URL。canonical と一致させる |
@type は内容に合わせて選びます。技術解説なら TechArticle、ニュースなら NewsArticle、ブログなら BlogPosting です。いずれも Article のサブタイプなので、Article として認識されます。判断に迷うなら Article で構いません。
Organization と BreadcrumbList はどう書きますか?
Organization は name が必須で、url・logo・sameAs を足します。BreadcrumbList は itemListElement に ListItem を position 順に並べ、各項目へ name と item(URL)を入れます。
Organization はページ種別に関係なく、ほぼ全てのサイトが持つべき数少ない型です。AI は「誰が言っているのか」を引用の判断に使うため、運営者が特定できないサイトはそれだけで不利になります。本ツールが Organization の欠如だけを一律に warn としているのもこの理由からです。
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "JIT株式会社",
"url": "https://www.itlibra.com",
"logo": "https://www.itlibra.com/logo.png",
"sameAs": [
"https://x.com/example",
"https://github.com/example"
]
}{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "ホーム",
"item": "https://example.com"
},
{
"@type": "ListItem",
"position": 2,
"name": "解説",
"item": "https://example.com/guide"
},
{
"@type": "ListItem",
"position": 3,
"name": "構造化データ(JSON-LD)の書き方",
"item": "https://example.com/guide/structured-data"
}
]
}BreadcrumbList は画面に表示しているパンくずと一致させるのが原則です。画面に無い階層を構造化データにだけ書くのはガイドライン違反です。 最後の項目(現在のページ)は item を省略できますが、書いても問題ありません。
複数の型は、どうやって 1 つにまとめますか?
@graph に配列で並べます。script タグを型ごとに分けても動作しますが、@graph なら @idで相互参照でき、重複も避けられます。実務では 1 ページ 1 ブロックにまとめるのが管理しやすい形です。
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "TechArticle",
"@id": "https://example.com/guide/x#article",
"headline": "記事タイトル",
"datePublished": "2026-07-17T09:00:00+09:00",
"author": { "@id": "https://example.com#org" },
"publisher": { "@id": "https://example.com#org" }
},
{
"@type": "BreadcrumbList",
"@id": "https://example.com/guide/x#breadcrumb",
"itemListElement": []
},
{
"@type": "Organization",
"@id": "https://example.com#org",
"name": "JIT株式会社",
"url": "https://www.itlibra.com"
}
]
}@id を付けておくと、author や publisher から { "@id": "..." } という参照だけで指せます。同じ組織情報を 3 回書き写す必要がなくなり、社名を変更したときの直し漏れも起きません。
Next.js ではどう埋め込みますか?
サーバーコンポーネントの中で script タグを直接描画し、dangerouslySetInnerHTML に JSON.stringify の結果を渡します。自前のデータを自前で JSON 化しているだけなので、この用途では安全です。外部から受け取った値を混ぜる場合のみ注意が必要です。
export default function Page() {
const jsonLd = {
"@context": "https://schema.org",
"@graph": [
{
"@type": "TechArticle",
headline: "記事タイトル",
datePublished: "2026-07-17T09:00:00+09:00",
author: { "@type": "Organization", name: "JIT株式会社" },
},
],
};
return (
<>
{/* 自前の値を JSON.stringify しているだけなので安全 */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<article>...</article>
</>
);
}next/script は使わないでください。strategy によっては JavaScript で後から挿入されるため、JS を実行しないクローラーには見えなくなります。構造化データは HTML に最初から入っている必要があります。素の script タグをそのまま書くのが正解です。
書いたものは、どこで検証しますか?
schema.org の記法として正しいかは Schema Markup Validator、Google のリッチリザルト対象になるかはリッチリザルトテストで確認します。この 2 つは目的が違うので、両方を通してください。公開後は Search Console で継続的に監視します。
- Schema Markup Validator(validator.schema.org) — schema.org の語彙として正しいかを検証します。Google 固有の要件は見ません
- リッチリザルトテスト(search.google.com/test/rich-results) — Google のリッチリザルト対象になるかを判定します。必須プロパティの欠落もここで分かります
- Search Console の「拡張」レポート — 公開後、実際にクロールされた結果のエラーが出ます。テンプレートの不具合は、 ここで初めて全ページ分がまとめて見えます
ローカルで手早く確認するなら、HTML から JSON-LD を抜き出して JSON としてパースできるかを見るだけでも、多くの事故は防げます。構文エラーがあるとそのブロック全体が丸ごと無効になるためです。
curl -sL https://example.com/ \
| grep -o '<script type="application/ld+json">.*</script>' \
| sed -e 's/<[^>]*>//g' \
| python -m json.toolやってはいけないことは何ですか?
最も重いのは、画面に表示していない内容を構造化データに書くことです。Google のガイドライン違反であり、手動対策の対象になります。構造化データはページの内容を機械可読にするものであって、内容を水増しする道具ではありません。
- 画面に無い内容を書く — 表示していない FAQ、存在しないレビュー、書いていない著者名。ガイドライン違反です
- 日付を偽る — 更新していないのに
dateModifiedを今日にする行為。鮮度シグナルの偽装であり、AI にとっても検索エンジンにとっても不正確な情報を配ることになります - 末尾カンマを残す — JSON は末尾カンマを許容しません。1 文字でブロック全体が無効になります
- 複数ブロックで矛盾させる — テーマの JSON-LD とプラグインの JSON-LD が別々の
datePublishedを出しているサイトは実在します。どちらが信じられるか分かりません - 全ページに同じ FAQPage を貼る — FAQ が無いページに FAQPage を置くのは、画面に無い内容を書くのと同じことです
- JS で後から挿入する — JS を実行しないクローラーからは、存在しないのと同じです
構造化データは「機械に対して、画面と同じことを、誤解の余地なく言い直す」作業です。この一線を守っている限り、書きすぎて損をすることはありません。 越えた瞬間に、順位を上げるどころか手動対策のリスクを負うことになります。