記事の​マークアップを​Googleの​Rich Snippets for Articlesに​対応させた​話

公開

更新

structured data testing toolのテスト結果。問題ありません、と表示されています!

このブログの記事は構造化データとしてマークアップをしていましたが、それを改めてGoogleさんのRich Snippets for Articlesに対応したという話です。

Rich Snippets for Articlesが表示されたイメージ
via Enabling Rich Snippets for Articles  | Structured Data  | Google Developers

ニュース記事の 2 つの非 AMP 検索結果(1 つは画像あり、1 つは画像なし)。

これまでは microdataの記法で下記の4項目を schema.org/BlogPosting としてマークアップしていました。

  • 記事タイトル (name)
  • 公開日 (datePublished)
  • 本文 (articleBody)
  • URL (url)

※()内はプロパティ

上記でも構造化データとしては間違ってはいないのですが、Rich Snippets for Articlesでは、記事タイトルプロパティはnameではなくてheadlineだったり、imageが必須で、大きさの範囲が決まっていたりなど、独自の仕様が存在します。

Property Type Description
headline (required) Text The headline of the article
image (required) URL A URL, or list of URLs pointing to the representative image file(s). Images must be at least 160x90 pixels and at most 1920x1080 pixels. We recommend images in .jpg, .png, or. gif formats. All image URLs should be crawlable and indexable. Otherwise, we will not be able to display them on the search results page.
Only marked-up images that directly belong to the article should be listed in this property. If there are multiple applicable images, please list them all with the important images first.
datePublished (required) Date The date and time the article was first published, in ISO 8601 format.
description Text A short description of the article.
articleBody Text The actual body of the article.
alternativeHeadline Text A secondary headline for the article.
via Enabling Rich Snippets for Articles  | Structured Data  | Google Developers

そこで、nameheadlineにして、記事中に画像がある際は、手動でitemprop="image"をマークアップするようにしました。

なので記事中に画像がない場合は、Rich Snippetsの仕様から外れますが、記事に関係のない画像(サイトイメージのようなものや、no image的な画像)を指定するのも個人的にはちょっと違う気がしますし、Googleさんも記事に直接関係のある画像のみにしやがれ(Only marked-up images that directly belong to the article should be listed in this property.)と言ってますので、なるべくリッチなコンテンツ作りを意識して頑張ろうという感じです。


また、microdataではなくJSON-LDで出力するMovable Typeのテンプレートも作成してみました。下記を記事テンプレートのどこかに埋め込んでやれば、特別なマークアップをすることなく、Rich Snippetsに対応できます(画像があれば)。

<mt:Ignore>記事中に使用されている画像アセットの取得</mt:Ignore>
<mt:EntryAssets type="image">
<mt:SetVarBlock name="push(article_images)"><mt:AssetURL /></mt:SetVarBlock>
</mt:EntryAssets>
<mt:Unless regex_replace="/^\s*\n/gm","">
<script type="application/ld+json">
{
  "@context": "http://schema.org"
  ,"@type": "BlogPosting"
  ,"headline": "<mt:EntryTitle remove_html="1">"
  <mt:If name="article_images">
  ,"image": [
  <mt:loop name="article_images">
    <mt:Unless name="__first__">,</mt:Unless>"<mt:Var __value__ />"
  </mt:loop>
  ]
  </mt:If>
  ,"datePublished": "<mt:EntryDate format_name="ISO8601">"
  ,"description": "<mt:EntryExcerpt remove_html="1">"
  ,"articleBody": "<mt:EntryBody remove_html="1" trim="1" encode_js="1">"
}
</script>
</mt:Unless>

テンプレートとしては、ごくごく普通に記事中のデータをそのまま値としてるだけで特別難しいことはしていません。

一点だけ気をつけたいのが、記事本文であるarticleBodyには大体の場合、HTMLのタグが記載されていたりクオートが入っていたりしますので、そのまま出力するとJSONの値としてもschema.orgのデータタイプとしても問題になってしまうことです。

そのため、記事本文のデータからHTMLタグを除去した上で、jsのテキスト形式にエンコードする必要があります。Movable Type では、グローバルモディファイアで双方に該当するものがありますので、remove_htmlencode_jsを付加するのみで済みます。

"articleBody": "<mt:EntryBody remove_html="1" trim="1" encode_js="1">"

ほんとグローバルモディファイアさまさまですね。

ただし、以前記事に書いた「JSON-LDをWebComponentsで表示する」などのようにプログラムから再利用する場合は、記事本文中からHTMLタグがなくなってしまうので、デコードして再利用しようとしても例えばblockquotetableなどが再現できなくなり、記事として表示するためには別の方法を考えなければいけないなあと思っています。