2026年5月20日
2026年5月20日
WordPressにJSON-LDの構造化データを追加する方法|ArticleとBreadcrumbList
構造化データは、ページの内容(記事の題名・公開日・著者・パンくずの階層など)を検索エンジンが読み取りやすい形で書き添えるものです。Google は JSON-LD・microdata・RDFa の3形式を読み取り、その中で JSON-LD を推奨しています。JSON-LD は <script type="application/ld+json"> の中に JSON で書くため、本文の HTML に手を加えずに追加できます。
この記事では、WordPress の投稿に Article(記事)と BreadcrumbList(パンくずリスト)の JSON-LD を出力するコードを紹介します。Google のプロパティの説明は、2026年10月時点の Google 検索セントラルのドキュメントで確認しています。
追加する前に確認すること
SEOプラグインがすでに出力していないか
Yoast SEO・Rank Math・All in One SEO などの SEO プラグインは、記事やパンくずの構造化データを自動で出力します。同じ種類のデータを自作のコードでも出すと、内容の違う2つのデータが並び、どちらを正とすべきか分かりにくくなります。
まず公開中の記事を開き、ブラウザーの「ページのソースを表示」で application/ld+json を検索してください。すでに Article や BreadcrumbList が出ている場合は、プラグインの設定で調整し、この記事のコードは使わないでください。
構造化データで表示が約束されるわけではない
構造化データは検索エンジンへの手がかりで、追加してもリッチリザルト(検索結果の装飾された表示)が出るとは限りません。また、マークアップはページに実際に表示している内容と一致させる必要があります。Google のガイドラインに反するマークアップは、手動による対策の対象になることがあります。
FAQPage は Google 検索で使われなくなった
以前は FAQPage の構造化データで、検索結果に質問と回答の折りたたみ表示が出ることがありました。Google は2023年にこの表示を政府・医療の権威あるサイトに限り、2026年5月7日からは Google 検索で表示しなくなりました(Google 検索セントラルの FAQ のページによる)。2026年10月時点で、Google のリッチリザルトを目的に FAQPage を追加する意味はありません。
コードを置く場所
以下のコードは、子テーマの functions.php か、コードスニペット用のプラグインに追加します。親テーマの functions.php に書くと、テーマの更新で消えます。編集の前に、ファイルのバックアップを取ってください。
共通の出力関数
JSON-LD を <script> タグとして出力する関数を先に用意します。
<?php
/**
* 配列を JSON-LD の script タグとして出力する。
*/
function wpdr_print_json_ld( array $data ): void {
$json = wp_json_encode(
$data,
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG
);
if ( false === $json ) {
return;
}
echo '<script type="application/ld+json">' . $json . '</script>' . "\n";
}
JSON_HEX_TAG は、データの中の < と > を、JSON の Unicode エスケープ \u003C と \u003E に置き換える指定です(JSON として読み取ると元の文字に戻ります)。これがないと、記事の題名などに </script> という文字列が含まれていた場合に、そこで script タグが閉じてしまいます。JSON_UNESCAPED_UNICODE は日本語を \uXXXX に変換せずそのまま出す指定、JSON_UNESCAPED_SLASHES は URL の / を \/ にしない指定です。
Article(記事)の構造化データ
Google の Article のドキュメントでは、必須のプロパティはなく、次のプロパティが推奨されています。
| プロパティ | 内容 |
|---|---|
headline |
記事の題名 |
datePublished |
公開日時(ISO 8601 形式) |
dateModified |
更新日時(ISO 8601 形式) |
author |
著者(Person または Organization)。name と url を付ける |
image |
記事に関係する画像の URL |
投稿の詳細ページで、これらを出力するコードです。
<?php
add_action( 'wp_head', function (): void {
if ( ! is_singular( 'post' ) ) {
return;
}
$post_id = get_queried_object_id();
$author_id = (int) get_post_field( 'post_author', $post_id );
$data = array(
'@context' => 'https://schema.org',
'@type' => 'Article',
'headline' => wp_strip_all_tags( get_post_field( 'post_title', $post_id ) ),
'datePublished' => get_the_date( 'c', $post_id ),
'dateModified' => get_the_modified_date( 'c', $post_id ),
'mainEntityOfPage' => get_permalink( $post_id ),
'author' => array(
'@type' => 'Person',
'name' => get_the_author_meta( 'display_name', $author_id ),
'url' => get_author_posts_url( $author_id ),
),
'publisher' => array(
'@type' => 'Organization',
'name' => get_bloginfo( 'name' ),
'url' => home_url( '/' ),
),
);
if ( has_post_thumbnail( $post_id ) ) {
$image_url = wp_get_attachment_image_url( get_post_thumbnail_id( $post_id ), 'full' );
if ( $image_url ) {
$data['image'] = array( $image_url );
}
}
wpdr_print_json_ld( $data );
} );
コードのポイントは次のとおりです。
get_the_date( 'c', … )は、サイトのタイムゾーン付きの ISO 8601 形式(例:2026-10-30T09:00:00+09:00)で日時を返します。- 題名は
get_the_title()ではなく、保存されている題名をそのまま取り、HTML タグを除いています。get_the_title()は表示用の整形で&などを文字参照に変えることがあるためです。 author.urlには著者のプロフィールページなど、著者を示すページの URL を入れます。ここでは投稿者アーカイブの URL を使っています。SEO プラグインなどで投稿者アーカイブを無効にしている場合は、表示できるプロフィールページの URL に替えてください。- 画像はアイキャッチ画像のフルサイズを使っています。Google は、記事に関係する高解像度の画像(幅×高さが5万ピクセル以上)を勧めています。ロゴは記事の画像として使わないでください。
@typeは、ブログ記事ならBlogPosting、ニュース記事ならNewsArticleにしてもかまいません。
BreadcrumbList(パンくずリスト)の構造化データ
Google のパンくずのドキュメントでは、BreadcrumbList に ListItem を2つ以上並べ、各 ListItem に position(1から始まる順番)・name・item(URL)を付けます。最後の項目(現在のページ)は item を省略でき、省略すると Google はそのページの URL を使います。
次のコードは「ホーム → カテゴリー(親カテゴリーを含む) → 記事」の階層を出力します。
<?php
add_action( 'wp_head', function (): void {
if ( ! is_singular( 'post' ) ) {
return;
}
$post_id = get_queried_object_id();
$crumbs = array(
array(
'name' => 'ホーム',
'item' => home_url( '/' ),
),
);
$categories = get_the_category( $post_id );
if ( $categories ) {
$category = $categories[0];
$term_ids = array_reverse( get_ancestors( $category->term_id, 'category', 'taxonomy' ) );
$term_ids[] = $category->term_id;
foreach ( $term_ids as $term_id ) {
$term = get_term( $term_id, 'category' );
if ( ! $term instanceof WP_Term ) {
continue;
}
$link = get_term_link( $term );
if ( is_wp_error( $link ) ) {
continue;
}
$crumbs[] = array(
'name' => wp_specialchars_decode( $term->name, ENT_QUOTES ),
'item' => $link,
);
}
}
$crumbs[] = array(
'name' => wp_strip_all_tags( get_post_field( 'post_title', $post_id ) ),
);
$items = array();
foreach ( $crumbs as $index => $crumb ) {
$items[] = array_merge(
array(
'@type' => 'ListItem',
'position' => $index + 1,
),
$crumb
);
}
wpdr_print_json_ld( array(
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => $items,
) );
} );
- 記事に複数のカテゴリーがある場合は、
get_the_category()が返す最初のカテゴリーを使います。ページに表示しているパンくずと同じカテゴリーになるよう、必要に応じて選び方を変えてください。 - 「ホーム」の部分は、ページのパンくずに表示している文言に合わせます。
- カテゴリー名は保存時に
&が&などの文字参照になっているため、wp_specialchars_decode()で元の文字に戻しています。
出力を確かめる
- 記事を開き、「ページのソースを表示」で
application/ld+jsonを検索して、2つの script タグが出ていることと、日本語が読める形で出ていることを確かめます。キャッシュ系のプラグインを使っている場合は、キャッシュを削除してから確認します。 - Google の「リッチリザルト テスト」(
https://search.google.com/test/rich-results)に記事の URL を入れ、Article とパンくずリストがエラーなく検出されるか確かめます。 - schema.org の書き方として正しいかは、「Schema Markup Validator」(
https://validator.schema.org/)でも確認できます。 - 公開後は、Google Search Console の拡張機能のレポートで、パンくずリストのエラーが出ていないかを見ます。
PHP の構文エラーがあるとサイト全体が表示されなくなることがあります。追加後はトップページと記事ページが表示されるか確認し、問題があれば FTP やファイルマネージャーで追加した部分を削除してください。
まとめ
- JSON-LD は
wp_headフックから<script type="application/ld+json">として出力できる。wp_json_encode()にJSON_HEX_TAGを付けて、題名などに含まれる</script>で壊れないようにする。 - Article は
headline・datePublished・dateModified・author(nameとurl)・imageを、BreadcrumbList はposition・name・itemを付ける。 - SEO プラグインがすでに出力している種類は、自作のコードで重ねて出さない。
- FAQPage は2026年5月から Google 検索で表示されなくなっている。