javascript - JSON-LD 模式与 GatsbyJS 的丰富片段

标签 javascript reactjs gatsby google-rich-snippets

我有一个基本的 Gatsby 博客设置,在发布这个问题时lacks good documentation for SEO components 。有一些基本 SEO 组件的示例,但我想要的是更深入的一点。也许,如果在这里达成解决方案,它可以贡献给 Gatsby 文档,让其他人受益。

除了通常的标题和描述元标记以及 facebook/twitter 开放图元(我已经完成)之外,我想为 rich snippets 添加结构化数据这将根据博客文章类型的不同而有所不同。例如,我可能有一个常规帖子,会打印 Article架构,有些帖子可能是 How-to ,在这种情况下,我想打印 HowTo 模式而不是文章。在某些时候,我可能会写一篇适合 FAQ 的帖子架构。

我不知道这是否是最好的方法,但这就是我的想法:

1。在 frontmatter 中将我想要的模式类型设置为 true,其余保留为 false。

我也在考虑将模式数据存储在 frontmatter 中,但由于该数据非常复杂,并且会因帖子类型(文章、HowTo 等)而异,我不确定这是否是一个好主意?

---
title: Hello World
description: How to say hello
article: false
how-to: true
faq: false
---

2。在 SEO 组件中测试真/假并打印正确的架构。

下面是我的整个 SEO 组件,它显然不起作用,但你希望能看到我的想法。我已经剖析并借鉴了gatsby advanced starter componentgatsby 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
      }
    }
  }
`

我看到的问题是:

  1. 如何测试要使用的架构类型并打印它
  2. 包含所有类型的面包屑架构
  3. 仅打印单个架构 JSON-LD 脚本标记,避免任何重复的架构
  4. 在 Markdown 文件中使用 frontmatter 是否适合存储复杂的架构数据
  5. 检索架构的 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 组件,如我的类型、常见问题解答、类(class)等:

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>

关于javascript - JSON-LD 模式与 GatsbyJS 的丰富片段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58808915/

相关文章:

reactjs - 通过使用 "Snapshots"的关键路由(静态渲染)来加速大型 React 项目的最佳方法

reactjs - 为什么渲染函数没有在react中调用?

reactjs - 在 Gatsby 中添加 PDF 文件

javascript - 焦点事件被另一个焦点事件忽略

javascript - 调整窗口大小时按类名触发调整文本区域大小

Javascript 函数接受一个段落作为参数并返回一个名称数组

node.js - AWS API网关WebSocket API : how to use it with React/NodeJS/native WebSocket?

node.js - 在 Gatsby 构建期间检索文件内容

reactjs - 如何在 React 中的不同文件之间共享变量数据

javascript - 无法确定为什么canvas drawImage无法处理PNG图像