フリーランスでWeb制作をしている矢野です。
今回は、技術ブログ記事にArticle構造化データ(JSON-LD)を追加したときに遭遇した、地味だけど気づきにくいバグの話を書きます。
構造化データを追加した理由
検索エンジンに「これはブログ記事です」と機械的に伝えるために、Article系の構造化データ(JSON-LD)を追加することにしました。
検索結果でのリッチリザルト表示や、記事の公開日・著者などの情報をクローラーに正確に伝える狙いです。
wp_headフックでBlogPostingのJSON-LDを出力する
実装自体はシンプルで、wp_headフックにBlogPosting型のJSON-LDを出力する関数を1つ追加するだけです。
function yano_works_article_schema() {
if ( ! is_singular( 'post' ) ) {
return;
}
$image = has_post_thumbnail() ? get_the_post_thumbnail_url( null, 'large' ) : get_template_directory_uri() . '/images/hero-illustration.png';
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'BlogPosting',
'headline' => get_the_title(),
'description' => get_the_excerpt(),
'image' => $image,
'datePublished' => get_the_date( 'c' ),
'dateModified' => get_the_modified_date( 'c' ),
'author' => array(
'@type' => 'Person',
'name' => get_the_author(),
),
// ...
);
echo '<script type="application/ld+json">' . wp_json_encode( $schema ) . '</script>';
}
add_action( 'wp_head', 'yano_works_article_schema' );
ここまでは特に問題なく動いたのですが、公開後に生成されたJSON-LDを確認してみると、author.nameだけが空文字になっていました。
get_the_author()が空文字を返していた話
原因は、wp_headが呼ばれる時点では、まだWordPressのメインループ(the_post())が回っていないことでした。
get_the_author()は、ループの中でthe_post()が実行されたときにセットされる$authordataというグローバル変数を参照する仕組みになっています。
wp_headはページ内の<head>を出力する段階、つまりループが始まる前に発火するフックなので、$authordataがまだ空のまま関数が呼ばれてしまい、結果として著者名も空文字になっていたというわけです。
BEFORE(ループ前提のget_the_author())
'author' => array(
'@type' => 'Person',
'name' => get_the_author(),
),
AFTER
'author' => array(
'@type' => 'Person',
'name' => get_the_author_meta( 'display_name', get_post_field( 'post_author', get_the_ID() ) ),
),
修正は、投稿IDから著者IDを明示的に取得して、get_the_author_meta()にIDを直接渡す形にするだけでした。
こうすればループが回っているかどうかに関係なく、常に正しい著者情報を取得できます。
まとめ
今回は、ブログ記事にArticle構造化データを追加する中で、wp_headフック内でget_the_author()が空文字を返すバグに遭遇した話を書きました。
「ループの中でしか正しく動かない関数」は他にもいくつかあるので、wp_headやinitのような早いタイミングのフックでテンプレートタグを使うときは、素直にループ前提の関数を使わず、IDを明示的に渡す書き方にしておくと安全だと感じました。
同じように構造化データを実装する方の参考になればうれしいです。
使っているレンタルサーバー
このサイト(yanoworks.com)はXServerで運用しています。個人開発の検証から本番デプロイまで、価格・速度ともに不満なく使えています。