WordPressでLLMO対策!SEO効果を高めるページごとの構造化データの切り分け



生成AI時代におけるSEO対策は、従来のSEO対策に加え、生成AIやLLM(大規模言語モデル)にも適したコンテンツ制作と情報伝達が重要になります。
つまり、SEOと並行してLLMO(大規模言語モデル最適化)への対策も必要不可欠となってきます。

LLMOとは、大規模言語モデル(LLM)が情報を理解しやすいように、Webサイトを最適化することです。
LLMとは、大量のテキストデータを学習することで、人間のような自然な文章を生成したり、質問に答えたり、翻訳したりできる人工知能モデルのことです。
WebサイトをLLMが理解しやすい構造やコンテンツにすることで、生成AIの回答における引用元としての選ばれやすくなります。

LLMOは、従来の検索エンジン最適化(SEO)に加え、ChatGPTなどの生成AIが情報を参照・活用しやすいようにWebサイトを調整し、サイトへの流入増加を目指すことができます。
AI検索時代においては、AIによる情報収集が普及する中で、WebサイトがAIに適切に評価され、ユーザーに提示されるように最適化する施策になります。

LLMは、JSON-LDという形式で整理されたデータを読み解き、必要な情報をピンポイントで取り出すことができます。これにより、構造化されたデータが持つ価値を最大限に引き出すことが可能になります。JSON-LDは、ウェブ上の多岐にわたる情報を整理し、相互に関連付けるための技術で、このJSON-LDによって構造化された情報を学習し、より精度の高い、かつ広範囲にわたる知識を習得できます。
LLMが効果的に私たちの情報を学習して利用してもらうには、JSON-LD形式でLLMが理解しやすいかたちで情報を整理・提供する必要があります。

JSON-LD形式の構造化データは、該当するWebページのファイルのhead要素内にscriptタグを使って記述していくことになりますが、WordPressなどの共通のヘッダーを読み込んでいる場合は、ページごとに適切な情報をマークアップすることが難しくなります。

検索エンジンに正確な情報を伝えるには、トップページや固定ページ、投稿ページなど、ページごとに適切な情報をマークアップしていきたいところです。
ここでは、WordPressサイトでJSON-LD形式の構造化データを、ページごとで切り分ける方法についてご紹介します。

今回ご紹介する方法はプラグインは使用しません。functions.phpの記述で対応する方法となります。
WordPressのfunctions.phpを編集していきますが、編集を間違えるとWordPressが動かなくなる可能性があるので、必ず事前にバックアップをとってから作業を行うようにしてください。

WordPressでのLLMO対策


JSON-LD形式は、ウェブ上の情報を機械が理解しやすい形で表現するための重要な技術で、LLMはこの形式で構造化された情報を活用することで、より高度な情報処理や知識獲得が可能になります。
JSON-LD形式では、Schema.orgが定めたルールに従って情報を記述していきます。
Schema.orgは、Google、Microsoft、Yahoo!といった主要な検索エンジンが共同で開発した、構造化データのための共通規格であり、これにより検索エンジンにウェブページの内容を正確に伝えることができます。

例えば、企業または個人事業のWebサイトのトップページには、以下のような情報を構造化して伝える必要があります。

<script type="application/ld+json">
{
  "@context": "https://schema.org/",
  "@type": "Person",
  "name": "AKIRA",
  "url": "https://nuovasfida.com/",
  "image": "https://nuovasfida.com/atons/wp-content/themes/nuovasfida/img/about/profile.png",
  "description": "Web制作、マーケティング、サイトの運用・保守、サーバーやドメイン管理まで幅広くお受けします。ITの分野で様々な業界のビジネスをサポート。",
  "jobTitle": "Web制作 / マーケティング / コンサルティング",
  "worksFor": {
    "@type": "Organization",
    "name": "NUOVA SFIDA"
  },
  "contactPoint": {
    "@type": "ContactPoint",
    "email": "akira@nuovasfida.com"
  },
  "sameAs": [
    "https://x.com/NUOVASFIDA",
    "https://www.facebook.com/nuovasfida/",
    "https://www.instagram.com/nuovasfida/",
    "https://www.threads.net/@nuovasfida",
    "https://bsky.app/profile/nuovasfida.com"
  ]
}
</script>


