2026年8月18日
2026年8月18日
WordPressにスキーママークアップを実装してSEOを強化する方法
はじめに
スキーママークアップ(構造化データ)を実装することで、Google検索結果にリッチスニペット(評価星・FAQ・パンくずリストなど)が表示され、クリック率(CTR)の向上が期待できます。JSON-LDフォーマットでの実装がGoogleの推奨方式です。
症状・原因
スキーママークアップが必要なケース:
- 検索結果でリッチリザルトを表示させたい
- FAQ・How-to等の特殊なリッチスニペットを取得したい
- 商品ページの価格・在庫・評価を構造化データで伝えたい
- ローカルビジネス情報をGoogleマップと連携させたい
解決手順
ステップ1:基本的なArticleスキーマを実装する
// functions.php
add_action('wp_head', 'output_article_schema');
function output_article_schema(): void {
if (!is_single()) return;
$post = get_post();
if (!$post) return;
$author = get_the_author_meta('display_name', $post->post_author);
$published = get_the_date('c', $post);
$modified = get_the_modified_date('c', $post);
$description = get_the_excerpt($post) ?: wp_trim_words(strip_tags($post->post_content), 30);
$image = get_the_post_thumbnail_url($post, 'large');
$schema = [
'@context' => 'https://schema.org',
'@type' => 'Article',
'headline' => get_the_title($post),
'description' => $description,
'datePublished' => $published,
'dateModified' => $modified,
'author' => [
'@type' => 'Person',
'name' => $author,
'url' => get_author_posts_url($post->post_author),
],
'publisher' => [
'@type' => 'Organization',
'name' => get_bloginfo('name'),
'logo' => [
'@type' => 'ImageObject',
'url' => get_site_icon_url(512) ?: '',
],
],
'mainEntityOfPage' => [
'@type' => 'WebPage',
'@id' => get_permalink($post),
],
];
if ($image) {
$schema['image'] = ['@type' => 'ImageObject', 'url' => $image];
}
// JSON-LDとして出力(HTMLエスケープなし)
printf(
'<script type="application/ld+json">%s</script>' . PHP_EOL,
wp_json_encode($schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)
);
}
ステップ2:FAQPageスキーマを実装する
// FAQページのスキーマ(Gutenbergのよくある質問ブロックと連動)
add_action('wp_head', 'output_faq_schema');
function output_faq_schema(): void {
if (!is_singular()) return;
$post = get_post();
// カスタムフィールドからFAQデータを取得
$faqs = get_post_meta($post->ID, '_faq_items', true);
if (empty($faqs) || !is_array($faqs)) {
// 本文からdetails/summaryタグを自動抽出
preg_match_all(
'/<summary[^>]*>(.*?)<\/summary>\s*<(?:div|p)[^>]*>(.*?)<\/(?:div|p)>/is',
$post->post_content,
$matches
);
if (empty($matches[1])) return;
foreach ($matches[1] as $i => $question) {
$faqs[] = [
'question' => strip_tags($question),
'answer' => strip_tags($matches[2][$i] ?? ''),
];
}
}
if (empty($faqs)) return;
$schema = [
'@context' => 'https://schema.org',
'@type' => 'FAQPage',
'mainEntity' => array_map(function($faq) {
return [
'@type' => 'Question',
'name' => $faq['question'],
'acceptedAnswer' => [
'@type' => 'Answer',
'text' => $faq['answer'],
],
];
}, $faqs),
];
printf(
'<script type="application/ld+json">%s</script>' . PHP_EOL,
wp_json_encode($schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
);
}
ステップ3:BreadcrumbListスキーマを実装する
// パンくずリストのスキーマ
add_action('wp_head', 'output_breadcrumb_schema');
function output_breadcrumb_schema(): void {
$items = [];
$pos = 1;
// ホーム
$items[] = [
'@type' => 'ListItem',
'position' => $pos++,
'name' => 'ホーム',
'item' => home_url('/'),
];
if (is_singular('post')) {
$cat = get_the_category();
if ($cat) {
$items[] = [
'@type' => 'ListItem',
'position' => $pos++,
'name' => $cat[0]->name,
'item' => get_category_link($cat[0]->term_id),
];
}
$items[] = [
'@type' => 'ListItem',
'position' => $pos++,
'name' => get_the_title(),
'item' => get_permalink(),
];
} elseif (is_category()) {
$items[] = [
'@type' => 'ListItem',
'position' => $pos++,
'name' => single_cat_title('', false),
'item' => get_category_link(get_queried_object_id()),
];
}
if (count($items) <= 1) return; // ホームのみなら出力しない
$schema = [
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => $items,
];
printf(
'<script type="application/ld+json">%s</script>' . PHP_EOL,
wp_json_encode($schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
);
}
ステップ4:Productスキーマを実装する
// 商品ページのスキーマ
add_action('wp_head', 'output_product_schema');
function output_product_schema(): void {
if (!is_singular('product')) return;
$post = get_post();
$price = get_post_meta($post->ID, '_product_price', true);
$stock = get_post_meta($post->ID, '_product_stock', true);
$sku = get_post_meta($post->ID, '_product_sku', true);
$schema = [
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => get_the_title($post),
'description' => get_the_excerpt($post),
'image' => get_the_post_thumbnail_url($post, 'large') ?: '',
'sku' => $sku ?: '',
'brand' => [
'@type' => 'Brand',
'name' => get_bloginfo('name'),
],
];
if ($price) {
$schema['offers'] = [
'@type' => 'Offer',
'price' => (float)$price,
'priceCurrency' => 'JPY',
'availability' => ($stock > 0)
? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock',
'url' => get_permalink($post),
];
}
printf(
'<script type="application/ld+json">%s</script>' . PHP_EOL,
wp_json_encode($schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
);
}
ステップ5:Google Rich Results Testで確認する
# WP-CLIで特定ページのスキーマを確認
wp eval "
add_action('wp_head', function() {}, 99999);
\$post = get_post(123);
setup_postdata(\$post);
do_action('wp_head');
"
# curlでJSON-LDを抽出して確認
curl -s https://example.com/post/123 | \
grep -A 50 'application/ld+json' | \
head -60
# Google Rich Results Test APIを使う
curl -s "https://searchconsole.googleapis.com/v1/urlTestingTools/mobileFriendlyTest:run" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/post/123"}'
注意事項
- スキーマのデータは実際に表示されているコンテンツと一致させてください(ガイドライン違反になります)
JSON_UNESCAPED_UNICODEを使わないと日本語が形式になります- 複数のスキーマが必要な場合は配列形式で1つの
タグにまとめることもできます
まとめ
スキーママークアップの実装は、①wp_headフックでJSON-LDを出力、②Article・FAQ・BreadcrumbList・Productの各スキーマを適切なページで出力、③wp_json_encode()でUnicode対応JSON生成、④Google Rich Results Testで検証の流れで実装します。