BloggerでJSON-LD構造化
以前、Yostのページを参考にBloggerのページをJSON-LDデータを使って構造化しました。当時はうまく機能していた(はず)なのですが、設定した、PersonやOrganization、WebSiteなどがGoogleのリッチリザルトテストに反映されていないことに気づきました。
かろうじて「ぱんくずリスト」だけは機能しているようです。どういう事なのか調べて改善しました。
構造化データについて
先に、構造化データとは何かをおさらいしておきます。Google検索セントラル:「構造化データの仕組みについて」によると、複雑化したWebページの内容を正確に検索エンジンに伝える為のデータです。
構造化データにはここで紹介するGoogleが推奨するJSON-LDの他に、microdataやRDFaといったものがあります。
JSON-LDはその名の通り<script>タグ内に記述するJSONデータなのに対し、あとのものはHTMLタグの属性としてデータを埋め込む仕組みになっています。
JSON-LDは元のソースコードを汚さないですが、HTMLと構造化データ用に別々に出力しないといけないので、他に比べてページサイズが大きくなりがちです。
macrodataで「パンくずリスト」のサンプルを作成すると、冒頭は次のようになります。
macrodata
<ol itemscope itemtype="https://schema.org/BreadcrumbList">
<li itemprop="itemListElement" itemscope
itemtype="https://schema.org/ListItem">
<a itemprop="item" href="https://nanbu.marune205.net/2020/02/blogger-json-ld.html?m=1">
<span itemprop="name">BlogPage</span></a>
<meta itemprop="position" content="1" />
</li>
...
同じ内容をJSON-LDで記述すると次のようになります。
JSON-LD
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [{
"@type": "ListItem",
"position": 1,
"name": "BlogPage",
"item": "https://nanbu.marune205.net/2020/02/blogger-json-ld.html"
}
...
比べてみると同じ内容をフォーマットを変えて出力しているだけだということがわかります。
最初に、「https://schema.org」、「BreadcrumbList」という表記があります。これはSchema.orgが定義するBreadcrumbListの形式にのっとって表現していることを示しています。
先のリンク先を見てみると、「ぱんくずリスト」=「BreadcrumbList」には、「position」や「name」、「item」といった項目があることが説明されており、これらはコード内の項目名に一致しています。
Googleの仕様変更?
Googleのリッチリザルトテストに反応しないものの、PersonやOrganizationはSchema.orgのページには健在でした。
ただ先のGoogleのページに次のような文章を見つけました。
Google 検索の動作の定義には、Schema.org のドキュメントではなく Google 検索セントラルのドキュメントを使用してください。schema.org には Google 検索では不要な属性やオブジェクトもありますが、他のサービス、ツール、プラットフォームで役立つ場合もあります。
推測するに、こちらに例示のあるものだけが対象になるのではないでしょうか。
Article
WebSiteオブジェクトが使えないのでその代わりを探したところ、Articleを見つけました。 非AMPページのArticle項目にしたがって、Articleオブジェクトを作成します。
Googleのページに記載されていたオブジェクトのプロパティは次の通りです。
- dateModified
ISO8601形式(例:2020-03-10T13:55:00+09:00)で更新日をセットします。(推奨項目)
- datePublished
ISO8601形式で公開日をセットします。(推奨項目)
- headline
見出し、半角110字(全角55文字)を超えてはいけません。
- image
イメージ、複数ある場合は,でつなげて設定することが可能です。サポートされている形式である他、696ピクセル以上にする必要があるそうです。
(696ピクセル未満の画像を指定してもエラーにはならないようです)
非AMPページ用に案内されていた項目はこれだけだったのですが、効果あるかわかりませんが、AMPページ用に案内されていたauthorとpublisherを付け加えて設定すると次のようになります。
JavaScriptでは'(シングルクォーテーション)も利用できますが、JSON-LD中では文字リテラルは"(ダブルクォーテーション)だけになります。注意してください。
ちなみにdescription等のSchema.orgで定義されている項目も付与してみましたが、切り捨てられるようでした。
script内でタグ(<b:if>など)を使っている部分はBlogger用です。Bloggerを使っている人は「Blogの投稿」ガジェット内でdata:postsをpost変数でループしている箇所に合わせてサンプルを書いています。
そうでない環境の場合はページ表示時に適切な文字列がセットされるように構成してください。
JSON-LD
<script type='application/ld+json'>
{
"@context": "https://schema.org",
"@type": "Article",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "<data:blog.url/>"
},
"headline": "<data:blog.title/>",
"image": [
<b:if cond='data:blog.postImageUrl'>
"<data:blog.postImageUrl/>"
<b:else/>
"https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdJQ3w3Yt001rSOgmGvAMyZPXRX81eL6FM76k87w2cxZv-15RGrsffug8fLkmvmZZ21vThK8YtblaiNmGTIOOTZbKXdioXgjrxufr6hL_6-CFnMCPup1AMpO7yiByxT-R2pV5ljw3V1ir8/s0/favicon.png"
</b:if>
],
"datePublished": "<data:post.date.iso8601/>",
"dateModified": "<data:post.lastUpdatedISO8601/>",
"author": {
"@type": "Person",
"name": "なんぶ電子",
"url": "https://www.blogger.com/profile/17570606631417493762"
},
"publisher": {
"@type": "Organization",
"name": "なんぶ電子",
"logo": {
"@type": "ImageObject",
"url": "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQnEzqUWsarGWgK76BnfS62cbP9rPJVURivXo0DkvN1yHs-vlUgOWB5ZbQlUeMteiFTPmSt4eZfa2K-BBKva1GsDDXOOBu4XDn_djImQeifDr_QMA_VeGzhyphenhyphenkufUcwLjbkHS10Mrs4Wqk/s113/zdenek-machacek-1387013-unsplash.jpg"
}
}
}
</script>
BreadCrumb(ぱんくずリスト)
こちらの例示はほぼBlogger用になってしまうかもしれませんが、紹介しておきます。ブログ記事に設定する「ラベル」を使って階層構造にしています。ちなみにBloggerの独自タグについては別記事で解説していますので、気になったら読んでみてください。
Bloggerの「ページの投稿」ガジェット内で有効です。「ページ」だった場合は「ラベル」が存在しませんので別途処理が必要になります。
JSON-LD
<script type='application/ld+json'>
{
"@context":"https://schema.org",
"@type":"BreadcrumbList",
"@id":"https://nanbu.marune205.net/#breadcrumb",
"itemListElement":[
{"@type":"ListItem","position":1,"item":{"@type":"WebPage","@id":"https://nanbu.marune205.net/p/sitemaps.html?m=1","url":"https://nanbu.marune205.net/p/sitemaps.html","name":"ホーム"}},
<b:if cond='data:post.labels'>
<b:loop index='ilabelloop' values='data:post.labels' var='label'>
<b:if cond='data:ilabelloop==0'>
{"@type":"ListItem","position":2,"item":{"@type":"WebPage","@id":"<data:label.url/>","url":"https://nanbu.marune205.net/p/sitemaps.html?m=1&refine=<data:label.name/>","name":"<data:label.name/>"}},
</b:if>
</b:loop>
<b:else/>
{"@type":"ListItem","position":2,"item":{"@type":"WebPage","@id":"","url":"","name":"ラベルなし"}},
</b:if>
{"@type":"ListItem","position":3,"item":{"@type":"WebPage","@id":"<data:blog.url/>","url":"<data:blog.url/>","name":"<data:blog.pageName/>"}
}
]
}
</script>
わかりづらいと思いますので、Bloggerのコードを展開した実際のJSON-LDも紹介しておきます。
JSON-LD
<script type='application/ld+json'>
{
"@context":"https://schema.org",
"@type":"BreadcrumbList",
"@id":"https://nanbu.marune205.net/#breadcrumb",
"itemListElement":[
{"@type":"ListItem","position":1,"item":{"@type":"WebPage","@id":"https://nanbu.marune205.net/p/sitemaps.html?m=1","url":"https://nanbu.marune205.net/p/sitemaps.html","name":"ホーム"}},
{"@type":"ListItem","position":2,"item":{"@type":"WebPage","@id":"https://nanbu.marune205.net/search/label/Blogger","url":"https://nanbu.marune205.net/p/sitemaps.html?m=1&refine=Blogger","name":"Blogger"}},
{"@type":"ListItem","position":3,"item":{"@type":"WebPage","@id":"https://nanbu.marune205.net/2021/11/blogger-json-ld.html","url":"https://nanbu.marune205.net/2021/11/blogger-json-ld.html?m=1","name":"BloggerでJSON-LD構造化"}}
]
}
</script>
サイトリンク検索ボックス
Googleの検索結果の内側にさらにサイト内の検索ができる検索ボックスを表示させるための設定となります。urlやurlTemplateの箇所を環境に応じて変更して下さい。
JSON-LD
<script type='application/ld+json'>
{
"@context": "https://schema.org",
"@type": "WebSite",
"url": "https://nanbu.marune205.net/",
"potentialAction": {
"@type": "SearchAction",
"target": {
"@type": "EntryPoint",
"urlTemplate": "https://nanbu.marune205.net/search?q={search_term_string}"
},
"query-input": "required name=search_term_string"
}
}
</script>