If you’ve spent any time building single page applications (SPAs) with React, chances are you’ve heard of the react-helmet library. React helmet streamlines much of the work involved in maintaining the document head of your React page components.
But why do we need react-helmet to modify our <head> tag, can’t we just do it ourselves? Well, yes. But there’s more to the story than that.
Here’s what we’ll be taking a closer look at in this article:
- What is React Helmet?
- Document head tags in React SPAs
- Why react-helmet is a useful addition to a react application.
- Why we recommend react-helmet-async over react-helmet for your react project.
- And finally some best practices when it comes to optimizing your <head> tag for excellent React SEO.

Free Weekly SEO Newsletter
Hey! I’m Scott, I’ve been an SEO consultant for nearly 10 years. Get on my weekly newsletter to get..
- Weekly SEO updates, keep up with the latest and greatest.
- How we grow websites from zero to millions of visitors
- A bunch of SEO tips and Tricks you won’t find anywhere else test
The Head Tag in React SPAs
To understand why react-helmet exists, it’s important to understand the structure of an SPA for SEO. As the name implies, an SPA consists of a single HTML page. All subsequent pages aside from the landing page are loaded programmatically via client-side Javascript.
Each programmatically loaded page is actually just content loaded into the body inside the same HTML shell.
Each page is a React component, which is just some code that generates HTML. These components mainly just modify content in the body tag, and don’t have direct access to the <head> tag in the HTML shell.
Long story short; you can’t modify the <head> directly within a React page component. That’s why developers use react helmet.
How to modify the head in a React SPA?
What this means is that without a clever coding strategy, the <head> tag will remain unchanged as users navigate the site. When the user clicks a navigation link and React loads a new page component, we need some code to modify the HTML shell’s <head> tag to reflect the new page’s meta data.
Rather than building this coding strategy from scratch, we can use the react-helmet library to streamline the process of modifying the <head> tag.
What is react-helmet used for?
The goal of this article is to expand upon many of the common definitions of react helmet, and we have set the stage to do just that.
React helmet programmatically modifies the contents of <head> in the HTML shell of your React SPA.
There are some other cool use-cases for react helmet, but at its core, it is simply code that modifies the DOM. It accepts a bunch of metadata as parameters, creates the required HTML elements, and plugs them into the <head> tag.
Take a look at this bit of code straight from the react-helmet source code:
const elementTag = document.getElementsByTagName(tagName)[0];
// A bunch of other redundancy code and then...
if (elementTag.getAttribute(attribute) !== value) {
elementTag.setAttribute(attribute, value);
}
To be clear, there is a lot more work going on behind the scenes of this library. But this code snippet represents the main function of react-helmet: Set the attribute of a given DOM element within the <head> tag of our SPAs HTML shell.
That’s the true purpose of react-helmet.
As stated in the docs: “Helmet takes plain HTML tags and outputs plain HTML tags. It’s dead simple, and React beginner friendly.”
React Helmet Example
Let’s take a look at a basic example of using react-helmet:
<Helmet>
<title>How to Use React Helmet</title>
<link rel="canonical" href="http://mysite.com/example" />
<meta name="description" content="The best and most comprehensive guide to using and understanding the react-helmet library." />
</Helmet>
The concept here is simple. Everything inside the <Helmet> tag will be parsed by react-helmet and converted into actual HTML to be placed in the <head> tag.
React Helmet on Server Side Rendering
Many React SPAs utilize isomorphic react, which is just a fancy way to say that React code is rendered into HTML on the server rather than the client.This is known as server side rendering (SSR), and multiple React metaframeworks exist that leverage this technology.
React helmet usually works fine in cases where your SPA is rendered on the client. However, server side rendering (SSR) is a popular feature of React, and using react-helmet in an SSR environment may lead to some unexpected problems with your <head> metadata. Namely, memory leaks.
Without getting too technical, let’s take a closer look.
What is a side effect?
Using Javascript I/O is an asynchronous, non-blocking feature. For instance, if I utilize the native fetch api to fetch some external data, other Javascript tasks can run while fetch awaits the response for this outside data.
Relying on asynchronous, external data such as this is known as side effects, and when side effects are used, things can become unpredictable, especially in the case of SSR.
Well, react-helmet uses side effects. In fact, it uses a library called react-side-effect, which is why react-helmet by itself isn’t well-suited for a React SSR environment.
Example of React Helmet Failing in SSR
Imagine a Node server that is hosting a React SSR application. Each request requires a fetch call to an external api, creating a side effect. Now, assume the following were to occur:
- User A makes a request to the site.
- While the side effect of user A’s request is pending, user B makes a request.
- The data from user A’s request is finally returned while user B’s is pending.
- The data from user A’s request is ‘leaked’ to user B, and user B ends up receiving the data from user A’s request!
This scenario is known as a memory leak, and in this case happens when side effects aren’t properly scoped to each user’s request.
It’s important to note that memory leak problems aren’t limited to apps that use server side rendering, which is why many developers have opted for react-helmet-async as a safer alternative.
Using react-helmet-async to Prevent Memory Leaks
React-helmet-async is a fork of react-helmet built by someone who experienced this exact memory leak issue on a high volume website. We recommend using react-helmet-async over react-helmet in virtually every scenario.
The important thing to understand is that react-helmet-async ensures that data, or state, is scoped on a per request basis. This means that data is encapsulated for each user’s session separately, ensuring we don’t run into any more annoying memory leaks.
To accomplish this, react-helmet-async uses the provider pattern, which will look very familiar if you’ve ever used state management libraries such as Redux.
But for the developer, things really don’t change a whole lot. Here’s an example of using react-helmet-async on the client:
import React from 'react';
import ReactDOM from 'react-dom';
import { Helmet, HelmetProvider } from 'react-helmet-async';
const app = (
<HelmetProvider>
<App>
<Helmet>
<title>Hello World</title>
<link rel="canonical" href="https://www.tacobell.com/" />
</Helmet>
<h1>Hello World</h1>
</App>
</HelmetProvider>
);
And utilization on a server side app looks like this:
import React from 'react';
import { renderToString } from 'react-dom/server';
import { Helmet, HelmetProvider } from 'react-helmet-async';
const helmetContext = {};
const app = (
<HelmetProvider context={helmetContext}>
<App>
<Helmet>
<title>Hello World</title>
<link rel="canonical" href="https://www.tacobell.com/" />
</Helmet>
<h1>Hello World</h1>
</App>
</HelmetProvider>
);
const html = renderToString(app);
The main difference between client and server side implementation is the addition of the context property, which is needed on the server to hold state specific to each request.
React Helmet SEO | Best Practices for Optimizing Meta Tags for Search Engines
When it comes to optimizing meta tags for SEO, the list of metadata types to cover is quite extensive. However, once you understand the concept, you can pretty much begin applying the knowledge to any circumstance in order to rank better on all search engines.That being said, let’s go over a few of the more common meta tags and how best to optimize them for SEO. This overview was taken from our NextJs Head tutorial, which gives an excellent breakdown of using the helmet component in the NextJs framework.
Title Tag
<title>Title Goes Here</title>
Title tags are perhaps the most important of all meta tags found within the head tag. It sends a powerful signal to Google about your content, providing a bite sized phrase defining what your content actually is. If we could optimize only one aspect of the Head, this would be it.
The title is shown as the link text in Google search results, and also in browser tabs. A length of 50-60 characters is ideal for the title tag.
Meta Description
<meta name='description' content='Description goes here' />
The meta description is perhaps the most underrated meta tag found within the head tag. It is often left blank, leaving Google to extract the description from your page, leading to undesired results.
The meta description is displayed underneath the title in Google search results. Since Google usually truncates descriptions at around 155-160 characters, it’s considered optimal to stay within this range.
Structured Data
<script type="application/ld+json">{ json: “goes here” }</script>
Structured data is a way to spoon feed Google information about your site. Googlebot is just a program, and programs can read and process structured data more efficiently than extracting data from tags. Search engines like efficiency.
Structured data mostly reflects the metadata found within already existing tags inside the head tag. It’s programmatically represented using JavaScript object notation (JSON), and as you can see it’s fairly simple to set up.
React Helmet Component | Overview and Concluding Thoughts
Using the helmet component, preferably react-helmet-async, streamlines the process of managing SEO related metadata in the <head> tag of your React SPA.
Each React page component doesn’t have direct access to the HTML shell’s head tag, and therefore a programmatic solution is required. This is in essence what the helmet component achieves.
At the time of writing, react-helmet has a weekly download count of 1,485,178 on NPM, compared to 2,171,014 for react-helmet-async. Most developers understand the importance of going with the latter, and considering that react-helmet hasn’t been updated in about 2 years, it’s surprising that so many projects still utilize this library.
Nonetheless, both libraries are used to manage the <head> of your React SPA. Hopefully after reading this article, you feel a bit more comfortable with what these libraries bring to the table.