question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Facebook Share not picking up OpenGraph meta tags from Gatsby site via React Helmet.

See original GitHub issue

Description

Facebook Share not picking up OpenGraph meta tags from Gatsby site via React Helmet.

Steps to reproduce

I have an SEO component that renders React Helmet meta tags like so:

# seo.js

import React from 'react'
import PropTypes from 'prop-types'
import { Helmet } from 'react-helmet'
import { useStaticQuery, graphql } from 'gatsby'

function SEO({ description, lang, meta, title, pageUrl, image, post, children }) {
  const { site } = useStaticQuery(
    graphql`
      query {
        site {
          siteMetadata {
            title
            description
            siteUrl
            author
          }
        }
      }
    `
  )

  const metaDescription = description || site.siteMetadata.description
  const metaTitle = title || site.siteMetadata.title
  const metaUrl = pageUrl || site.siteMetadata.siteUrl

  return (
    <Helmet
      defer={false}
      htmlAttributes={{
        lang,
      }}
      defaultTitle={metaTitle}
      titleTemplate={`%s`}
      meta={meta}
    >
      {/* General tags */}
      <title>{metaTitle}</title>
      <meta name="image" content={image} />
      <meta name="description" content={metaDescription} />

      {/* OpenGraph tags */}
      <meta property="og:title" content={metaTitle} />
      <meta property="og:type" content={post ? `article` : `website`} />
      <meta property="og:url" content={metaUrl} />
      <meta property="og:image" content={image} />
      <meta property="og:description" content={metaDescription} />

      {/* Twitter Card tags */}
      <meta name="twitter:card" content="summary" />
      <meta name="twitter:creator" content="{site.siteMetadata.author}" />
      <meta name="twitter:title" content={metaTitle} />
      <meta name="twitter:image" content={image} />
      <meta name="twitter:description" content={metaDescription} />

      {children}
    </Helmet>
  )
}

SEO.defaultProps = {
  lang: `en`,
  meta: [],
  description: ``,
}

SEO.propTypes = {
  description: PropTypes.string,
  lang: PropTypes.string,
  title: PropTypes.string,
}

export default SEO

And a blog page teamplate that uses the SEO component like so:

# blogs.js

import React from 'react'
import { graphql, Link } from 'gatsby'
import { Container, Row, Col, useScreenClass, Visible } from 'react-grid-system'

import SEO from '../components/seo'
import Layout from '../components/layout'
import Main from '../components/main'
import BlogList from '../components/insights/blogList'
import Pagination from '../components/pagination'

const Blog = (props) => {
  const {
    seoTitle,
    seoDescription,
    seoHelmet,
  } = props.data.contentfulPage
  const posts = props.data.allContentfulInsightsPage.edges
  const { currentPage } = props.pageContext
  const screenClass = useScreenClass()

  return (
    <Layout>
      <SEO
        title={`${seoTitle} ${currentPage > 1 ?  `- Page ${currentPage}` : `` }`}
        description={seoDescription?.seoDescription ? seoDescription.seoDescription : false}
      >
        {seoHelmet ? seoHelmet.seoHelmet : ''}
      </SEO>
      <Main>
        <h1 className={`headline`}>Blog</h1>
        <BlogList posts={posts} />
        <Pagination context={props.pageContext} />
      </Main>
    </Layout>
  )
}

export const query = graphql`
  query($skip: Int!, $limit: Int!) {
    contentfulPage(slug: {eq: "blog"}) {
      id
      slug
      seoTitle
      seoDescription {
        seoDescription
      }
      seoHelmet {
        seoHelmet
      }
    }
    allContentfulBlogs(
      sort: { fields: [date], order: DESC }
      limit: $limit
      skip: $skip
    ) {
      edges {
        node {
          id
          title
          slug
          date
          preview
          text {
            json
          }
          image {
            localFile {
              ...blogThumbnail
            }
          }
          category {
            name
            slug
          }
        }
      }
    }
  }
`

export default Blog

Expected result

Meta tags should be generated properly on static site and should be accessible by Facebook share scraper.

Actual result

Facebook share debugging tool shows no such result.

The error on FB Sharing Debugger:

⚠️ Warnings That Should Be Fixed

Inferred Property

The ‘og:image’ property should be explicitly provided, even if a value can be inferred from other tags.

Missing Properties

The following required properties are missing: og:url, og:type, og:title, og:image, og:description, fb:app_id

