構造化データ(structured data)の部分をmicrodataからJSON-LDに置き換えてみた。
とりあえずArticle | Search | Google Developers にある「SEE MARKUP」からサンプルのJSON-LDのデータをコピーして、それを元にhexoのテンプレートの個別のページのアーカイブに下記のJSON-LDを追加。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <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でテキスト部分を取得するだけ。
1 2 3 4 5 6 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 のデータを追加している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <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 の記述を入れることにした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <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にも対応したいなと思うけど、まあそのうち。
最後に構造化データ テストツール で表示を確認。実際の検索結果に出てくるかどうかはわからないけど、データ的には特に問題なさそうである。
以上。