構造化データ(structured data)の部分を microdata から JSON-LD に置き換えてみた。
とりあえずArticle | Search | Google Developersにある「SEE MARKUP」からサンプルの JSON-LD のデータをコピーして、それを元に hexo のテンプレートの個別のページのアーカイブに下記の JSON-LD を追加。
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "BlogPosting",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "<%- page.permalink %>"
},
"headline": "<%- page.title %>",
<% if (page.featured && page.featured.image) { %>
"image": [
"https://memolog.org/assets/images/<%= page.featured.image %>/<%= page.featured.image %>.jpg"
],
<% } %>
"datePublished": "<%- page.date %>",
"dateModified": "<%- page.updated %>",
"author": {
"@type": "Person",
"name": "Yutaka Yamaguchi"
},
"publisher": {
"@type": "Organization",
"name": "メモログ",
"logo": {
"@type": "ImageObject",
"url": "https://memolog.org/assets/icons/icon-1024.png"
}
},
"description": "<%- remove_html(page.excerpt) %>"
}
</script>
description には HTML を含まないテキストを出力したいのだけど、hexo のpage.excerpt
の出力には HTML が含まれていてそれを取り除く手段が標準ではない(ように見える)。なので、remove_html
という簡単なヘルパーを用意した。改行の情報などもいらないので、DOM にデータを入れてそれを textContent でテキスト部分を取得するだけ。
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
hexo.extend.helper.register("remove_html", function (content) {
return (
new JSDOM(`<div>${content}</div>`).window.document.getElementsByTagName(
"div"
)[0].textContent || ""
);
});
同様に、各ページの共通の情報としてLogoとSocial Profileのデータを追加している。
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@graph":
[
{
"@context": "http://schema.org",
"@type": "Organization",
"url": "http://memolog.org",
"logo": "https://memolog.org/assets/icons/icon-1024.png"
},
{
"@context": "http://schema.org",
"@type": "Person",
"name": "Yutaka Yamaguchi",
"url": "http://memolog.org",
"sameAs": [
"https://www.facebook.com/yutaka.yamaguchi",
"https://www.linkedin.com/in/yutakayamaguchi/",
"https://twitter.com/memolog"
]
}
]
}
</script>
二つのトップレベルのアイテムを一つの script タグで追加したい場合は、@graph
で記入すると良いとweb - JSON-LD Schema.org: Multiple video/image page - Stack Overflowに書かれてあったのでそのようにした(複数の script タグに分けてもいい)。
インデックステンプレートの方にはCarouselsの記述を入れることにした。
<script type="application/ld+json">
{
"@context":"http://schema.org",
"@type":"ItemList",
"itemListElement":[
<% page.posts.each( (post, i) => { %>
{
"@type":"ListItem",
"position":<%- i+1 %>,
"url": "<%- post.permalink %>"
}<% if (i + 1 < page.posts.length ) { %>,<% } %>
<% }) %>
]
}
</script>
Carousel の表示はMark Up Your Content Items には、「The Top stories carousel requires that your content be published in AMP. For more information, see AMP with structured data.」とあり、non-AMP ページではいわゆるカルーセルでの表示ではなく、リスト表示になるようである。
ので、そのうち AMP にも対応したいなと思うけど、まあそのうち。
最後に構造化データ テストツールで表示を確認。実際の検索結果に出てくるかどうかはわからないけど、データ的には特に問題なさそうである。
以上。