WordPressで構造化データをマークアップする

WordPressで構造化データをマークアップする

SEO対策における施策の一つに、Googleが推奨する「構造化データマークアップ」があります。

構造化データに関する基礎的なナレッジと、実際にマークアップする方法について解説します。

構造化データとは

構造化データは、検索エンジンが各ページの内容を理解しやすくするために記述する書式です。ページ上の見た目には表示されず、ロボットにだけ伝わる書式で記述します。

検索結果上の表示への影響が大きいため、SEO対策に力を入れたい場合は取り入れておいて損のない書式です。

構造化データをマークアップするメリット

クロール効率が良くなる

検索エンジンのクローラーは、実際に様々なページのソースコードを取得して内容を把握してランキングの参考にします。しかし膨大な数のページをクロールするため、すべてのページを上から下まで全部読めるわけではありません。

構造化データを用意しておき、クローラーがそこさえ読めばページの概要をある程度把握できるようにしておけば、結果としてSEO対策における有利な結果につながる可能性があります。

リッチスニペットの表示をある程度コントロールできる

GoogleやYahoo!などの検索結果画面では、さまざまな情報が表示されます。

単純に記事のタイトルだけではなく、例えば更新日や公開日、記事中で使用されている動画、Q&Aのような項目など多岐にわたります。

それらは「リッチスニペット」と呼ばれるのですが、構造化データとして情報を記述することで表示をある程度コントロールできます。

構造化データの書き方・書式

JSON-LD

JavaScript Object Notation for Linked Dataの略称。Googleが推奨している、構造化データをマークアップする際にもっともベーシックな書式です。

とくに理由がない限りはJSON-LDで記述しておけば良いのではないでしょうか。

ページの表示には影響せず、PHPなどでプログラム的に生成しやすいため、同じ種類のページには同じように構造化データをマークアップしたいWordPressサイトなどで多く活用されています。

Microdata

HTMLタグの中に直接構造化データを埋め込む形式があります。

itemscope、itemtype、itempropなどのHTML属性をつかって、実際のHTMLの内容をそのまま構造化データとして使えるため、LPなどの静的なWebサイトで使われることがあります。

RDFa

Resource Description Framework in Attributesの略称。

HTML5やXHTMLのタグ内に構造化データを埋め込む形式です。Microdataと似ていますが、より複雑なデータモデルを記述できる特徴があります。

例えば学術系のポータルサイト、政府のデータベースなど、ページごとのデータの相互運用が必要なページで活用されています。

代表的な構造化データの種類

よく採用される構造化データの種類をご紹介します。

Organization

そのページを運営する組織をあらわす構造化データです。下記のような形式になります。

{
"@type":"Organization",
"@id":"https://dawny.org#organization",
"name":"DAWNY",
"url":"https://dawny.org"
}

Website

ホームページであることを示す構造化データです。トップページにだけ記述することがおすすめです。下記のような形式になります。

{
"@type":"WebSite",
"@id":"https://dawny.org#website",
"url":"https://dawny.org",
"name":"DAWNY"
}

BlogPosting

投稿ページなどの下層ページではArticleやBlogPostingがよく使用されますが、個人的には著者や公開日、更新日などを一緒に含められるBlogPostingがおすすめです。

下記のような形式になります。

{
 "@type":"BlogPosting",
 "headline":"Hello world!",
 "datePublished":"2024-09-28T00:39:00+09:00",
 "dateModified":"2024-09-28T00:39:00+09:00",
 "mainEntityOfPage":
  {
   "@type":"WebPage",
   "@id":"https://dawny.org/?p=1"
  },
 "author":
  {
   "@type":"Person",
   "name":"たくろー"
  }
}

そのページの階層を示す構造化データです。基本的には全ページで出力されるようマークアップしておくのがおすすめです。下記のような形式になります。

