menu
announcement

Spectrum is now read-only. Learn more about the decision in our official announcement.

Gatsby

Fast in every way that matters. Gatsby is a free and open source framework based on React that helps developers build blazing fast websites and apps.

Channels
Team

Open Graph Tags Issue

March 16, 2020 at 6:56pm

Open Graph Tags Issue

March 16, 2020 at 6:56pm
I have been trying to set the appropriate meta tags in order for the Facebook crawler (and other social media sites) to properly display the correct preview based on the link. Issue here being that the link path works totally fine but the preview doesn't display the way it needs to. I'm hoping to get it to have the typical Facebook preview (image, title, little description) but as of now I just get the site title and that's about it.
I've read on multiple forums and discussions that these tags need to be generated on the server side. As such, I also tried to play around with the gatsby-ssr.js file to no avail. We are also implementing React Helmet to dynamically add certain tags but again these don't work when it comes to the relevant open graph tags needed. Been spending quite some time on this but if any one has any pointers/ideas I'd appreciate it. Any and all help welcomed!

March 16, 2020 at 7:09pm
May also be worth noting that we're using a WordPress CMS and am hoping to have the OG tags contain the correct info associated with each Post/Page (og:image should be the cover image for that post/page, og:title should be the title, etc.)
gatsby-plugin-react-helmet takes care of the SSR for you, when using react-helmet. You do need to use the meta property with react-helmet, though; it won't render the children property during SSR.
Edited
So long as you do that, you can get it the needed data during build time, and you don't have any runtime conditions that may force the react-helmet component not to render during SSR, then you should be good. If not, then a simplified reproduction might help to pinpoint the issue.
So we are using gatsby-plugin-react-helmet as well, however, we are using a combination of both fetch requests directly to our WP API and the typical GraphQL queries traditionally used with Gatsby. There is a condition on our page/post template that only allows the page to render after the fetch request to get all relevant data is successful (which happens in componentDidMount).
Could this be one of the runtime conditions that would affect React-Helmet's functionality like you mentioned? Or would this not have an impact on the SSR
Edited
What I like to do, to make sure I'm getting the necessary data rendered in my static HTML, is grep it:
cat public/index.html |tidy -mqi --vertical-space no --show-warnings no --wrap 0 |grep -E 'meta'
Something like that. Most of those crawlers aren't running javascript, so they expect the <meta> tags to be in the HTML. You could also do a curl request against your running site, or turn off javascript for that domain, and see if the tags appear in the inspector.
It does sound like your setup won't render the meta tags. Is it possible for you to pre-fetch the data from Wordpress during the build? You could create the pages using createPage in gatsby-node, and pass the requisite data via context. If you don't want to use SSR to render static HTML, then perhaps you could only pull the information needed for the <meta> tags, and let the rest of the page render dynamically, during runtime.
Hmm haven't tried your gatsby-node method yet but I did try to do something similar with gatsby-ssr whereby the idea was to grab the necessary page info and populate the meta tags through there. This actually accomplished the task of being able to place explicit meta tags (dummy data currently) in the HTML header but issue here was I wasn't able to pull the relevant page/post data in this step (my guess is probably cuz the data hasn't even been pulled yet tho I could be wrong about this).
Regardless, I'll give a similar method a shot in the gatsby-node file as well. Maybe the pages will have more of their data loaded in this step (still getting accustomed to Gatsby lifecycle if you couldn't tell).
Edited
gatsby-ssr actually runs after the entire bootstrap process, and during bootstrap is generally where data is fetched for the build, since that is where the gatsby-node endpoints are run. This article might help some.
There is wrapRootElement and wrapPageElement in gatsby-ssr and gatsby-browser that will receive the props that are provided to each page.. but that really shouldn't be needed for this particular use case.
Here's a couple of ways you could get the data to your Helmet component:
  • you could query the needed data in createPages in gatsby-node, then give it to the pages using the context in createPage() (see also). In each page, the pageContext prop will contain the values you define in context using createPage().
  • In sourceNodes in gatsby-node, you could query all of your SEO information, and define some GraphQL nodes with it. Then, in each page, you could query those nodes, which will make it available in the data prop. If using a template for rendering the pages, and you want to filter the page query to whatever is relevant to that page, then you could define specific information in the context that will allow the page to run a GraphQL query using the context as a variable (reference)
Edited
The only problem I see with this potential fix is that even if I'm able to successfully implement the call from gatsby-node and get all the data we would still need to keep the conditional rendering in our template files. We're trying to keep the application loading times somewhat dynamic since there is a lot of content on the WP instance and our client didn't really like the long build time that can be associated with content heavy Gatsby applications.
So assuming that we don't want to preload all page/post data in the build process and still want to keep things semi-dynamic, would you still recommend your suggested solution?
You should be able to make it work as hybrid pages (part static/part dynamic). The Helmet component is the only thing that is required to be statically rendered in your use case. So, you just need to make sure that it renders unconditionally, which you could do with a HOC. Then the rest of the page content can render on mount.
I might do something like this for the template, for example:
class Template extends React.Component {
/* template content, including componentDidMount() */
}
export default (props) => {
return (
<React.Fragment>
<Helmet/>
<Template {...props} />
</React.Fragment>
)
}
That particular usage kind of defeats the purpose of Gatsby, though; at least partially. Statically rendered pages will be much faster than dynamically loaded, the content is not 100% dependent on javascript, and you can also limit the attack vectors on your WP server significantly by using IP security since all data is pre-loaded... but, really, how you use choose to use it is entirely up to you (and your client, of course). Gatsby is an excellent build tool either way. I've used it for dynamic projects, too.
Edited
Now that I'm thinking about it, it might actually be worth it to just use wrapPageElement() in gatsby-ssr as your HOC, since it should always be statically rendered for each page, and it will always receive each page's props, too. So, something like this:
// gatsby-ssr.js
exports.wrapPageElement = (props) => {
return (
<React.Fragment>
<Helmet meta={props.pageContext.meta} />
{props.element}
</React.Fragment>
)
}
Yeah definitely a fan of Gatsby I enjoyed working with/learning it throughout the project and hope to continue doing so. If it were up to me I would've left the build as it was, but unfortunately it ain't! But thanks for the quick responses, I'll work on implementing something similar to what you suggested. Much love 🙏🙏
Edited
like-fill
1