JSON-LDとは

JSON-LDは、ページの内容を検索エンジンに構造的に伝えるための構造化データ記法である。schema.orgの語彙をJSON形式で記述し、<script type="application/ld+json">としてHTMLに埋め込む。

Introduction to Structured Data | Google Search Central でも、JSON-LDがGoogleの推奨する実装方法として説明されている。HTML要素に属性を付与するMicrodataやRDFaと異なり、既存のHTML構造に手を加えず<head>内へまとめて追加できる点がメリットである。

構造化データを正しく実装すると、検索結果に著者名・公開日・パンくずリストなどが表示されるリッチリザルトの対象になる可能性がある。ただし構造化データはリッチリザルト表示を保証するものではなく、あくまで検索エンジンへの補助情報である点に注意する。

Hugoへの組み込み方

Hugoではheadタグ内に構造化データ用のpartialを追加するだけで組み込める。

<head>
  ...
  {{- partial "json_ld.html" . -}}
</head>

partial側で、記事ページかどうかを.IsPageで判定し、記事ページの場合のみBlogPostingBreadcrumbListを出力する。Organizationは全ページ共通で出力する。

<script type="application/ld+json">
  [
    {{ if .IsPage }}
    {
      "@context": "https://schema.org",
      "@type": "BlogPosting",
      "headline": {{ .Title }},
      "image": {{ ((path.Join ((.Permalink | relURL)) (.Params.thumbnail)) | absLangURL) }},
      "datePublished": {{ .PublishDate }},
      "dateModified": {{ .Lastmod }},
      "author": {
        "@type": "Person",
        "name": {{ .Site.Params.author.name }}
      },
      "mainEntityOfPage": { "@type": "WebPage" },
      "publisher": {
        "@type": "Organization",
        "name": {{ .Site.Params.author.name }},
        "logo": {
          "@type": "ImageObject",
          "url": {{ .Site.Params.logo }}
        }
      },
      "description": {{ .Summary | plainify | safeHTML }},
      "keywords": [{{ range $i, $e := .Params.tags }}{{ if $i }}, {{ end }}{{ $e }}{{ end }}]
    },
    {
      "@context": "https://schema.org",
      "@type": "BreadcrumbList",
      "itemListElement": [{
        "@type": "ListItem",
        "position": 1,
        "name": {{ index .Section }},
        "item": {{ .Section | absLangURL }}
      }]
    },
    {{ end }}
    {
      "@context": "https://schema.org",
      "@type": "Organization",
      "name": {{ .Site.Params.title }},
      "url": {{ .Site.BaseURL }},
      "sameAs": [
        {{ .Site.Params.author.twitter }},
        {{ .Site.Params.author.github }}
      ]
    }
  ]
</script>

Hugoの.html出力はGoのhtml/templateパッケージでレンダリングされる。html/templateは出力先の文脈を判定して自動的にエスケープする仕組みを持ち、<script type="application/ld+json">内ではJSON文脈として値をエスケープする。そのためHugoのテンプレート変数(.Title.Summaryなど)をJSON文字列としてそのまま埋め込んでも壊れない。

各項目

BlogPosting

Learn About Article Schema Markup | Google Search Central によると、ArticleNewsArticleBlogPostingのいずれかを使って記事ページを表現する。必須プロパティは定められていないが、headlineimagedatePublishedauthorを含めることで、Googleのトップストーリーカルーセルなどのリッチリザルト表示の対象になりやすくなる。

各プロパティの役割は以下のとおりである。

プロパティ役割
headline記事のタイトル
image記事のサムネイル画像URL
datePublished公開日時
dateModified更新日時
author著者情報(Person型)
publisher発行元情報(Organization型)。ロゴ画像を含める
description記事の要約
keywords記事に関連するキーワード

publisher.logoOrganization Schema Markup | Google Search Central にあるとおり、幅・高さともに最低112pxの画像を指定する必要がある。

BreadcrumbListは、ページまでの階層構造を表すパンくずリストの構造化データである。How To Add Breadcrumb (BreadcrumbList) Markup | Google Search Central によると、itemListElement配列にListItemを並べ、各要素にposition(1始まりの順序)・name(表示名)・item(絶対URL)を指定する。

正しく実装すると、検索結果のURL表示部分がパンくずリスト形式に置き換わり、ページの位置づけがユーザーに伝わりやすくなる。

Organization

Organizationは、サイトやブログの運営主体を表す構造化データである。全ページ共通で出力しておくことで、サイト全体の発行元情報を検索エンジンに伝える。

主なプロパティは以下のとおりである。

プロパティ役割
name組織名・サイト名
urlサイトのURL
logo組織のロゴ画像
sameAsTwitterやGitHubなど、同一組織を示す外部プロフィールのURL一覧

sameAsは、SNSアカウントなど組織と紐づく外部ページのURLを列挙するプロパティである。Googleナレッジパネルなどで、サイトと外部プロフィールが同一の運営主体であることを示す手がかりになる。

動作確認

構造化データが正しく認識されるかは、リッチリザルトテスト にページのURLを入力して確認する。検出された構造化データの一覧とエラー・警告が表示されるため、プロパティの過不足を確認できる。

まとめ

HugoでJSON-LDを組み込むには、<head>内にpartialを1つ追加するだけでよい。BlogPostingで記事情報、BreadcrumbListでページの階層、Organizationでサイトの運営主体を検索エンジンに伝えることで、リッチリザルト表示につながる可能性が高まる。