Decorative Bubbles
dark themed logoByteSizedPieces

Understanding Open Graph Dynamic Image Meta Tags with NextJS

Updated on Mar 22, 2023

Metadata and meta tags are underestimated SEO optimization tools. Newer web developers may completely gloss over this powerful technique to improve the discoverability of the websites for which they are responsible. One might discover the lacking of meta tags in a website via tools like checkbot.io, or one might realize when they share a link to their website, an image doesn’t show up with the link on Twitter or Facebook like other websites! Why is that?

Vercel OG Image Generation
Vercel OG Image Generation

In this article, we will focus on a few critical concepts before diving into NextJS new open graph dynamic image updates. In order to truly grasp the incredible benefits of this released feature, we need to have a solid understanding of the following:

  1. Metadata meaning and meta tags
  2. Open graph protocol
  3. Shortcomings with the standard method of adding image meta tags
  4. Open graph dynamic images with NextJS

Metadata meaning and meta tags

To first understand why we care about the recent NextJS release, we need to have a background for the notion of metadata, what it means, and how meta tags fall under the metadata scope.

What is Metadata?
What is Metadata?

What is Metadata?

Generally speaking, metadata is defined as data that describes data. A more helpful way to understand metadata is by examining its application in specific areas. In this case, let’s understand metadata when applied to web development.

In web development, metadata consists of unseen HTML elements that serve the purpose of communicating and clarifying relevant website information for search engines like Google, ultimately making it a critical role in effective Search Engine Optimization.

Metadata still feels a bit abstract, and this is where meta tags come in to clear up the picture and give it a bit more structure.

What is a Meta Tag?
What is a Meta Tag?

Meta tags help us accomplish the goal of communicating and clarifying the relevant website information for our search engines. Meta tags are the actual snippets of text that describe a page’s content. They don’t appear on the page itself, but they are present in the page’s source code for crawlers to parse.

How do we create a meta tag on a website? Let’s examine an example of the usage of meta tags in ByteSizedPieces!

<Head>
<title>ByteSizedPieces blog posts about ReactJS web development</title>
<meta name="description" content="A web development blog focused on interview preparation, javascript, css, react, accessibility, web development tools, mobile development, and the tech industry." />
</Head>

In the above example, we have a few details to make note of.

  1. The <head> element we have utilized serves as a container for our metadata and is placed between the <html> tag and the <body> tag. As such, any metadata should be positioned as children of the head element!

  2. The meta element is our meta tag! Note how we have some attributes, names, and content which tell the search engine crawlers that the meta tag is specifically intending to provide a description of our website, as well as the supplemental content which is the actual description.

Meta tags can have several names and provide a range of information. We can see a full list of the meta tags to a site via inspection of developer tools.

Looking at Medium, we can see many meta tags set within the head element! This explains why Medium does so well in the SEO space!

Medium Meta Tags
Medium Meta Tags

Open Graph Protocol

The open graph protocol is another metadata extension that gives websites a unique stance in the social graph. More specifically, whenever you share a URL on social media, Open Graph meta tags (OGP tags for short), inform what supplemental information comes with that URL. It could be the title, description, or in many cases an image.

On Twitter, a supplemental image influences engagement statistics by leaps and bounds. Retweets increased by 150%, clicks increased by 20%, and favorites increased by 90%.

Engagement increases with images!
Engagement increases with images!

The numbers do not lie, and images as metadata are important!

How do we typically communicate the image with the URL? Well, open graph is intended to be generalized across social media platforms. However, one needs to stay attentive to potential unique handling. Twitter Cards, for instance, look similar to Open Graph tags, but still deviate from the rulesets of OGP!

To avoid complications, we focus our attention on the general OGP conventions. To turn your own web page into a graph object, you would define a meta tag that follows the rulesets defined by the social media platform. For Facebook, the meta tag for an image would look like the following.

<meta property="og:image" content="" />

In conjunction with the importance of image metadata with shared URLs on social media, we should note the impact an aesthetic image makes versus one with low quality or visual relevance to the text.

This leads me to my final review topic prior to exploring NextJS OG Dynamic Image release.

Shortcomings with the standard method of adding image meta tags

We have established that images drive better conversion rates and the quality of images matters. The unfortunate fact is, with large blogs or e-commerce sites, a lot of effort goes into asset creation. The standard method of adding image meta tags requires individually creating images per page. This has proven to be inefficient and a waste of developer and designer time. If only things could be standardized!

Massive Waste of Time Sign
Massive Waste of Time Sign

In comes Vercel with their new amazing release for NextJS. Now we can see the beauty behind OG Dynamic Images.

Open graph dynamic images with NextJS

First we answer the following question.

What are Open Graph Dynamic Images?

Open graph or OG dynamic images enable social images to be generated on the fly per developer specification. These images can be configured to include dynamic properties, unlocking asset customization as well. Finally, the image generation runs on the vercel edge, to deliver rapid results based on user local, and is combined with caching for faster results.

Now that we understand what OG dynamic images are, let’s go over how we can create a new API for OGImage and leverage it in our website.

Before we begin, a gentle reminder that this feature is only available to projects that have been brought to version 13 of NextJS, and is still experimental.

Steps to leverage OG Dynamic Images

  1. Install @vercel/og npm package
  2. Create a new API for OGImage
  3. Use new API

Install vercel/og npm package

npm i --save @vercel/og

replace npm with yarn or pnpm as needed.

Create a new API for OG Image

First let’s decide what we are going to create.

Our asset is intended for to blog articles. When we share a link on social media to our blog post, ideally we would like to see an image with a background color, our blogs name, the title of the article and the category! OG Dynamic Images will come in handy here, as we will be able to set the dynamic properties for our images, and never have to look back!

Under pages/api/* we will want to create a new file og.js

Here we will import the ImageResponse object from @vercel/og . This object is responsible for processing our provided HTML and CSS, and convert that into an appropriate image which the endpoint will serve.

Recall the mention that this process is experimental, therefore we need to enable the experimental edge temporarily via:

export const config = {
runtime: 'experimental-edge',
};

Finally, let’s create a handler that takes in a request object, this process should be familiar to any NextJS endpoint.

Now our pages/api/og.js file should look like the following:

// pages/api/og.js
import { ImageResponse } from '@vercel/og';
// enable experimental edge
export const config = {
runtime: 'experimental-edge',
};
export default function handler(req: NextRequest) {}

Now we want to define some HTML and CSS and pass it to our imported ImageResponse object. For sake of simplicity, we will statically set filler text for the intended dynamic article title and category.

Below is the following rendering:

Image Generated at the Vercel Edge with Static Fields
Image Generated at the Vercel Edge with Static Fields

And below is how we did it via HTML and CSS passed to ImageResponse.

// pages/api/og.js
import { ImageResponse } from '@vercel/og';
// enable experimental edge
export const config = {
runtime: 'experimental-edge',
};
export default function handler(req: NextRequest) {
return new ImageResponse(
<div
style={{
backgroundColor: "#6800A3",
backgroundSize: "100%",
height: "100%",
width: "100%",
color: "#F9F9F9",
display: 'flex'
}}
>
<div
style={{
padding: "20px",
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
width: '100%'
}}
>
<h1
style={{
fontWeight: 900
}}
>
ByteSizedPieces
</h1>
<h2>Article title should go here</h2>
<div style={{
'width': '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
textAlign: 'center'
}}>
<p style={{
textAlign: 'center',
backgroundColor: '#A341DB',
borderRadius: '50px',
padding: '5px 10px'
}}>Category here</p>
</div>
</div>
</div>
);
}

If you want to play with this example, vercel offers an OG Image Playground. I have created a shareable playground here.

Now we get to the fun part, which are the dynamic traits to the generated image!

Our handler always receives a Request object as an argument. From the req we will obtain the url and retrieve provided searchParams .

searchParams are query params set when we use our endpoint via a meta tag. The query params can be dynamic or static depending on the developer. If this isn’t making too much sense, hang tight, when we use the endpoint we are creating it will click!

Let’s expect for now from our query params, a title and category field. We will set fallbacks should something unexpected happen and they are not set correctly.

Then we will just use those fields in our HTML and CSS passed to ImageResponse!

// pages/api/og.js
import { ImageResponse } from '@vercel/og';
// enable experimental edge
export const config = {
runtime: 'experimental-edge',
};
export default function handler(req: NextRequest) {
// get searchParams
const { searchParams } = new URL(req.url); const { title = 'New Article', category = '' } = searchParams;
return new ImageResponse(
<div
style={{
backgroundColor: "#6800A3",
backgroundSize: "100%",
height: "100%",
width: "100%",
color: "#F9F9F9"
}}
>
<div
style={{
padding: "20px"
}}
>
<h1
style={{
fontWeight: 900
}}
>
ByteSizedPieces
</h1>
<h2>{title}</h2>
<div style={{
'width': '100%',
display: 'flex',
justifyContent: 'center'
}}>
<p style={{
width: '150px',
backgroundColor: '#A341DB',
borderRadius: '50px'
}}>{category}</p>
</div>
</div>
</div>
);
}

Note that we adjusted the image to leverage the title and category variables now!

We have completed the first big part for OG Dynamic Images. The endpoint is set to expect two dynamic fields, a title and category, and will consume the provided HTML and CSS and return an image rendered with those fields.

You can test if the endpoint is working by visiting your running local instance of the app at https://localhost:3000/api/og?title=test&category=react

Note that in the test I have supplied the query params title and category. We observe an element that when inspected in the Developer Tools, reveals an img element. Neat!

Now the final detail comes to bring this full circle.

Use new API

Define a meta tag in the head for the page you would like the asset to display. For me that would be within pages/posts/[slug.js]

<Head>
<meta property="og:image"
content=\`https://bytesizedpieces.com/api/og?title=${getPostShortTitle(frontMatter) || ''}&category=${getPostCategory(frontMatter)}\`
/>
</Head>

A few details to note here that are very important for this to work.

You must specify the following attributes:

  • property as og:image
  • content with value set to the deployed instance for your app

Finally, check out how I provided the query params title and category to the value for the content attribute!

frontmatter is a representation of parsed YAML metadata each of my articles begin with. Thus I will achieve at each bytesizedpieces.com/posts/* route a dynamically generated asset at the edge, with built in caching!

Amazing!

Vercel is a no brainer. The improvements to NextJS are ever enticing. If you are interested in joining Vercel, try it out!

Custom Fonts in OG Dynamic Image

One final mention, note that the supplied image contains the Poppins typeface. If you would like to utilize a custom font, NextJS have accommodated this use case.

By making use of fetch you can supply a URL instance with the path to your custom fonts, and await the result in the handler. Refer to the following documentation to see how this is accomplished.

Testing

Test open graph images on Facebook, LinkedIn and Twitter separately, or take advantage of an open graph debugger.

  1. Facebook open graph Debugger.
  2. Twitter open graph Debugger.
  3. Linkedin open graph Debugger.
  4. All social media, open graph Debugger
  5. OG Dynamic Image Playground

Documentation to learn more


Remember, developers are creatures that turn coffee into code. So I'd very much appreciate if you bought me a coffee! buy me a coffee icon I will be posting very frequently on my findings and learnings in the tech industry and beyond. Join my newsletter if you would like to stay tuned!

Thanks for reading again! ❤️

Top Articles
Pros and Cons of Caching Data in Software1
How to build a Modal in ReactJS (Part One)2
Email automation with Firebase Mail Extension and SendGrid3
0

Join our newsletter to read delightful bytesizedpieces every Monday!

This newsletter will keep you up to date with bytesizedpieces releases. Get the inside scoop on web development, interview preparation, career development, SEO, and best tools!