And here is the scraped page:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style data-href="/styles.13d4056a8a600210f038.css">a,abbr, ... </style>
<meta name="generator" content="Gatsby 2.19.49">
<title data-react-helmet="true"></title>
<link as="font" href=" ... " rel="preload" crossorigin="anonymous">
<style id="jss-server-side"></style>
<style data-styled="" data-styled-version="4.4.1"></style>
<script>window.dataLayer = window.dataLayer || []; ... </script>
<link rel="sitemap" type="application/xml" href="/sitemap.xml">
<link rel="canonical" href=" ... " data-baseprotocol="https:" data-basehost=" ... ">
<link rel="icon" href="/icons/icon-48x48.png?v=4b382095dbd38c63f79bce6052737f30">
<link rel="manifest" href="/manifest.webmanifest">
<meta name="theme-color" content="#3FB6E8">
<link rel="apple-touch-icon" sizes="48x48" href="/icons/icon-48x48.png?v=4b382095dbd38c63f79bce6052737f30">
<link rel="apple-touch-icon" sizes="72x72" href="/icons/icon-72x72.png?v=4b382095dbd38c63f79bce6052737f30">
<link rel="apple-touch-icon" sizes="96x96" href="/icons/icon-96x96.png?v=4b382095dbd38c63f79bce6052737f30">
<link rel="apple-touch-icon" sizes="144x144" href="/icons/icon-144x144.png?v=4b382095dbd38c63f79bce6052737f30">
<link rel="apple-touch-icon" sizes="192x192" href="/icons/icon-192x192.png?v=4b382095dbd38c63f79bce6052737f30">
<link rel="apple-touch-icon" sizes="256x256" href="/icons/icon-256x256.png?v=4b382095dbd38c63f79bce6052737f30">
<link rel="apple-touch-icon" sizes="384x384" href="/icons/icon-384x384.png?v=4b382095dbd38c63f79bce6052737f30">
<link rel="apple-touch-icon" sizes="512x512" href="/icons/icon-512x512.png?v=4b382095dbd38c63f79bce6052737f30">
<link as="script" rel="preload" href="/component---src-templates-insight-js-0b3261c291dd76b6e32d.js">
<link as="script" rel="preload" href="/commons-0606cae2f0bba83915df.js">
<link as="script" rel="preload" href="/app-595ec14f594e84b72fc9.js">
<link as="script" rel="preload" href="/styles-9336dff5557f552f77fc.js">
<link as="script" rel="preload" href="/webpack-runtime-5af2f2a5f9a736a820a9.js">
<link as="fetch" rel="preload" href="/page-data/insights/key-strategies-for-building-websites-that-capture-and-convert/page-data.json" crossorigin="anonymous">
<link as="fetch" rel="preload" href="/page-data/app-data.json" crossorigin="anonymous">
</head>
<body>
<noscript><iframe src="https://www.googletagmanager.com/ns.html? ... " height="0" width="0" style="display: none; visibility: hidden"></iframe></noscript>
<div id="___gatsby">
<div style="outline:none" tabindex="-1" id="gatsby-focus-wrapper"></div>
<div id="gatsby-announcer" style="position:absolute;top:0;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0" aria-live="assertive" aria-atomic="true"></div>
</div>
<script id="gatsby-script-loader">/*<![CDATA[*/ ... /*]]>*/</script>
<script id="gatsby-chunk-mapping">/*<![CDATA[*/ ... /*]]>*/</script>
<script src="/webpack-runtime-5af2f2a5f9a736a820a9.js" async=""></script>
<script src="/styles-9336dff5557f552f77fc.js" async=""></script>
<script src="/app-595ec14f594e84b72fc9.js" async=""></script>
<script src="/commons-0606cae2f0bba83915df.js" async=""></script>
<script src="/component---src-templates-insight-js-0b3261c291dd76b6e32d.js" async=""></script>
</body>
</html>

Here are some other fixes I tried…

Environment

Run gatsby info --clipboard in your project directory and paste the output here.

System:
    OS: Linux 4.4 Ubuntu 18.04.4 LTS (Bionic Beaver)      
    CPU: (8) x64 Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz 
    Shell: 5.4.2 - /usr/bin/zsh
  Binaries:
    Node: 10.16.3 - /usr/local/bin/node
    Yarn: 1.21.1 - /usr/bin/yarn
    npm: 6.14.2 - /usr/local/bin/npm
  Languages:
    Python: 2.7.17 - /usr/bin/python
  npmPackages:
    gatsby: ^2.19.25 => 2.20.8
    gatsby-background-image: ^0.9.12 => 0.9.19
    gatsby-cli: ^2.11.3 => 2.11.3
    gatsby-image: ^2.2.34 => 2.3.1
    gatsby-plugin-canonical-urls: ^2.1.20 => 2.2.1        
    gatsby-plugin-google-tagmanager: ^2.1.24 => 2.2.1     
    gatsby-plugin-manifest: ^2.2.31 => 2.3.3
    gatsby-plugin-material-ui: ^2.1.6 => 2.1.6
    gatsby-plugin-offline: ^3.1.1 => 3.1.2
    gatsby-plugin-preload-fonts: ^1.0.34 => 1.1.1
    gatsby-plugin-react-helmet: ^3.2.1 => 3.2.1
    gatsby-plugin-robots-txt: ^1.5.0 => 1.5.0
    gatsby-plugin-sass: ^2.1.26 => 2.2.1
    gatsby-plugin-sharp: ^2.4.0 => 2.5.3
    gatsby-plugin-sitemap: ^2.2.26 => 2.3.1
    gatsby-plugin-smoothscroll: ^1.0.4 => 1.1.0
    gatsby-plugin-styled-components: ^3.1.16 => 3.2.1     
    gatsby-plugin-transition-link: ^1.17.7 => 1.18.0 
    gatsby-plugin-typography: ^2.3.20 => 2.4.1
    gatsby-source-contentful: ^2.1.73 => 2.2.5
    gatsby-source-filesystem: ^2.1.40 => 2.2.2
    gatsby-transformer-sharp: ^2.3.7 => 2.4.2
  npmGlobalPackages:
    gatsby-cli: 2.8.19

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:29 (14 by maintainers)

github_iconTop GitHub Comments

12reactions
jmadelainecommented, May 12, 2020

I have discovered that wrapping the Seo component with context providers inside wrapRootElement (exported from gatsby-ssr.js) causes this issue for me.

My current setup is something like this:

// gatsby-ssr.js

export const wrapRootElement = ({ element }) => (
  <ThemeProvider>
    {element}
  </ThemeProvider>
)
// some-page.jsx

const SomePage = () => (
  <Layout>
    <Seo
      title="some title"
      description="some description"
    />
   // other components here...
  </Layout>
)

Building the above app results in the index.html missing all the meta tags that are defined inside the Seo component.


If I render the Seo component inside wrapRootElement but still as a child of the provider, I get the same result.

Still doesn’t work:

// gatsby-ssr.js

export const wrapRootElement = ({ element }) => (
  <ThemeProvider>
    <Seo title="some title" description="some description">
      {element}
    </Seo>
  </ThemeProvider>
)

However, if I render the Seo component outside the providers, then my index.html is built with all the meta tags defined in Seo.

This works:

// gatsby-ssr.js

export const wrapRootElement = ({ element }) => (
  <Seo title="some title" description="some description">
    <ThemeProvider>
      {element}
    </ThemeProvider>
  </Seo>
)

The problem is, I want different meta tags based on the current page.

Does anyone know how to solve this?

UPDATE:

I discovered that my ThemeProvider was skipping first render (in order to load dark vs light theme based on a localStorage value and prevent showing the incorrect color theme), and therefore the Seo component was not being rendered on the server.

5reactions
jitendra-koodocommented, May 24, 2020

I’m also facing the same issue… Metatags come after inline CSS in generated HTML. If CSS is too big, metatags are not parsed by Whatsapp (assuming they read first few KB)… How can I make sure that metatags are always printed on top with Helmet and css comes below that? Thanks?

og_problem

Read more comments on GitHub >

github_iconTop Results From Across the Web

Facebook Share not picking up OpenGraph ... - Stack Overflow
js using React Helmet that is called inside a blog template blog.js . However Facebook Share does not recognize the opengraph tags. The...
Read more >
Gatsby open graph meta tags are not recognized - Marco Melilli
What to do when facebook or twitter don't find OpenGraph meta tags generated by gatsby-plugin-react-helmet.
Read more >
GatsbyJS SEO and Open Graph with Helmet - FAESEL.COM
The Open Graph protocol enables any web page to become a rich object in a social graph. For instance, this is used on...
Read more >
Meta tags: All you need to know for your Gatsby blog
When you share your Gatsby blog to the world, you'll want to make sure you give a good first impression. With react-helmet and...
Read more >
Learn Add SEO Meta with React Helmet - Frontend Masters
Jason walks through installing React Helmet, adding plugins to the gatsby config file, pulling out default site meta data, exporting a prop called...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found