Next.jsでブログ記事の構造化データ(JSON-LD)を生成する
ブログのNext.js移行に伴い、構造化データ(JSON-LD)も生成する必要があったので対応した。
実装
- HeadコンポーネントにてjsonLDを表示できるようにしておく(抜粋)
※ そのまま表示するとjsonがエスケープされてしまうのでdangerouslySetInnerHTMLでrawDataを表示する
// components/Head.tsx
import { default as NextHead } from 'next/head'
import React from 'react'
type Props = {
title?: string
jsonLd?: string
}
export const Head = ({ title, jsonLd }: Props) => {
const defaultTitle = process.env.NEXT_PUBLIC_SITE_NAME
return (
<NextHead>
<title>{title || defaultTitle}</title>
{jsonLd && (
<script
key="json-ld"
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: jsonLd }}
/>
)}
</NextHead>
)
}
- 記事ページでJSON-LDを生成してHeadコンポーネントに渡す(抜粋)
// pages/posts/[slug].tsx
import React from 'react'
const generateJsonLd = (post: BlogPost) => {
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL
const path = `/posts/${post.slug}`
const url = `${siteUrl}${path}`
const defaultOgp = `${siteUrl}/images/ogp.png`
const imageUrl = post.coverImage?.url || defaultOgp
const jsonLd = {
'@context': 'http://schema.org',
'@type': 'Article',
name: post.title,
headline: post.title,
datePublished: post.publishDate,
dateModified: post.publishDate,
url: url,
mainEntityOfPage: url,
image: [imageUrl],
description: post.description,
author: {
'@type': 'Person',
name: 'hello world',
},
publisher: {
'@type': 'Organization',
name: process.env.NEXT_PUBLIC_SITE_NAME,
logo: {
'@type': 'ImageObject',
url: defaultOgp,
},
},
}
return JSON.stringify(jsonLd)
}
type Props = {
post: BlogPost | null
}
const PostPage = ({ post }: Props) => {
return (
<Layout>
<Container>
<Header />
<Head
title={post.title}
jsonLd={generateJsonLd(post)}
/>
<article>
<PostHeader />
<PostContent content={post.body} />
</article>
)}
</Container>
</Layout>
)
}
export default PostPag
確認方法
以前は「構造化データ テストツール」で確認していたが近々廃止になるらしく、代わりに「 リッチリザルト テスト - Google Search Console」を利用して確認を行った。