DEV Community

Mihai Bojin
Mihai Bojin

Posted on • Originally published at mihaibojin.com on

Configuring social sharing cards in GatsbyJS

Photo: Social media apps
"Photo by Nathan Dumlao on Unsplash"

🔔 This article was originally posted on my site, MihaiBojin.com. 🔔


When a user shares a web link, most applications parse a standard set of meta tags and use the provided information to render a 'card', including an image, a title, and a summary.

A few competing standards exist; the most relevant are Twitter Cards and Facebook's Open Graph Protocol.

When the necessary meta tags are missing, applications such as Twitter, Facebook, Whatsapp, Signal, Telegram, etc., will be unable to render the card. In such cases, they will either display the link as-is or try to infer some parts of the card metadata; in the latter case, your mileage may vary.


Here's an example of a site without social sharing cards metadata:

Screenshot of a shared link to a page without social card metadata

And here's how my site's homepage is rendered:

Screenshot of a rendered Twitter card

Since I wanted my site to display correctly in as many apps as possible, I provided both Open Graph and Twitter Card tags!


I use Gatsby for my site, and unfortunately, it does not have native support for social cards. Also, when I implemented this feature, I was pretty new to GatsbyJS and had to figure out how to load files and process images through GraphQL (childImageSharp, gatsbyImageData, GatsbyImage, StaticImage).

It was rough, to say the least (unclear documentation, competing advice for Gatsby v2 and v3, and my general lack of knowledge).

Fortunately, I prevailed! Here's how:

Load any image via GraphQL

  const { myImage } = useStaticQuery(graphql`
    query {
      myImage: file(relativePath: { eq: "name-of-file.jpg" }) {
        childImageSharp {
          gatsbyImageData(layout: CONSTRAINED)
        }
      }
    }
  `);
Enter fullscreen mode Exit fullscreen mode

This works with images placed under src/images/.

Get a link to a processed image

import { getImage, getSrc } from 'gatsby-plugin-image';

// ...

const img = getImage(image);
const imgSrc = SITE_URL + getSrc(img);
Enter fullscreen mode Exit fullscreen mode

Create an SEO component

Ok, I'll admit, Gatsby does have good SEO support, including some general advice on social cards.

This formed the basis of my configuration, although I had to heavily customize it!

I configured the SEO component to accept a number of inputs:

function SEO({ title, description, lastUpdated, tags, image, imageAlt, absoluteURL }) {
  const img = getImage(image);
  const imgSrc = SITE_URL + getSrc(img);

  let meta = [];

  //...
  return (
    <Helmet
      htmlAttributes={{prefix: 'og: http://ogp.me/ns#'}}
      title={title}
      meta={meta}
      //...
    />
  );
}

Seo.propTypes = {
  title: PropTypes.string.isRequired,
  description: PropTypes.string.isRequired,
  lastUpdated: PropTypes.string.isRequired,
  tags: PropTypes.arrayOf(PropTypes.string),
  image: PropTypes.object.isRequired,
  imageAlt: PropTypes.string.isRequired,
  absoluteURL: PropTypes.string.isRequired,
};
export default SEO

Enter fullscreen mode Exit fullscreen mode

And generated the required meta tags:

Generate Twitter Card meta tags

meta.push({
  name: "twitter:card",
  content: "summary_large_image",
});
meta.push({
  name: `twitter:title`,
  content: title,
});
meta.push({
  name: `twitter:description`,
  content: pageDescription,
});
meta.push({
  property: `twitter:image`,
  content: imgSrc,
});
meta.push({
  name: `twitter:image:alt`,
  content: imageAlt,
});
Enter fullscreen mode Exit fullscreen mode

Generate Open Graph meta tags


meta.push({
  property: `og:type`,
  content: `website`,
});
meta.push({
  property: `og:url`,
  content: absoluteURL,
});
meta.push({
  property: `og:title`,
  content: title,
});
meta.push({
  property: `og:description`,
  content: pageDescription,
});
meta.push({
  property: `og:image`,
  content: imgSrc,
});
meta.push({
  name: `og:image:alt`,
  content: imageAlt,
});
meta.push({
  property: `og:updated_time`,
  content: lastUpdated,
});
meta.push({
  property: "og:image:width",
  content: parseInt(img.width),
});
meta.push({
  property: "og:image:height",
  content: parseInt(img.height),
});
Enter fullscreen mode Exit fullscreen mode

Bringing it all together

And that was that! All that was left was for me to send all the required variables via my page layouts, e.g.

<Seo title="My article" description="Short summary of my article" etc="...">
Enter fullscreen mode Exit fullscreen mode

But is it working?

Testing social sharing card rendering

To test your feature, use the following tools:

Bonus: social sharing buttons

No site would be complete without a feature to allow users to share content on social media easily!

I found an excellent tutorial for integrating social sharing buttons.


It goes a little bit like this:

Create a component and import media from react-share

import {
  TwitterShareButton,
  TwitterIcon,
} from 'react-share';

const ShareButtons = ({
  title,
  url,
  tags,
  twitterHandle,
}) => {

  // remove any non-alphanumeric characters
  const hashtags = tags.map((t) => t.replace(/[^a-zA-Z0-9]+/g, ''));

  return (
    <>
      <TwitterShareButton
        title={title}
        url={url}
        via={twitterHandle}
        hashtags={hashtags}
      >
        <TwitterIcon size={40} round={true} />
      </TwitterShareButton>
    </>
  );
};
Enter fullscreen mode Exit fullscreen mode

(Of course, the above is greatly simplified and only displays Twitter. For my site, I defined more.)

Include the component on your pages

<ShareButtons
  url={SITE_URL + location.pathname}
  title={...}
  description={...}
  tags={[...]}
/>
Enter fullscreen mode Exit fullscreen mode

And here is the result:

Screenshot of social sharing buttons

Conclusion

I hope you found this short tutorial helpful! As I'm writing it now, it feels pretty straightforward, but at the time, I struggled for hours trying to piece together confusing or incomplete information from various articles and blogs.

Hopefully, this can help you avoid my experience and integrate your social sharing features much faster!

In an ideal world, Gatsby would have come with better, out-of-the-box, social sharing features!

Maybe one day...


If you liked this article and want to read more like it, please subscribe to my newsletter; I send one out every few weeks!

Discussion (0)