scriptタグを使いtype属性を「application/ld+json」として、「@context」「@type」のほか、「name」「url」「description」など、プロパティを指定して構造化データを記述していきます。

ただ、これを共通のheader.phpのhead要素内に記述しても、すべてのページで同じ情報となってしまいます。

ページごとの構造化データの切り分け


WordPressで構築したサイトでは、トップページや固定ページのほか、ニュースやお知らせ、プレスリリース、ブログなど、一つ一つの記事ごとで、説明文は変わりますし、運用方法によっては著者も変わります。
各ページごとで適切な情報を伝えるには、効果的に構造化データを切り分ける必要があります。

ここからは、JSON-LD形式の構造化データを、ページごとで切り分ける方法について見ていきます。

まずは、ページごとの構造化データのサンプルを見ておきましょう。
Webサイトのトップページでは、下記のようにJSON-LD形式で記述します。

<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "Organization",
  "name": "〇〇株式会社",
  "url": "https://example.com/",
  "sameAs": [
    "https://x.com/example",
    "https://www.instagram.com/example/"
  ],
  "email": "info@example.com",
  "telephone": "+81-123-456-7890",
}
</script>


記事(投稿ページ)であれば下記のように記述します。

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "https://example.com/post/article-title/"
  },
  "headline": "記事のタイトル",
  "image": [
    "https://example.com/images/article-thumbnail.jpg"
  ],
  "datePublished": "2023-10-27T10:00:00+09:00",
  "dateModified": "2023-10-27T12:00:00+09:00",
  "author": {
    "@type": "Person",
    "name": "著者名"
  },
  "publisher": {
    "@type": "Organization",
    "name": "ウェブサイト名",
    "logo": {
      "@type": "ImageObject",
      "url": "https://example.com/images/logo.png"
    }
  },
  "description": "記事の概要"
}
</script>


また、固定ページであれば下記のような構造化データを記述する必要があります。

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "WebPage",
  "url": "https://example.com/page/about/",
  "name": "固定ページタイトル",
  "description": "固定ページの説明"
}
</script>



これらをページに合わせて記述する必要があります。
上記はあくまでサンプルですので、必要に応じて適切な情報を追加することになります。

functions.phpでのページごとの切り分け


企業や個人事業、また個人ブログなど、様々なパターンでサンプルをご紹介します。
基本的な流れとして、functions.phpにて関数を作成し、ページごとに切り分ける処理を実行していきます。

まずは、企業や個人事業など事業者向けです。
以下がベースとなります。

functions.php

function add_json_ld_business() {
  $site_name = '〇〇株式会社'; // 事業者名
  $site_url = 'https://example.com/'; // サイトURL

  if ( is_front_page() || is_home() ) {
      // トップページのJSON-LD
      $json_ld = array(
          "@context" => "https://schema.org",
          "@type" => "WebSite",
          "url" => $site_url,
          "name" => $site_name,
          "potentialAction" => array(
              "@type" => "SearchAction",
              "target" => $site_url . '?s={search_term_string}',
              "query-input" => "required name=search_term_string"
          )
      );
  } elseif ( is_page( 'about' ) ) {
      // 固定ページ(会社概要など)のJSON-LD
      $json_ld = array(
          "@context" => "https://schema.org",
          "@type" => "Organization",
          "name" => $site_name,
          "url" => $site_url,
          "logo" => get_site_icon_url(), // サイトアイコンURLを使用
          "description" => get_the_content(), // 固定ページの内容を説明として使用
          // ... (必要に応じて他のプロパティを追加)
      );
  } elseif ( is_singular( 'post' ) ) {
      // 投稿ページのJSON-LD(ブログ記事など)
      // ... (ブログ記事用のJSON-LD)
  } else {
      // その他のページのJSON-LD
      // ... (必要に応じて設定)
  }

  if ( ! empty( $json_ld ) ) {
      echo '<script type="application/ld+json">' . json_encode( $json_ld, JSON_UNESCAPED_UNICODE ) . '</script>';
  }
}
add_action( 'wp_head', 'add_json_ld_business' );


