Facebook Share not picking up OpenGraph meta tags from Gatsby site via React Helmet.
See original GitHub issueDescription
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…
- checked for .htaccess issues
- checked if caching issue
- using
gatsby-plugin-react-helmet
by default - tried disabling other plugins such as
material-ui
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:
- Created 3 years ago
- Comments:29 (14 by maintainers)
I have discovered that wrapping the
Seo
component with context providers insidewrapRootElement
(exported fromgatsby-ssr.js
) causes this issue for me.My current setup is something like this:
Building the above app results in the
index.html
missing all the meta tags that are defined inside theSeo
component.If I render the
Seo
component insidewrapRootElement
but still as a child of the provider, I get the same result.Still doesn’t work:
However, if I render the
Seo
component outside the providers, then myindex.html
is built with all the meta tags defined inSeo
.This works:
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 theSeo
component was not being rendered on the server.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?