WordPress自作テーマにレシピのリッチリザルトを実装したのでコード覚書です。
とりあえずコード例
functions.phpコード例です。
プロパティは自分の判断での最低限にしました。
<?php
//リッチリザルト用の画像サイズ追加
add_image_size('thumbnail-1-1', 225, 225, true );
add_image_size('thumbnail-4-3', 400, 300, true );
add_image_size('thumbnail-16-9', 400, 225, true );
function json_recipe() {
if( is_singular('recipe') && has_post_thumbnail() ) ://カスタム投稿レシピかつサムネイルあり
//レシピ名
$post_obj = get_queried_object();
$post_title = $post_obj->post_title;
//画像
$thumb_1_1 = wp_get_attachment_image_src( get_post_thumbnail_id($post_obj->ID), 'thumbnail-1-1');
$thumb_4_3 = wp_get_attachment_image_src( get_post_thumbnail_id($post_obj->ID), 'thumbnail-4-3');
$thumb_16_9 = wp_get_attachment_image_src( get_post_thumbnail_id($post_obj->ID), 'thumbnail-16-9');
$img_1_1 = $thumb_1_1[0];
$img_4_3 = $thumb_4_3[0];
$img_16_9 = $thumb_16_9[0];
//投稿日時
$post_date = mysql2date('Y-m-d' , $post_obj->post_date);
//投稿者名
$post = get_post(get_the_id());
$postauthor = get_userdata($post -> post_author);
$author = $postauthor -> display_name;
//description
$copy = get_post_meta( get_the_ID() , 'copy', true );
//何人分
$yield = get_post_meta( get_the_ID() , 'yield', true );
//材料
$ingredient_meta = get_post_meta( get_the_ID() , 'ingredient', true );
$ingredient = explode("," , $ingredient_meta);
//調理方法
$instructions_meta = get_post_meta( get_the_ID() , 'instructions', true );
$instr = explode("," , $instructions_meta);
$instructions = str_replace("\r\n", '', $instr);
//json
$json_recipe = array(
"@context" => "http://schema.org",
"@type" => "Recipe",
"name" => $post_title,
"image" => [
$img_1_1,
$img_4_3,
$img_16_9,
],
"datePublished" => $post_date,
"description" => $copy ,
"recipeYield" => $yield,
"author" => [
"@type"=> "Person",
"name"=> $author,
],
"recipeIngredient" => $ingredient,
"recipeInstructions" => $instructions,
);
echo '<script type="application/ld+json">'.json_encode($json_recipe ,JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT).'</script>';
endif;
}
add_action( 'wp_head', 'json_recipe' );?>
概要としては
- get_queried_objectで情報取得
- jsonエンコード出力(JSON_UNESCAPED_UNICODEで日本語対応。JSON_PRETTY_PRINTで改行も入れるとコーディングしやすい。)
- wp_headにフック
get_queried_objectはループ外で情報取得するのに便利です。
情報の取得元
以下はWPのデフォに乗っかる形で取得。
- レシピ名【”name”】…記事タイトル(->post_title)
- 画像【”image”】…サムネイル
- 投稿日時【”datePublished”】…(->post_date)
- 投稿者名【”author”:{“name”}】…(->post_author)
以下はカスタムフィールド。
- レシピの概要【”description”】
- 何人分【”recipeYield”】
- 材料【”recipeIngredient”】
- 調理方法【”recipeInstructions”】
imageの設定
タイトルなどはすぐに引っ張れるので問題ないとして、注意が必要なのはimageです。
適切な画像が選択されるようにするために、アスペクト比が 16×9、4×3、1×1 の高解像度画像(幅と高さをかけて 50,000 ピクセル以上の画像)を複数指定してください。
https://developers.google.com/search/docs/appearance/structured-data/recipe?hl=ja
というわけでこれらのサイズが必要になります。
できればメディアライブラリにアップした際にこれらのアスペクト比で自動生成しておく形にしたい。
3サイズならちょうどWordPressデフォルトで用意されている自動生成機能を活用しよう、と思いましたがやめました。
だめな理由です。
- サムネイルはいいですが中サイズと大サイズは上限指定になっている、つまりデフォルト機能では比率をコントロールできない。
- 管理画面からサイズ入力する形式→後から変更できてしまうと困る。
というわけでadd_image_sizeで自動生成の画像サイズを追加します。以下生成する比率とサイズです。
- 1:1…225×225(50,625ピクセル)
- 4:3…400×300
- 16:9…400×225
記述例です。
//リッチリザルト用の画像サイズ追加
add_image_size('thumbnail-1-1', 225, 225, true );
add_image_size('thumbnail-4-3', 400, 300, true );
add_image_size('thumbnail-16-9', 400, 225, true );
コード側ではリッチスニペットのプロパティではimage必須なので、条件にサムネイルがあることを加えます。コード例ではレシピというカスタム投稿でサムネイルがある場合という形にしました。
if( is_singular('recipe') && has_post_thumbnail() ) :
//ここに中身
endif;
name(レシピ名)とdatePublished(投稿日時)
get_queried_objectを活用します。
$post_obj = get_queried_object();
$post_title = $post_obj->post_title;
$post_date = mysql2date('Y-m-d' , $post_obj->post_date);
$json_recipe = array(
"name" => $post_title,
"datePublished" => $post_date,
のような感じ。投稿日時の時間はいらないので、mysql2dateで。
投稿者名
$post = get_post(get_the_id());
$postauthor = get_userdata($post -> post_author);
$author = $postauthor -> display_name;
といった感じ。
カスタムフィールドから取得
- description(レシピの要約文)
- recipeYield(何人分)…数字
- recipeIngredient(材料)…カンマ区切り
- recipeInstructions(調理方法)…カンマ区切り
これらをカスタムフィールドから引っ張ります。(入力欄を複数設ける、表形式にするなども考えられそうです。)
何人分は半角数字で。材料は材料ごとにカンマ区切り。調理方法もステップごとにカンマ区切り。
なおGoogleの説明を見ると調理方法についてはHowToStepを使って明確に指定することがすすめられています。この記事のソースは簡略化した自分流なのでそうなっていません。
なおカスタムフィールド以外から引っ張る方法も考えられますが、これが一番難易度が低く簡単そうと思いました。
コメント