構造化データ(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にも対応したいなと思うけど、まあそのうち。
最後に構造化データ テストツールで表示を確認。実際の検索結果に出てくるかどうかはわからないけど、データ的には特に問題なさそうである。
以上。