Схема JSON-LD с GatsbyJS для богатых фрагментов - PullRequest
0 голосов
/ 12 ноября 2019

У меня есть базовая настройка блога с Gatsby, и на момент публикации этого вопроса не хватает хорошей документации для SEO-компонентов . Есть примеры основных компонентов SEO, но я хочу немного углубиться. Возможно, если решение будет достигнуто здесь, оно может быть внесено в документы Gatsby для других пользователей.

Помимо обычных метатегов заголовка и описания и мета открытого графика в Facebook / Twitter (что я и сделал)уже), я хочу добавить структурированные данные для богатых фрагментов , которые будут варьироваться в зависимости от типа сообщения в блоге. Например, у меня может быть обычное сообщение, которое будет печатать схему Article , некоторые сообщения могут быть How-to , в этом случае я хотел бы напечатать схему HowTo вместо Article. В какой-то момент я мог бы написать сообщение с подходящей схемой 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, который, очевидно, не работает, но вы можете надеяться увидеть, куда движется мое мышление. Я проанализировал и позаимствовал у усовершенствованный стартовый компонент Гэтсби и призматический компонент Гэтсби , но ни тот, ни другой не делают то, что мне нужно. Вот мое:

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. Использует frontmatter в файлах уценки, подходящих для хранения сложных данных схемы
  5. Получение данных frontmatterдля схемы
...