{
"@type":"BreadcrumbList",
"@id":"https://dawny.org#breadcrumb",
"itemListElement":
 [{
   "@type":"ListItem",
   "position":1,
   "item":{
    "name":"Home",
    "@id":"https://dawny.org"
   }
  },
 {
  "@type":"ListItem",
  "position":2,
  "item":{
   "name":"Uncategorized",
   "@id":"https://dawny.org/?cat=1"
  }
 },
 {
  "@type":"ListItem",
  "position":3,
  "item":{
   "name":"Hello world!",
   "@id":"https://dawny.org/?p=1"
  }
 }
}

WordPressで構造化データをマークアップする方法

WordPressで構造化データをマークアップする際、HTMLに直接書いてもいいのですが、PHPでプログラム的に実装してしまった方が効率よく運用できます。

つまりJSON-LD形式が最適です。

プラグインで使用する方法と、テーマファイル内でコードを記述して実装する方法をご紹介します。

プラグインを使用する

導入することで、構造化データをマークアップできるプラグインが存在します。

それぞれ機能や対応範囲が異なりますので、自身のWebサイトに導入したい構造化データに対応しているプラグインを選びましょう。

テーマファイルにコードを追加する

テーマファイルにコードを追加することでも、構造化データを出力することができます。

当テーマのDAWNYでは、schema.phpに下記の記述をして読み込んでいます。

<?php
if (!defined('ABSPATH')) exit;

function output_schema_data() {
    $site_url = get_home_url();
    $site_name = get_bloginfo('name');
    $site_description = get_bloginfo('description');
    $current_title = get_the_title();
    $current_description = has_excerpt() ? get_the_excerpt() : '';
	
	if (is_archive() || is_category() || is_tag() || is_tax()) {
        $current_url = get_archive_url(); // アーカイブ用URL
        $current_title = wp_strip_all_tags(remove_prefix_from_archive_title(get_the_archive_title())); // アーカイブタイトルからプレフィックスとHTMLタグを削除
        $current_description = wp_strip_all_tags(get_the_archive_description()); // アーカイブ説明からHTMLタグを削除
    } else {
        $current_url = get_permalink(); // その他のページ用URL
        $current_title = get_the_title();
        $current_description = has_excerpt() ? get_the_excerpt() : '';
    }
    
    $schema_data = [
        "@context" => "https://schema.org",
        "@graph" => [
            [
                "@type" => "Organization",
                "@id" => $site_url . "#organization",
                "name" => $site_name,
                "url" => $site_url
            ]
        ]
    ];

    // トップページの場合のみ WebSite スキーマを追加
    if (is_front_page()) {
        $schema_data["@graph"][] = [
            "@type" => "WebSite",
            "@id" => $site_url . "#website",
            "url" => $site_url,
            "name" => $site_name . " - " . $site_description
        ];
    }

    // パンくずリスト
    $position = 2;  // ホームページの後から開始
    $breadcrumbs = [
        "@type" => "BreadcrumbList",
		"@id" => $site_url . "#breadcrumb",
        "itemListElement" => [
            [
                "@type" => "ListItem",
                "position" => 1,
                "item" => [
                    "name" => "Home",
                    "@id" => $site_url
                ]
            ]
        ]
    ];

    if (is_single() || is_page() || is_archive()) {
        // カテゴリー
        if (is_single()) {
            $categories = get_the_category();
            if (!empty($categories)) {
                $category = $categories[0];  // IDが一番若いカテゴリーを取得
                $ancestors = get_ancestors($category->term_id, 'category');
                foreach (array_reverse($ancestors) as $ancestor) {
                    $ancestor_category = get_term_by('id', $ancestor, 'category');
                    $breadcrumbs["itemListElement"][] = [
                        "@type" => "ListItem",
                        "position" => $position++,
                        "item" => [
                            "name" => $ancestor_category->name,
                            "@id" => get_category_link($ancestor_category->term_id)
                        ]
                    ];
                }
                // 現在のカテゴリー
                $breadcrumbs["itemListElement"][] = [
                    "@type" => "ListItem",
                    "position" => $position++,
                    "item" => [
                        "name" => $category->name,
                        "@id" => get_category_link($category->term_id)
                    ]
                ];
            }

            // ブログ記事としての情報
            $published = get_the_time('c');
            $modified = get_the_modified_time('c');
            
            $schema_data["@graph"][] = [
                "@type" => "BlogPosting",
                "headline" => $current_title,
                "datePublished" => $published,
                "dateModified" => $modified,
                "mainEntityOfPage" => [
                    "@type" => "WebPage",
                    "@id" => $current_url
                ],
                "author" => [
                    "@type" => "Person",
                    "name" => get_the_author()
                ]
            ];
        }

        // 現在のページ
        $breadcrumbs["itemListElement"][] = [
            "@type" => "ListItem",
            "position" => $position,
            "item" => [
                "name" => $current_title,
                "@id" => $current_url
            ]
        ];
    }

    $schema_data["@graph"][] = $breadcrumbs;

    echo '<script type="application/ld+json">' . json_encode($schema_data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . '</script>';
}

add_action('wp_footer', 'output_schema_data');

//アーカイブページのURLを取得する関数
function get_archive_url() {
    if (is_category() || is_tag() || is_tax()) {
        $term = get_queried_object();
        return get_term_link($term);
    } elseif (is_post_type_archive()) {
        return get_post_type_archive_link(get_post_type());
    } elseif (is_author()) {
        return get_author_posts_url(get_queried_object_id());
    } elseif (is_date()) {
        return get_day_link(get_query_var('year'), get_query_var('monthnum'), get_query_var('day'));
    }

    return home_url('/');
}
?>

詳しい内容については、仕様書で解説します。

構造化データが反映されているかテストする方法

構造化データは見た目に反映されませんから、記述ミスがないかテストしておくことが大切です。

その際はGoogleが提供するスキーママークアップ検証ツールを使用します。

公開されているページであれば、URLを入力すれば自動で判定してくれます。ローカルで構築している場合は、ソースコードからスニペット部分を拾ってきて入力しましょう。

テスト結果は下記のように表示され、エラーが出ているか否かが確認できます。

DAWNYの構造化データについて

当テーマDAWNYで自動出力している構造化データをカスタマイズする方法などは、別途解説記事を制作する予定です。お楽しみに。