add_json_ld_businessという関数を作成して処理を実行する流れになります。
サイト名やサイトURLは、変数で管理しておくといいでしょう。
サイトアイコンであったりディスクリプションなどの情報は、WordPressの関数を使って出力していくことになります。
「is_front_page() || is_home()」でトップページ、is_page()で固定ページの情報を記述しています。
is_singular()は、ニュースやお知らせ、プレスリリースなど、カスタム投稿ごとで切り分けることができます。
if文では、$json_ldという変数が空でない場合に、JSON-LD形式のデータをHTMLのscriptタグ内に出力します。
最後に、wp_headのアクションフックで、add_json_ld_businessの処理をheadに出力します。

これで、Webサイトのトップページ、固定ページ、投稿ページなど、ページごとでJSON-LDを切り分けることができます。

もう少し具体的に見ていきますと、以下のような記述になります。
まずは法人の場合で見ていきます。

functions.php(法人)

function add_json_ld_business() {
  $site_name = '〇〇株式会社'; // 事業者名
  $site_url = 'https://example.com/'; // サイトURL

  if ( is_front_page() || is_home() ) {
      // トップページのJSON-LD
      $description = get_bloginfo('description'); // WordPressのサイト説明を使用
      $json_ld = array(
          "@context" => "https://schema.org",
          "@type" => "WebSite",
          "url" => $site_url,
          "name" => $site_name,
          "description" => $description,
          "potentialAction" => array(
              "@type" => "SearchAction",
              "target" => $site_url . '?s={search_term_string}',
              "query-input" => "required name=search_term_string"
          )
      );
  } elseif ( is_page( 'about' ) ) {
      // 固定ページ(会社概要など)のJSON-LD
      $description = wp_strip_all_tags(get_the_excerpt(get_the_ID())); // 固定ページの抜粋を使用
      $json_ld = array(
          "@context" => "https://schema.org",
          "@type" => "Organization",
          "name" => $site_name,
          "url" => $site_url,
          "logo" => get_site_icon_url(), // サイトアイコンURLを使用
          "description" => $description,
          // ... (必要に応じて他のプロパティを追加)
      );
  } elseif ( is_singular( 'news' ) ) {
      // 投稿ページのJSON-LD(ブログ記事など)
      $description = wp_strip_all_tags(get_the_excerpt(get_the_ID())); // 投稿ページの抜粋を使用
      $json_ld = array(
          "@context" => "https://schema.org",
          "@type" => "BlogPosting", // BlogPostingを使用
          "mainEntityOfPage" => array(
              "@type" => "WebPage",
              "@id" => get_permalink(get_the_ID())
          ),
          "headline" => get_the_title(get_the_ID()),
          "image" => array(get_the_post_thumbnail_url(get_the_ID(), 'full')),
          "datePublished" => get_the_date('c', get_the_ID()),
          "dateModified" => get_the_modified_date('c', get_the_ID()),
          "author" => array(
              "@type" => "Person", // 著者
              "name" => get_the_author_meta('display_name', get_post_field('post_author', get_the_ID())),
              "url" => get_author_posts_url(get_post_field('post_author', get_the_ID())) // 著者アーカイブURL
          ),
          "publisher" => array(
              "@type" => "Organization",
              "name" => $site_name,
              "logo" => array(
                  "@type" => "ImageObject",
                  "url" => get_site_icon_url()
              )
          ),
          "description" => $description,
      );
  } else {
      // その他のページのJSON-LD
      $description = get_bloginfo('description'); // WordPressのサイト説明を使用
      $json_ld = array(
          "@context" => "https://schema.org",
          "description" => $description,
      );
  }

  if (!empty($json_ld)) {
      echo '<script type="application/ld+json">' . json_encode($json_ld, JSON_UNESCAPED_UNICODE) . '</script>';
  }
}
add_action('wp_head', 'add_json_ld_business');


aboutページの”@type”は、Organizationとするのが適切でしょう。
その他のページのJSON-LDは、それ以外のページは共通で設定してもよい情報としてください。トップページと同じで構いませんし、少しプロパティを追加してもいいです。

個人事業でWebサイトの他にブログを運用している場合には、ブログ名と個人名、事業者名の情報を変数で管理するといいでしょう。
関数名は「add_json_ld」とします。

functions.php(個人)

