1
0
mirror of https://github.com/oceanprotocol/docs.git synced 2024-11-26 19:49:26 +01:00

SEO component

* Twitter Cards
* OpenGraph
* schema.org
This commit is contained in:
Matthias Kretschmann 2018-11-22 20:58:42 +01:00
parent 22ba5c0e7e
commit bbb67d779b
Signed by: m
GPG Key ID: 606EEEF3C479A91F
4 changed files with 128 additions and 52 deletions

View File

@ -17,10 +17,65 @@ const query = graphql`
} }
} }
} }
logo: allFile(filter: { name: { eq: "favicon-black" } }) {
edges {
node {
relativePath
}
}
}
} }
` `
const MetaTags = ({ title, description, url, image, schema, siteMeta }) => ( const createSchemaOrg = (title, description, image, url, siteMeta, article) => {
const schemaOrgJSONLD = [
{
'@context': 'http://schema.org',
'@type': 'WebSite',
url: siteMeta.siteUrl,
name: title
}
]
if (article) {
schemaOrgJSONLD.push(
{
'@context': 'http://schema.org',
'@type': 'BreadcrumbList',
itemListElement: [
{
'@type': 'ListItem',
position: 1,
item: { '@id': url, name: title, image }
}
]
},
{
// https://schema.org/TechArticle
'@context': 'http://schema.org',
'@type': 'TechArticle',
name: title,
headline: title,
description,
url,
image: { '@type': 'URL', url: image }
}
)
}
return schemaOrgJSONLD
}
const MetaTags = ({
title,
description,
url,
image,
schema,
siteMeta,
article
}) => (
<Helmet <Helmet
defaultTitle={siteMeta.siteTitle} defaultTitle={siteMeta.siteTitle}
titleTemplate={`%s - ${siteMeta.siteTitle}`} titleTemplate={`%s - ${siteMeta.siteTitle}`}
@ -41,17 +96,14 @@ const MetaTags = ({ title, description, url, image, schema, siteMeta }) => (
{/* OpenGraph tags */} {/* OpenGraph tags */}
<meta property="og:url" content={url} /> <meta property="og:url" content={url} />
{documentSEO && <meta property="og:type" content="article" />} {article && <meta property="og:type" content="article" />}
<meta property="og:title" content={title} /> <meta property="og:title" content={title} />
<meta property="og:description" content={description} /> <meta property="og:description" content={description} />
<meta property="og:image" content={image} /> <meta property="og:image" content={image} />
{/* Twitter Card tags */} {/* Twitter Card tags */}
<meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:card" content="summary_large_image" />
<meta <meta name="twitter:creator" content={siteMeta.social.twitter || ''} />
name="twitter:creator"
content={siteMeta.social.twitter ? siteMeta.social.twitter : ''}
/>
<meta name="twitter:title" content={title} /> <meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} /> <meta name="twitter:description" content={description} />
<meta name="twitter:image" content={image} /> <meta name="twitter:image" content={image} />
@ -59,27 +111,46 @@ const MetaTags = ({ title, description, url, image, schema, siteMeta }) => (
) )
MetaTags.propTypes = { MetaTags.propTypes = {
description: PropTypes.string,
image: PropTypes.string,
url: PropTypes.string,
schema: PropTypes.string,
title: PropTypes.string, title: PropTypes.string,
siteMeta: PropTypes.object description: PropTypes.string,
url: PropTypes.string,
image: PropTypes.string,
schema: PropTypes.string,
siteMeta: PropTypes.object,
article: PropTypes.bool
} }
const SEO = ({ title, description, slug }) => ( const SEO = ({ title, description, slug, article }) => (
<StaticQuery <StaticQuery
query={query} query={query}
render={data => { render={data => {
const siteMeta = data.site.siteMetadata const siteMeta = data.site.siteMetadata
const logo = data.logo.edges[0].node.relativePath
title = title || siteMeta.siteTitle
description = description || siteMeta.siteDescription
let url = siteMeta.siteUrl || siteMeta.siteUrl + slug
let image = `${siteMeta.siteUrl}/${logo}`
let schema = createSchemaOrg(
title,
description,
image,
url,
siteMeta,
article
)
schema = JSON.stringify(schema)
return ( return (
<MetaTags <MetaTags
description={description}
// image={image}
url={url}
title={title} title={title}
description={description}
url={url}
image={image}
schema={schema}
siteMeta={siteMeta} siteMeta={siteMeta}
article={article}
/> />
) )
}} }}
@ -89,7 +160,8 @@ const SEO = ({ title, description, slug }) => (
SEO.propTypes = { SEO.propTypes = {
title: PropTypes.string, title: PropTypes.string,
description: PropTypes.string, description: PropTypes.string,
slug: PropTypes.string slug: PropTypes.string,
article: PropTypes.bool
} }
export default SEO export default SEO

View File

@ -6,7 +6,7 @@ import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import giphyAPI from 'giphy-js-sdk-core' import giphyAPI from 'giphy-js-sdk-core'
import Helmet from 'react-helmet' import SEO from '../components/Seo'
import Layout from '../components/Layout' import Layout from '../components/Layout'
import Content from '../components/Content' import Content from '../components/Content'
import styles from './404.module.scss' import styles from './404.module.scss'
@ -45,7 +45,7 @@ export default class NotFoundPage extends Component {
render() { render() {
return ( return (
<> <>
<Helmet title="404 - Not Found" /> <SEO title="404 - Not Found" />
<Layout location={this.props.location}> <Layout location={this.props.location}>
<Content> <Content>
<article className={styles.content}> <article className={styles.content}>

View File

@ -13,6 +13,25 @@ import DocFooter from '../components/DocFooter'
import SEO from '../components/Seo' import SEO from '../components/Seo'
import styles from './Doc.module.scss' import styles from './Doc.module.scss'
const DocMain = ({ title, description, tableOfContents, post, single }) => (
<article className={single ? styles.mainSingle : styles.main}>
<DocHeader title={title} description={description} />
{tableOfContents && <DocToc tableOfContents={tableOfContents} />}
<DocContent html={post.html} htmlAst={post.htmlAst} />
<DocFooter post={post} />
</article>
)
DocMain.propTypes = {
title: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
tableOfContents: PropTypes.string.isRequired,
post: PropTypes.object.isRequired,
single: PropTypes.bool
}
export default class DocTemplate extends Component { export default class DocTemplate extends Component {
static propTypes = { static propTypes = {
data: PropTypes.object.isRequired, data: PropTypes.object.isRequired,
@ -41,7 +60,12 @@ export default class DocTemplate extends Component {
<body className={section} /> <body className={section} />
</Helmet> </Helmet>
<SEO title={title} description={description} slug={slug} /> <SEO
title={title}
description={description}
slug={slug}
article
/>
<Layout location={location}> <Layout location={location}>
<HeaderSection title={section ? sectionTitle : title} /> <HeaderSection title={section ? sectionTitle : title} />
@ -55,42 +79,21 @@ export default class DocTemplate extends Component {
sidebar={section} sidebar={section}
/> />
</aside> </aside>
<article className={styles.main}> <DocMain
<DocHeader
title={title}
description={description}
/>
{tableOfContents && (
<DocToc
tableOfContents={tableOfContents}
/>
)}
<DocContent
html={post.html}
htmlAst={post.htmlAst}
/>
<DocFooter post={post} />
</article>
</main>
) : (
<article className={styles.mainSingle}>
<DocHeader
title={title} title={title}
description={description} description={description}
tableOfContents={tableOfContents}
post={post}
/> />
</main>
{tableOfContents && ( ) : (
<DocToc tableOfContents={tableOfContents} /> <DocMain
)} title={title}
description={description}
<DocContent tableOfContents={tableOfContents}
html={post.html} post={post}
htmlAst={post.htmlAst} single
/> />
<DocFooter post={post} />
</article>
)} )}
</Content> </Content>
</Layout> </Layout>
@ -112,6 +115,7 @@ export const pageQuery = graphql`
} }
fields { fields {
section section
slug
} }
...PageFooter ...PageFooter
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB