Skip to content

Instantly share code, notes, and snippets.

@masimplo
Created March 14, 2019 08:11
Show Gist options
  • Save masimplo/d46930547805c17e669c0a97ed966178 to your computer and use it in GitHub Desktop.
Save masimplo/d46930547805c17e669c0a97ed966178 to your computer and use it in GitHub Desktop.
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';
// Complete tutorial: https://www.gatsbyjs.org/docs/add-seo-component/
const SEO = ({ title, description, banner, pathname, article, lang, robots, node }) => {
const { site } = useStaticQuery(query);
const {
buildTime,
siteMetadata: {
siteUrl,
defaultTitle,
defaultDescription,
defaultBanner,
headline,
siteLanguage,
ogLanguage,
author,
twitter,
facebook,
logo
},
} = site;
const seo = {
title: title || defaultTitle,
description: description || defaultDescription,
image: `${ banner || defaultBanner }`,
url: `${ siteUrl }${ pathname || '' }`,
lang: lang || siteLanguage,
robots: robots || null
};
// schema.org in JSONLD format
// https://developers.google.com/search/docs/guides/intro-structured-data
// You can fill out the 'author', 'creator' with more data or another type (e.g. 'Organization')
const schemaOrgWebPage = {
'@context': 'http://schema.org',
'@type': 'WebPage',
url: siteUrl,
headline,
inLanguage: siteLanguage,
mainEntityOfPage: siteUrl,
description: defaultDescription,
name: defaultTitle,
author: {
'@type': 'Organization',
name: author,
},
copyrightHolder: {
'@type': 'Organization',
name: author,
},
copyrightYear: '2019',
creator: {
'@type': 'Organization',
name: author,
},
publisher: {
'@type': 'Organization',
name: author,
},
datePublished: '2019-01-18T10:30:00+01:00',
dateModified: buildTime,
image: {
'@type': 'ImageObject',
url: `${ siteUrl }${ defaultBanner }`,
},
};
const schemaOrgOrganization = {
'@context': 'http://schema.org',
'@type': 'Organization',
'@id': `${ siteUrl }#organization`,
'legalName': 'example Network Ltd',
url: siteUrl,
name: author,
logo: logo,
contactPoint: {
'@type': 'ContactPoint',
'contactType': 'customer support',
'email': 'support@example.com'
},
sameAs: [
'https://www.facebook.com/example',
'https://plus.google.com/+example',
'https://www.youtube.com/channel/UCABc2e0MYiKdwwIlG_zHB0w',
'https://twitter.com/example',
]
};
// Initial breadcrumb list
const itemListElement = [
{
'@type': 'ListItem',
item: {
'@id': siteUrl,
name: 'Homepage',
},
position: 1,
},
];
let schemaArticle = null;
if (article) {
schemaArticle = {
'@context': 'http://schema.org',
'@type': 'Article',
author: {
'@type': 'Organization',
name: author,
},
copyrightHolder: {
'@type': 'Organization',
name: author,
},
copyrightYear: '2019',
creator: {
'@type': 'Organization',
name: author,
},
publisher: {
'@type': 'Organization',
name: author,
logo: {
'@type': 'ImageObject',
url: `${ siteUrl }${ defaultBanner }`,
},
},
datePublished: node.first_publication_date,
dateModified: node.last_publication_date,
description: seo.description,
headline: seo.title,
inLanguage: seo.lang,
url: seo.url,
name: seo.title,
image: {
'@type': 'ImageObject',
url: seo.image,
},
mainEntityOfPage: seo.url,
};
// Push current blogpost into breadcrumb list
itemListElement.push({
'@type': 'ListItem',
item: {
'@id': seo.url,
name: seo.title,
},
position: 2,
});
}
const breadcrumb = {
'@context': 'http://schema.org',
'@type': 'BreadcrumbList',
description: 'Breadcrumbs list',
name: 'Breadcrumbs',
itemListElement,
};
return (
<>
<Helmet title={seo.title}>
<html lang={seo.lang} />
<meta name="description" content={seo.description} />
<meta name="image" content={seo.image} />
<meta name="example" content="example" />
<meta name="apple-itunes-app" content="app-id=123" />
{seo.robots && <meta name="robots" content={seo.robots} />}
{/* Insert schema.org data conditionally (webpage/article) + everytime (breadcrumbs) */}
{!article && <script type="application/ld+json">{JSON.stringify(schemaOrgWebPage)}</script>}
{article && <script type="application/ld+json">{JSON.stringify(schemaArticle)}</script>}
<script type="application/ld+json">{JSON.stringify(schemaOrgOrganization)}</script>
<script type="application/ld+json">{JSON.stringify(breadcrumb)}</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,
description: PropTypes.string,
banner: PropTypes.string,
pathname: PropTypes.string,
article: PropTypes.bool,
node: PropTypes.object,
lang: PropTypes.string,
robots: PropTypes.string
};
SEO.defaultProps = {
title: null,
description: null,
banner: null,
pathname: null,
article: false,
lang: null,
node: null,
robots: null
};
const query = graphql`
query SEO {
site {
buildTime(formatString: "YYYY-MM-DD")
siteMetadata {
siteUrl
defaultTitle: title
defaultDescription: description
defaultBanner: banner
headline
siteLanguage
ogLanguage
author
twitter
facebook
}
}
}
`
;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment