Skip to content

Commit 1e98270

Browse files
committed
Add structured data for breadcrumbs.
1 parent 7e8b729 commit 1e98270

File tree

4 files changed

+74
-18
lines changed

4 files changed

+74
-18
lines changed

src/components/SEO.tsx

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ type SEOProps = {
1717
width: number
1818
}
1919
pathname?: string
20+
breadcrumbs?: Array<{
21+
name: string
22+
url?: string
23+
}>
2024
}
2125

2226
export const SEO: React.FC<SEOProps> = ({
@@ -25,7 +29,8 @@ export const SEO: React.FC<SEOProps> = ({
2529
meta,
2630
image,
2731
title,
28-
pathname
32+
pathname,
33+
breadcrumbs = []
2934
}) => {
3035
const { site } = useStaticQuery(
3136
graphql`
@@ -127,6 +132,34 @@ export const SEO: React.FC<SEOProps> = ({
127132
]
128133
)
129134
.concat(meta as any)}
135+
script={
136+
breadcrumbs.length > 0
137+
? [
138+
{
139+
type: 'application/ld+json',
140+
innerHTML: `
141+
{
142+
"@context": "https://schema.org",
143+
"@type": "BreadcrumbList",
144+
"itemListElement": [${JSON.stringify(
145+
breadcrumbs.map((crumb, i) => {
146+
const item: any = {
147+
'@type': 'ListItem',
148+
position: i + 1,
149+
name: crumb.name
150+
}
151+
if (crumb.url) {
152+
item.item = `${site.siteMetadata.siteUrl}${crumb.url}`
153+
}
154+
return item
155+
})
156+
)}]
157+
}
158+
`
159+
}
160+
]
161+
: undefined
162+
}
130163
/>
131164
)
132165
}

src/layouts/PostLayout.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { formatRFC7231 } from 'date-fns'
33

44
import * as S from './PostLayout.styles'
55
import { MainLayout } from './MainLayout'
6-
import { SEO } from '../components/SEO'
76

87
type PostLayoutProps = {
98
title: string
@@ -25,7 +24,6 @@ export const PostLayout: React.FC<PostLayoutProps> = ({
2524
}) => {
2625
return (
2726
<MainLayout {...more}>
28-
<SEO title={title} />
2927
<S.Container>
3028
<S.PostCategory>{category}</S.PostCategory>
3129
<S.PostTitle>{title}</S.PostTitle>

src/pages/{MarkdownRemark.frontmatter__slug}.tsx

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { graphql } from 'gatsby'
33
import { parseISO } from 'date-fns'
44

55
import { PostLayout } from '../layouts/PostLayout'
6+
import { getBlogNameById } from '../utils/blog'
7+
import { SEO } from '../components/SEO'
68

79
type TemplateProps = {
810
data: {
@@ -38,23 +40,27 @@ const Template: React.FC<TemplateProps> = ({ data, ...more }) => {
3840
const previousSlug = slugs[slugs.indexOf(frontmatter.slug) - 1]
3941
const nextSlug = slugs[slugs.indexOf(frontmatter.slug) + 1]
4042

41-
const category =
42-
categoryId === 'lymphoma'
43-
? 'Lymphoma'
44-
: categoryId === 'code'
45-
? 'Code'
46-
: 'Secret'
43+
const category = getBlogNameById(categoryId)
4744

4845
return (
49-
<PostLayout
50-
{...more}
51-
title={frontmatter.title}
52-
date={parseISO(frontmatter.date)}
53-
category={category}
54-
contents={html}
55-
previousSlug={previousSlug}
56-
nextSlug={nextSlug}
57-
/>
46+
<>
47+
<SEO
48+
title={frontmatter.title}
49+
breadcrumbs={[
50+
{ name: category, url: `/${categoryId}` },
51+
{ name: frontmatter.title }
52+
]}
53+
/>
54+
<PostLayout
55+
{...more}
56+
title={frontmatter.title}
57+
date={parseISO(frontmatter.date)}
58+
category={category}
59+
contents={html}
60+
previousSlug={previousSlug}
61+
nextSlug={nextSlug}
62+
/>
63+
</>
5864
)
5965
}
6066

src/utils/blog.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const blogIds = ['lymphoma', 'code'] as const
2+
type BlogId = typeof blogIds[number]
3+
4+
const isBlogId = (source: any): source is BlogId => {
5+
return blogIds.includes(source)
6+
}
7+
8+
export const getBlogNameById = (id: string): string => {
9+
if (!isBlogId(id)) {
10+
return 'General'
11+
}
12+
13+
switch (id) {
14+
case 'lymphoma':
15+
return 'Lymphoma'
16+
case 'code':
17+
return 'Code'
18+
}
19+
}

0 commit comments

Comments
 (0)