JSON-LD 丰富网页摘要的 GatsbyJS 架构
JSON-LD schema with GatsbyJS for rich snippets
我有一个基本的 Gatsby 博客设置,在 post 提出这个问题时 lacks good documentation for SEO components。有基本 SEO 组件的示例,但我想要的是更多 in-depth。也许,如果在这里达成解决方案,可以将其贡献给 Gatsby 文档,让其他人受益。
除了通常的标题和描述元标记以及 facebook/twitter 开放图元(我已经完成)之外,我想为 rich snippets which will vary depending on what the blog post type is. For example, I might have a regular post which would print Article schema, some posts might be How-to, in which case I'd like to print HowTo schema instead of Article. At some point I might write a post with would suit FAQ 架构添加结构化数据。
我不知道这是否是最好的方法,但这就是我的想法:
1。在 frontmatter 中,将我想要的模式类型设置为 true,其余的设置为 false。
我也在考虑将模式数据存储在 frontmatter 中,但由于此数据非常复杂,并且会从 post 类型到 post 类型(文章、方法等)不等,我'我不确定这是否是个好主意?
---
title: Hello World
description: How to say hello
article: false
how-to: true
faq: false
---
2。在 SEO 组件中测试 true/false 并打印正确的架构。
下面是我的整个 SEO 组件,这显然不起作用,但您可以希望看到我的想法。我已经从 gatsby advanced starter component and the gatsby starter prismic component 中剖析和借鉴,但都没有完全满足我的需要。这是我的:
import React from "react"
import Helmet from "react-helmet"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
import Facebook from "./Facebook"
import Twitter from "./Twitter"
const SEO = ({
title,
desc,
banner,
pathname,
published,
modified,
article,
webpage,
node,
}) => {
const { site } = useStaticQuery(query)
const {
buildTime,
siteMetadata: {
siteUrl,
defaultTitle,
defaultDescription,
defaultBanner,
headline,
siteLanguage,
ogLanguage,
author,
twitter,
facebook,
},
} = site
const seo = {
title: title || defaultTitle,
description: desc || defaultDescription,
image: `${siteUrl}${banner || defaultBanner}`,
url: `${siteUrl}${pathname || "/"}`,
date_published: published,
date_modified: modified,
}
// Default Website Schema
const schemaOrgJSONLD = [
{
"@context": "http://schema.org",
"@type": "WebSite",
url: siteUrl,
name: defaultTitle,
alternateName: headline ? headline : "",
},
]
if (howto) {
schemaOrgJSONLD.push({
/* HowTo Schema here */
})
}
if (faq) {
schemaOrgJSONLD.push({
/* FAQ Schema here */
})
}
if (article) {
schemaOrgJSONLD.push({
/* Regular Article Schema */
"@context": "http://schema.org",
"@type": "Article",
author: {
"@type": "Person",
name: author,
},
copyrightHolder: {
"@type": "Person",
name: author,
},
copyrightYear: "2019",
creator: {
"@type": "Person",
name: author,
},
publisher: {
"@type": "Organization",
name: author,
logo: {
"@type": "ImageObject",
url: `${siteUrl}${defaultBanner}`,
},
},
datePublished: seo.date_published,
dateModified: seo.date_modified,
description: seo.description,
headline: seo.title,
inLanguage: siteLanguage,
url: seo.url,
name: seo.title,
image: {
"@type": "ImageObject",
url: seo.image,
},
mainEntityOfPage: seo.url,
})
}
return (
<>
<Helmet title={seo.title}>
<html lang={siteLanguage} />
<meta name="description" content={seo.description} />
<meta name="image" content={seo.image} />
{/* Schema.org tags */}
<script type="application/ld+json">
{JSON.stringify(schemaOrgJSONLD)}
</script>
</Helmet>
<Facebook
desc={seo.description}
image={seo.image}
title={seo.title}
type={article ? "article" : "website"}
url={seo.url}
locale={ogLanguage}
name={facebook}
/>
<Twitter
title={seo.title}
image={seo.image}
desc={seo.description}
username={twitter}
/>
</>
)
}
export default SEO
SEO.propTypes = {
title: PropTypes.string,
desc: PropTypes.string,
banner: PropTypes.string,
pathname: PropTypes.string,
published: PropTypes.string,
modified: PropTypes.string,
article: PropTypes.bool,
webpage: PropTypes.bool,
node: PropTypes.object,
}
SEO.defaultProps = {
title: null,
desc: null,
banner: null,
pathname: null,
published: null,
modified: null,
article: false,
webpage: false,
node: null,
}
const query = graphql`
query SEO {
site {
buildTime(formatString: "YYYY-MM-DD")
siteMetadata {
siteUrl
defaultTitle: title
defaultDescription: description
defaultBanner: logo
headline
siteLanguage
ogLanguage
author
logo
twitter
facebook
}
}
}
`
我能看到的问题是:
- 如何测试要使用的模式类型并打印它
- 包括所有类型的面包屑架构
- 只打印一个模式 JSON-LD 脚本标签,避免任何重复的模式
- 是否在适合存储复杂模式数据的降价文件中使用 frontmatter
- 正在检索架构的 frontmatter 数据
我选择了这个解决方案。
前言:
---
type: howto // Use either 'article' or 'howto'
---
像查询其他数据一样使用 GraphQL 查询它:
frontmatter {
title
published(formatString: "MMMM DD, YYYY")
modified(formatString: "MMMM DD, YYYY")
description
type
}
将其传递给您的 SEO 组件:
<SEO
title={post.frontmatter.title}
desc={post.frontmatter.description}
published={post.frontmatter.published}
modified={post.frontmatter.modified}
type={post.frontmatter.type}
/>
在您的 SEO 组件中,您可以像这样使用它(对所有类型执行相同的操作)。您可以根据需要为我的类型、常见问题解答、课程等设置您的帖子和 SEO 组件:
const schemaType = type
if (schemaType === "howto") {
schemaHowTo = {
// Your howto schema here
}
}
if (schemaType === "article") {
schemaArticle = {
// Your article schema here
}
}
最后,在 React Helmet 中我们有:
<Helmet>
{schemaType === "howto" && (
<script type="application/ld+json">
{JSON.stringify(schemaHowTo)}
</script>
)}
{schemaType === "article" && (
<script type="application/ld+json">
{JSON.stringify(schemaArticle)}
</script>
)}
...
<Helmet>
刚刚找到关于该主题的精彩文章:https://www.iamtimsmith.com/blog/creating-a-better-seo-component-for-gatsby/
帮助我为我的应用程序中的所有页面动态创建丰富的代码段。
主要思想:将 children
传递给 seo.js
:
return (
<Helmet
htmlAttributes={{lang: `en`}}
titleTemplate={`%s | ${data.site.siteMetadata.title}`}
>
<title>{title}</title>
{children}
</Helmet>
);
然后在任何 page/component:
return (
<SEO title={title} description={description} image={image} slug={slug}>
<script type='application/ld+json'>
{`{
'@context': 'https://schema.org',
'@type': 'LiveBlogPosting',
'@id': 'https://example.com',
'headline': ${title},
'description': ${description}
}`}
</script>
</SEO>
);
};
我有一个基本的 Gatsby 博客设置,在 post 提出这个问题时 lacks good documentation for SEO components。有基本 SEO 组件的示例,但我想要的是更多 in-depth。也许,如果在这里达成解决方案,可以将其贡献给 Gatsby 文档,让其他人受益。
除了通常的标题和描述元标记以及 facebook/twitter 开放图元(我已经完成)之外,我想为 rich snippets which will vary depending on what the blog post type is. For example, I might have a regular post which would print Article schema, some posts might be How-to, in which case I'd like to print HowTo schema instead of Article. At some point I might write a post with would suit FAQ 架构添加结构化数据。
我不知道这是否是最好的方法,但这就是我的想法:
1。在 frontmatter 中,将我想要的模式类型设置为 true,其余的设置为 false。
我也在考虑将模式数据存储在 frontmatter 中,但由于此数据非常复杂,并且会从 post 类型到 post 类型(文章、方法等)不等,我'我不确定这是否是个好主意?
---
title: Hello World
description: How to say hello
article: false
how-to: true
faq: false
---
2。在 SEO 组件中测试 true/false 并打印正确的架构。
下面是我的整个 SEO 组件,这显然不起作用,但您可以希望看到我的想法。我已经从 gatsby advanced starter component and the gatsby starter prismic component 中剖析和借鉴,但都没有完全满足我的需要。这是我的:
import React from "react"
import Helmet from "react-helmet"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
import Facebook from "./Facebook"
import Twitter from "./Twitter"
const SEO = ({
title,
desc,
banner,
pathname,
published,
modified,
article,
webpage,
node,
}) => {
const { site } = useStaticQuery(query)
const {
buildTime,
siteMetadata: {
siteUrl,
defaultTitle,
defaultDescription,
defaultBanner,
headline,
siteLanguage,
ogLanguage,
author,
twitter,
facebook,
},
} = site
const seo = {
title: title || defaultTitle,
description: desc || defaultDescription,
image: `${siteUrl}${banner || defaultBanner}`,
url: `${siteUrl}${pathname || "/"}`,
date_published: published,
date_modified: modified,
}
// Default Website Schema
const schemaOrgJSONLD = [
{
"@context": "http://schema.org",
"@type": "WebSite",
url: siteUrl,
name: defaultTitle,
alternateName: headline ? headline : "",
},
]
if (howto) {
schemaOrgJSONLD.push({
/* HowTo Schema here */
})
}
if (faq) {
schemaOrgJSONLD.push({
/* FAQ Schema here */
})
}
if (article) {
schemaOrgJSONLD.push({
/* Regular Article Schema */
"@context": "http://schema.org",
"@type": "Article",
author: {
"@type": "Person",
name: author,
},
copyrightHolder: {
"@type": "Person",
name: author,
},
copyrightYear: "2019",
creator: {
"@type": "Person",
name: author,
},
publisher: {
"@type": "Organization",
name: author,
logo: {
"@type": "ImageObject",
url: `${siteUrl}${defaultBanner}`,
},
},
datePublished: seo.date_published,
dateModified: seo.date_modified,
description: seo.description,
headline: seo.title,
inLanguage: siteLanguage,
url: seo.url,
name: seo.title,
image: {
"@type": "ImageObject",
url: seo.image,
},
mainEntityOfPage: seo.url,
})
}
return (
<>
<Helmet title={seo.title}>
<html lang={siteLanguage} />
<meta name="description" content={seo.description} />
<meta name="image" content={seo.image} />
{/* Schema.org tags */}
<script type="application/ld+json">
{JSON.stringify(schemaOrgJSONLD)}
</script>
</Helmet>
<Facebook
desc={seo.description}
image={seo.image}
title={seo.title}
type={article ? "article" : "website"}
url={seo.url}
locale={ogLanguage}
name={facebook}
/>
<Twitter
title={seo.title}
image={seo.image}
desc={seo.description}
username={twitter}
/>
</>
)
}
export default SEO
SEO.propTypes = {
title: PropTypes.string,
desc: PropTypes.string,
banner: PropTypes.string,
pathname: PropTypes.string,
published: PropTypes.string,
modified: PropTypes.string,
article: PropTypes.bool,
webpage: PropTypes.bool,
node: PropTypes.object,
}
SEO.defaultProps = {
title: null,
desc: null,
banner: null,
pathname: null,
published: null,
modified: null,
article: false,
webpage: false,
node: null,
}
const query = graphql`
query SEO {
site {
buildTime(formatString: "YYYY-MM-DD")
siteMetadata {
siteUrl
defaultTitle: title
defaultDescription: description
defaultBanner: logo
headline
siteLanguage
ogLanguage
author
logo
twitter
facebook
}
}
}
`
我能看到的问题是:
- 如何测试要使用的模式类型并打印它
- 包括所有类型的面包屑架构
- 只打印一个模式 JSON-LD 脚本标签,避免任何重复的模式
- 是否在适合存储复杂模式数据的降价文件中使用 frontmatter
- 正在检索架构的 frontmatter 数据
我选择了这个解决方案。
前言:
---
type: howto // Use either 'article' or 'howto'
---
像查询其他数据一样使用 GraphQL 查询它:
frontmatter {
title
published(formatString: "MMMM DD, YYYY")
modified(formatString: "MMMM DD, YYYY")
description
type
}
将其传递给您的 SEO 组件:
<SEO
title={post.frontmatter.title}
desc={post.frontmatter.description}
published={post.frontmatter.published}
modified={post.frontmatter.modified}
type={post.frontmatter.type}
/>
在您的 SEO 组件中,您可以像这样使用它(对所有类型执行相同的操作)。您可以根据需要为我的类型、常见问题解答、课程等设置您的帖子和 SEO 组件:
const schemaType = type
if (schemaType === "howto") {
schemaHowTo = {
// Your howto schema here
}
}
if (schemaType === "article") {
schemaArticle = {
// Your article schema here
}
}
最后,在 React Helmet 中我们有:
<Helmet>
{schemaType === "howto" && (
<script type="application/ld+json">
{JSON.stringify(schemaHowTo)}
</script>
)}
{schemaType === "article" && (
<script type="application/ld+json">
{JSON.stringify(schemaArticle)}
</script>
)}
...
<Helmet>
刚刚找到关于该主题的精彩文章:https://www.iamtimsmith.com/blog/creating-a-better-seo-component-for-gatsby/
帮助我为我的应用程序中的所有页面动态创建丰富的代码段。
主要思想:将 children
传递给 seo.js
:
return (
<Helmet
htmlAttributes={{lang: `en`}}
titleTemplate={`%s | ${data.site.siteMetadata.title}`}
>
<title>{title}</title>
{children}
</Helmet>
);
然后在任何 page/component:
return (
<SEO title={title} description={description} image={image} slug={slug}>
<script type='application/ld+json'>
{`{
'@context': 'https://schema.org',
'@type': 'LiveBlogPosting',
'@id': 'https://example.com',
'headline': ${title},
'description': ${description}
}`}
</script>
</SEO>
);
};