Skip to content

Instantly share code, notes, and snippets.

@devraj
Created July 27, 2021 04:55
Show Gist options
  • Save devraj/4dbd4cf830382fe047cf7b403dafc36d to your computer and use it in GitHub Desktop.
Save devraj/4dbd4cf830382fe047cf7b403dafc36d to your computer and use it in GitHub Desktop.
SEO component for Gatsby with Twitter card
import React from "react"
import PropTypes from "prop-types"
import { Helmet } from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"
function Seo({ description, lang, meta, image: metaImage, title, pathname }) {
const { site } = useStaticQuery(
graphql`
query {
site {
siteMetadata {
title
description
author
keywords
siteUrl
}
}
}
`
)
const metaDescription = description || site.siteMetadata.description
const image =
metaImage && metaImage.src
? `${site.siteMetadata.siteUrl}${metaImage.src}`
: null
const canonical = pathname ? `${site.siteMetadata.siteUrl}${pathname}` : null
return (
<Helmet
htmlAttributes={{
lang,
}}
title={title}
titleTemplate={`%s | ${site.siteMetadata.title}`}
link={
canonical
? [
{
rel: "canonical",
href: canonical,
},
]
: []
}
meta={[
{
name: `description`,
content: metaDescription,
},
{
name: "keywords",
content: site.siteMetadata.keywords.join(","),
},
{
property: `og:title`,
content: title,
},
{
property: `og:description`,
content: metaDescription,
},
{
property: `og:type`,
content: `website`,
},
{
name: `twitter:creator`,
content: site.siteMetadata.author,
},
{
name: `twitter:title`,
content: title,
},
{
name: `twitter:description`,
content: metaDescription,
},
]
.concat(
metaImage
? [
{
property: "og:image",
content: image,
},
{
property: "og:image:width",
content: metaImage.width,
},
{
property: "og:image:height",
content: metaImage.height,
},
{
name: "twitter:image",
content: image,
},
{
name: "twitter:card",
content: "summary_large_image",
},
]
: [
{
name: "twitter:card",
content: "summary",
},
]
)
.concat(meta)}
/>
)
}
Seo.defaultProps = {
lang: `en`,
meta: [],
description: ``,
}
Seo.propTypes = {
description: PropTypes.string,
lang: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired,
image: PropTypes.shape({
src: PropTypes.string.isRequired,
height: PropTypes.number.isRequired,
width: PropTypes.number.isRequired,
}),
pathname: PropTypes.string,
}
export default Seo
@devraj
Copy link
Author

devraj commented Jul 27, 2021

Working example in Gatsby site:

const IndexPage = () => {
  const socialImage = {
    src: "/social.jpg",
    height: 1500,
    width: 3000
  }
  return (
    <Layout>
      <Seo 
        title="EV charging concierge"
        description="Privacy focused EV charging concierge for destinations"
        image={socialImage}
      />
      <Hero/>
      <HowItWorksSummary/>
      <Featured/>
      <StripeClimate/>
    </Layout>
  )
}

export default IndexPage

assumes that the file is in the static folder. Images used on Twitter cards must have a 2:1 ratio.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment