やること
ブログでよくある「関連記事」をGatsbyで実装する。 特定のブログ記事に関連した記事を表示することで、ユーザーの直帰率を下げることにも繋がる。更に滞在時間や平均PVが上がればSEO効果のプラスも期待できる。
Gatsbyの場合はGraphqlのQueryを使って関連記事を取得する。
関連記事が複数ある場合、それぞれの記事の関連度を数値化してソートするロジックがあればベストだけど、今回はシンプルに同じタグを持つ記事を関連記事として取得する。
前提
記事は以下のようなフォーマットで、
blog.md
---
title: "blog title"
description: "blog description"
tags: ["tag1", "tag2", ...]
---
記事を表示するページでは以下のように取得しているものとして進める。
// blogPost.js
export const BlogPost = () => {
// ...
}
export const pageQuery = graphql`
query BlogPost($id: String!) {
markdownRemark(id: { eq: $id }) {
id
frontmatter {
title
description
tags
}
}
}
`
resolverを作る
特定の条件に見合う記事を取得するには、専用のresolverを定義してやればいい。Gatsbyではgatsby-node.jsの中で、createResolversというAPIを使うことで新たなresolverを定義することができる。
// gatsby-node.js
exports.createResolvers = ({ createResolvers }) => {
const resolvers = { /* your resolver */ }
createResolvers(resolvers)
}
今回の場合は以下のような記述になる。
// gatsby-node.js
exports.createResolvers = ({ createResolvers }) => {
const resolvers = {
MarkdownRemark: {
relatedPosts: {
type: ['MarkdownRemark'],
resolve: (source, args, context, info) => {
return context.nodeModel.runQuery({
query: {
filter: {
id: {
ne: source.id,
},
frontmatter: {
tags: {
in: source.frontmatter.tags,
},
},
},
},
type: 'MarkdownRemark',
})
},
},
},
}
createResolvers(resolvers)
}
このresolverではmarkdownRemarkの中にrelatedPostsという新たなフィールドを作っている。relatedPostsは記事の配列なのでタイプをtype: ['MarkdownRemark']
と指定する。
resolve() の中ではMarkdownRemarkタイプのデータの中から、同じtagを持つ記事だけを取得している。 そのままだと関連元の記事自体も取得してしまうので、idで選別して除外している。
id: {
ne: source.id,
},
あとはQueryを更新すれば関連記事を取得することができる。
// blogPost.js
export const BlogPost = () => {
// ...
}
export const pageQuery = graphql`
query BlogPost($id: String!) {
markdownRemark(id: { eq: $id }) {
id
frontmatter {
title
description
tags
}
relatedPosts {
frontmatter {
title
}
}
}
}
`