HugoでJSON-LD形式のパンくずリストを出力する

HugoでパンくずリストをJSON-LD形式で出力するpartialテンプレートを作成しました。

はじめに

以前アップした記事「Hugoでmicrodata形式のパンくずリストを出力する」ではmicrodata形式の構造化データ形式でパンくずリストを出力しました。

microdata形式の場合はページを構成するHTMLに構造化データをマークアップする必要がありましたがJSON-LD形式の場合はその必要がありません。

Googleの構造化データに関する一般的なガイドラインではJSON-LD形式の構造化データが推奨となっていますので、このブログのパンくずリストをmicrodata形式からJSON-LD形式の構造化データに変更することにしました。

JSON-LD形式について

JSON-LD形式の構造化データはtype属性にapplication/ld+jsonを指定した<script>要素にJSON形式で記述します。

HTMLの要素の属性などに記述するRDFaやmaicrodata形式の構造化データよりも表現できることが多く推奨されている形式です。

以下はJSON-LD形式のパンくずリストの構造化データのサンプルです。

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [{
    "@type": "ListItem",
    "position": 1,
    "name": "トップページ",
    "item": "https://example.com/"
  },{
    "@type": "ListItem",
    "position": 2,
    "name": "記事一覧ページ",
    "item": "https://example.com/posts/"
  },{
    "@type": "ListItem",
    "position": 3,
    "name": "記事ページ"
  }]
}
</script>

パンくずリストの構造化データの場合は@typeBreadcrumbListを指定したJSONのitemListElementプロパティーにパンくずリストのページの一覧を設定します。

パンくずリストのアイテムのそれぞれのページはitemプロパティーにそのページのURLを設定します。

最後のアイテムの場合はitemプロパティーが必須ではなくURLが設定されていない場合は現在のページのURLが使用されます。

JSON-LD形式のパンくずリストの出力

JSON-LD形式のパンくずリストを出力するpartialテンプレートを作成しました。

partials/jsonld/breadcrumb.html
{{- $itemListElement := partial
  "partials/jsonld/breadcrumb/itemListElement" . -}}
{{- $breadcrumb := dict
  "@context"        "https://schema.org"
  "@type"           "BreadcrumbList"
  "itemListElement" $itemListElement
-}}
{{- return $breadcrumb -}}

{{/* トップページからのJSON-LDのListItemを取得するpartial */}}
{{- define "partials/jsonld/breadcrumb/itemListElement" -}}
  {{- $current := . -}}
  {{- $items := slice -}}
  {{- range $i, $page := partial "partials/jsonld/breadcrumb/pages" . -}}
    {{- $item := dict
      "@type"     "ListItem"
      "position"  (add $i 1)
      "name"      $page.LinkTitle
    -}}
    {{/* 現在のページ以外の場合はitemにURLを設定する */}}
    {{- if ne $current $page -}}
      {{- $item = merge $item
        (dict "item" ($page.Permalink | absURL)) -}}
    {{- end -}}
    {{- $items = $items | append $item -}}
  {{- end -}}
  {{- return $items -}}
{{- end -}}

{{/* トップページからのページ一覧を取得するpartial */}}
{{- define "partials/jsonld/breadcrumb/pages" -}}
  {{- $pages := slice -}}
  {{/* 上の階層のページがある場合はそのページまでの一覧を取得 */}}
  {{- with .Parent -}}
    {{- $pages = partial "partials/jsonld/breadcrumb/pages" . -}}
  {{- end -}}
  {{- return ($pages | append .) -}}
{{- end -}}

このpartialテンプレートはページにHTMLやJSONを出力するのではなくreturnを使って値を返すことができる機能を利用してJSONのもととなるdictを返却します。

{{- return $breadcrumb -}}

このテンプレートを利用する側のレイアウト用のテンプレートではこのテンプレートから返却されたdictjsonify関数でJSON形式に変換して出力します。

{{- with partial "partials/jsonld/breadcrumb" . -}}
  <script type="application/ld+json">
    {{- . | jsonify | safeJS -}}
  </script>
{{- end -}}

またインラインにpartialを2つ定義しています。

  • トップページからのページ一覧を取得するpartial
  • トップページからのJSON-LDのListItemを取得するpartial

これらもreturnで値を返すことができる機能を利用して関数のように使用しています。

構造化データのマークアップのテスト

正しく構造化データのマークアップができているかの検証はGoogleのリッチリザルト テストのページで行うことができます。

リッチリザルト テスト結果

正しくパンくずリストの構造化データのマークアップができていれば検出された構造化データにパンくずリストが有効なアイテムとして表示されます。

おわりに

以前作成したmicrodata形式の構造化データのパンくずリストの場合はpositionを設定するためにページに必要のないmetaタグをパンくずリストのHTMLにマークアップする必要がありました。

microdata形式のパンくずリストからJSON-LD形式の構造化データに変更してみた感想としてはJSON-LD形式の場合はページを構成するHTMLとは別に構造化データを定義できる点が大きいメリットだと思いました。