function add_json_ld() {
  $site_name = '〇〇ブログ';
  $author_name = '山田太郎';
  $business_name = '〇〇デザイン';

  if ( is_front_page() || is_home() ) {
      // トップページ(ホームページ/投稿ページ)のJSON-LD
      $json_ld = array(
          "@context" => "https://schema.org",
          "@type" => "WebSite",
          "url" => home_url(),
          "name" => $site_name,
          "potentialAction" => array(
              "@type" => "SearchAction",
              "target" => home_url( '/?s={search_term_string}' ),
              "query-input" => "required name=search_term_string"
          ),
          "publisher" => array(
              "@type" => "Organization",
              "name" => $business_name, // 事業者名を使用
              "logo" => array(
                  "@type" => "ImageObject",
                  "url" => get_site_icon_url() // サイトアイコンURLを使用
              )
          )
      );
  } elseif ( is_single() ) {
      // 投稿ページのJSON-LD
      global $post;
      $logo_id = get_theme_mod( 'custom_logo' );
      $logo = $logo_id ? wp_get_attachment_image_src( $logo_id, 'full' ) : false;
      $logo_url = $logo ? $logo[0] : get_site_icon_url(); // カスタムロゴがない場合はサイトアイコンを使用
      $author_url = get_author_posts_url( $post->post_author ); // 著者アーカイブページのURLを取得

      $json_ld = array(
          "@context" => "https://schema.org",
          "@type" => "BlogPosting", // BlogPostingタイプを使用
          "mainEntityOfPage" => array(
              "@type" => "WebPage",
              "@id" => get_permalink( $post )
          ),
          "headline" => get_the_title( $post ),
          "image" => array( get_the_post_thumbnail_url( $post, 'full' ) ),
          "datePublished" => get_the_date( 'c', $post ),
          "dateModified" => get_the_modified_date( 'c', $post ),
          "author" => array(
              "@type" => "Person", // 個人事業主なのでPerson
              "name" => $author_name,
              "url" => $author_url
          ),
          "publisher" => array(
              "@type" => "Organization",
              "name" => $business_name, // 事業者名を使用
              "logo" => array(
                  "@type" => "ImageObject",
                  "url" => $logo_url
              )
          ),
          "description" => wp_strip_all_tags( get_the_excerpt( $post ) )
      );
  } elseif ( is_page() ) {
      // 固定ページのJSON-LD
      global $post;
      $json_ld = array(
          "@context" => "https://schema.org",
          "@type" => "WebPage",
          "url" => get_permalink( $post ),
          "name" => get_the_title( $post ),
          "description" => wp_strip_all_tags( get_the_content( $post ) ),
          "publisher" => array(
              "@type" => "Organization",
              "name" => $business_name, // 事業者名を使用
              "logo" => array(
                  "@type" => "ImageObject",
                  "url" => get_site_icon_url()
              )
          )
      );
  }

  if ( ! empty( $json_ld ) ) {
      echo '<script type="application/ld+json">' . json_encode( $json_ld, JSON_UNESCAPED_UNICODE ) . '</script>';
  }
}
add_action( 'wp_head', 'add_json_ld' );



著者の情報の部分では、WordPressのget_author_posts_url()関数を使用して、著者のアーカイブページのURLを取得していますが、著者が個人のウェブサイトやプロフィールページを持っている場合は、そのURLを設定することもできます。

// 著者アーカイブページのURL
$author_url = get_author_posts_url( $post->post_author );

// 著者URLを固定値で設定
$author_url = 'https://example.com/about';

もし、著者が個人のウェブサイトやプロフィールページを持っていない場合は、WordPressのユーザー情報を充実させておきましょう。

また、一個人としてブログサイトを運営している場合でも、サイト名と著者名を変数で管理して構造化データを作るのもいいでしょう。
publisherのプロパティでは、個人なのでPersonとして適切な情報を伝えるようにしましょう。

functions.php(一個人)

