[Astro] 記事ページに JSON-LD 構造化データ(BlogPosting)とOGPを入れる

Tech
[Astro] 記事ページに JSON-LD 構造化データ(BlogPosting)とOGPを入れる

検索結果やSNSでの見え方のために、記事ページに JSON-LD 構造化データOGP メタタグを入れました。Astro なら frontmatter の値を流し込むだけなので簡単です。

JSON-LD(BlogPosting)

記事レイアウトで、frontmatter の値から BlogPosting を組み立てて <script type="application/ld+json"> に流し込みます。set:html={JSON.stringify(...)} を使うのがポイント。

---
// src/layouts/BlogPostLayout.astro
import { SITE } from '@/data/site';
const { post } = Astro.props;
const { title, description, pubDate, updatedDate, thumbnail } = post.data;
const pageUrl = `${SITE.url}/blog/${post.id}/`;
---
<script is:inline type="application/ld+json" set:html={JSON.stringify({
  '@context': 'https://schema.org',
  '@type': 'BlogPosting',
  headline: title,
  description: description,
  datePublished: pubDate.toISOString(),
  dateModified: (updatedDate || pubDate).toISOString(),
  author: { '@type': 'Person', name: SITE.author },
  publisher: { '@type': 'Organization', name: SITE.title },
  mainEntityOfPage: { '@type': 'WebPage', '@id': pageUrl },
  ...(thumbnail ? { image: thumbnail } : {}),
})} />

ポイント。

  • 日付は toISOString() で ISO 8601 にする(pubDatez.coerce.date() で Date 型なのでそのまま変換できる)。
  • dateModifiedupdatedDate があればそれを、無ければ pubDate を使う。
  • image は thumbnail があるときだけ入れる(スプレッド構文で条件付き追加)。

公開後は Google のリッチリザルトテストで検証できます。

OGP メタタグ

OGP は <head> にメタタグを並べるだけ。共通レイアウトで Props から流し込みます。

---
// src/layouts/BaseLayout.astro
const { title, description, ogImage } = Astro.props;
const canonicalUrl = new URL(Astro.url.pathname, SITE.url);
---
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:type" content="website" />
<meta property="og:url" content={canonicalUrl} />
{ogImage && <meta property="og:image" content={ogImage} />}
<meta name="twitter:card" content="summary" />

ハマりどころ:og:image とサムネイルは別物

注意点として、記事一覧のサムネイル画像と OGP 画像(og:image)は分けて考える必要があります。

このブログのサムネイルは SVG ですが、og:image に SVG を指定しても 多くの SNS はレンダリングしません。そのため、

  • サイト内のカード/ヘッダー画像 → SVG でOK
  • SNS シェア用の og:image → PNG/JPG を別途用意

という整理にしています(JSON-LD の image には SVG パスでも入れていますが、SNS のカード表示用には別途ラスタ画像が必要)。サムネを SVG で量産する話はこちら

メモ

  • JSON-LD は set:html={JSON.stringify(obj)} でオブジェクトから安全に出力できる。
  • 構造化データは Search Console の「拡張」やリッチリザルトテストで検証する。
  • OGP 画像は SVG 不可。SNS 重視なら専用のラスタOGPを用意する。

Astro, SEO