function add_json_ld() {
    $site_name = 'ブログサイト名'; // サイト名
    $author_name = '山田 太郎'; // 著者名

    if ( is_front_page() || is_home() ) {
        // トップページ(ホームページ/投稿ページ)のJSON-LD
        $json_ld = array(
            "@context" => "https://schema.org",
            "@type" => "WebSite",
            "url" => home_url(),
            "name" => $site_name,
            "potentialAction" => array(
                "@type" => "SearchAction",
                "target" => home_url( '/?s={search_term_string}' ),
                "query-input" => "required name=search_term_string"
            ),
            "publisher" => array(
                "@type" => "Person", // 個人なのでPerson
                "name" => $author_name, // 著者名
                "url" => home_url(), // サイトURL
                "logo" => array(
                    "@type" => "ImageObject",
                    "url" => get_site_icon_url() // サイトアイコンURLを使用
                )
            )
        );
    } elseif ( is_single() ) {
        // 投稿ページのJSON-LD
        global $post;
        $logo_id = get_theme_mod( 'custom_logo' );
        $logo = $logo_id ? wp_get_attachment_image_src( $logo_id, 'full' ) : false;
        $logo_url = $logo ? $logo[0] : get_site_icon_url(); // カスタムロゴがない場合はサイトアイコンを使用
        $author_url = get_author_posts_url( $post->post_author ); // 著者アーカイブページのURLを取得

        $json_ld = array(
            "@context" => "https://schema.org",
            "@type" => "BlogPosting", // BlogPostingタイプを使用
            "mainEntityOfPage" => array(
                "@type" => "WebPage",
                "@id" => get_permalink( $post )
            ),
            "headline" => get_the_title( $post ),
            "image" => array( get_the_post_thumbnail_url( $post, 'full' ) ),
            "datePublished" => get_the_date( 'c', $post ),
            "dateModified" => get_the_modified_date( 'c', $post ),
            "author" => array(
                "@type" => "Person", // 個人なのでPerson
                "name" => $author_name,
                "url" => $author_url
            ),
            "publisher" => array(
                "@type" => "Person", // 個人なのでPerson
                "name" => $author_name,
                "url" => home_url(), // サイトURL
                "logo" => array(
                    "@type" => "ImageObject",
                    "url" => $logo_url
                )
            ),
            "description" => wp_strip_all_tags( get_the_excerpt( $post ) )
        );
    } elseif ( is_page() ) {
        // 固定ページのJSON-LD
        global $post;
        $json_ld = array(
            "@context" => "https://schema.org",
            "@type" => "WebPage",
            "url" => get_permalink( $post ),
            "name" => get_the_title( $post ),
            "description" => wp_strip_all_tags( get_the_content( $post ) ),
            "publisher" => array(
                "@type" => "Person", // 個人なのでPerson
                "name" => $author_name,
                "url" => home_url(), // サイトURL
                "logo" => array(
                    "@type" => "ImageObject",
                    "url" => get_site_icon_url()
                )
            )
        );
    }

    if ( ! empty( $json_ld ) ) {
        echo '<script type="application/ld+json">' . json_encode( $json_ld, JSON_UNESCAPED_UNICODE ) . '</script>';
    }
}
add_action( 'wp_head', 'add_json_ld' );



ここまでの処理をWebサイトの運用状況に合わせてfunctions.phpで実装することで、ページごとでJSON-LDをhead要素に出力することができます。

JSON-LDのhead要素の出力



投稿記事もページタイトルやurl、ディスクリプション、また著者など詳細情報を正確に検索エンジンに伝えることができます。

Webページに実装した構造化データの確認


Webページに実装した構造化データが、大規模言語モデル(LLM)を含むGoogleの検索エンジンに正しく認識されているかは、「Google Rich Results Test」を使って確認することができます。

Google Rich Results Test
https://search.google.com/test/rich-results


確認したいWebページのURLを入力して、「URLをテスト」を選択します。

Webページに実装した構造化データをリッチリザルトテストで確認する



検索された構造化データの項目に、有効なアイテムが検出されていれば、構造化データは検索エンジンに伝わっています。
アイテムを選択すると、検出されたアイテムのデータが確認できます。

リッチリザルトテストでのWebページに実装した構造化データの確認



もし、必要な情報が足りなかった場合は、functions.phpのJSON-LDの内容を編集して追加していくことになります。

最後に


生成AI時代においては、LLMO(大規模言語モデル最適化)が従来のSEOと併用してとても重要になります。
生成AIにも好まれるよう、WordPressサイトの格ページで適切に情報を伝えれるようにしましょう。

ちなみに、All in One SEOというSEO関連のプラグインでは、スキーママークアップができるようですが、無料であればトップページのみ、固定ページや投稿ページ、カスタム投稿に対応するには有料プランとなるようです。
LLMO対応のプラグインも登場してきていますが、Webサイトのパフォーマンスが落ちるからなるべくプラグインに頼りたくないという方は、ぜひ今回ご紹介した方法でLLMO対策を行なってみてください。