1Installation

Install the package using your preferred package manager:

npmshell
npm install react-ssr-seo
yarnshell
yarn add react-ssr-seo
pnpmshell
pnpm add react-ssr-seo
i

Peer dependency: React >= 18.0.0 is required. The package has zero other dependencies.

2Create a Site Config

Define shared SEO defaults for your entire site. This config will be merged with page-specific overrides.

config/seo.tsTypeScript
import { createSEOConfig } from "react-ssr-seo";

// Shared base config — reused across all pages
export const siteConfig = createSEOConfig({
  titleTemplate: "%s | My Site",
  description: "Default site description for SEO.",
  openGraph: {
    siteName: "My Site",
    type: "website",
    locale: "en_US",
  },
  twitter: {
    card: "summary_large_image",
    site: "@mysite",
  },
});

export const SITE_URL = "https://mysite.com";
TIP

titleTemplate uses %s as a placeholder. When a page sets title: "About", it renders as About | My Site.

3Build Your First SEO Page

Use mergeSEOConfig to combine your base config with page-specific values, then render with the <SEOHead> component.

pages/About.tsxTSX
import {
  mergeSEOConfig,
  buildCanonicalUrl,
  SEOHead,
} from "react-ssr-seo";
import { siteConfig, SITE_URL } from "../config/seo";

export function AboutPage() {
  const seo = mergeSEOConfig(siteConfig, {
    title: "About Us",
    description: "Learn about our mission and team.",
    canonical: buildCanonicalUrl(SITE_URL, "/about"),
    openGraph: {
      title: "About Us — My Site",
      description: "Learn about our mission and team.",
      url: buildCanonicalUrl(SITE_URL, "/about"),
    },
  });

  return (
    <html>
      <head>
        <SEOHead {...seo} />
      </head>
      <body>
        <h1>About Us</h1>
        <p>Our story...</p>
      </body>
    </html>
  );
}

This generates the following HTML tags:

Generated <head> outputHTML
<title>About Us | My Site</title>
<meta name="description" content="Learn about our mission and team." />
<link rel="canonical" href="https://mysite.com/about" />
<meta property="og:title" content="About Us — My Site" />
<meta property="og:description" content="Learn about our mission and team." />
<meta property="og:url" content="https://mysite.com/about" />
<meta property="og:site_name" content="My Site" />
<meta property="og:type" content="website" />
<meta property="og:locale" content="en_US" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@mysite" />

4Add JSON-LD Structured Data

Use the built-in schema generators to add structured data for rich search results.

Adding article schemaTSX
import {
  createArticleSchema,
  createBreadcrumbSchema,
  JsonLd,
} from "react-ssr-seo";

// In your component:
const articleSchema = createArticleSchema({
  headline: "My Blog Post",
  url: "https://mysite.com/blog/my-post",
  datePublished: "2025-06-15",
  dateModified: "2025-07-01",
  author: [{ name: "Jane Doe", url: "https://mysite.com/authors/jane" }],
  publisher: { name: "My Site", logo: "https://mysite.com/logo.png" },
  images: ["https://mysite.com/images/post.jpg"],
});

const breadcrumb = createBreadcrumbSchema([
  { name: "Home", url: "https://mysite.com" },
  { name: "Blog", url: "https://mysite.com/blog" },
  { name: "My Blog Post", url: "https://mysite.com/blog/my-post" },
]);

// In JSX:
<head>
  <SEOHead {...seo} />
  <JsonLd data={articleSchema} />
  <JsonLd data={breadcrumb} />
</head>

5Framework Integration

Next.js (App Router)

Use the builder functions with generateMetadata and render JSON-LD directly in your page component.

app/blog/[slug]/page.tsxTSX
import {
  mergeSEOConfig,
  buildCanonicalUrl,
  buildTitle,
  buildOpenGraph,
  createArticleSchema,
  safeJsonLdSerialize,
} from "react-ssr-seo";
import { siteConfig, SITE_URL } from "@/config/seo";
import type { Metadata } from "next";

export async function generateMetadata({ params }): Promise<Metadata> {
  const post = await getPost(params.slug);
  const seo = mergeSEOConfig(siteConfig, {
    title: post.title,
    description: post.excerpt,
    canonical: buildCanonicalUrl(SITE_URL, `/blog/${post.slug}`),
  });

  return {
    title: buildTitle(seo.title!, seo.titleTemplate),
    description: seo.description,
    alternates: { canonical: seo.canonical },
    openGraph: {
      title: post.title,
      description: post.excerpt,
      url: seo.canonical,
      images: [{ url: post.image }],
    },
  };
}

export default async function BlogPage({ params }) {
  const post = await getPost(params.slug);

  const schema = createArticleSchema({
    headline: post.title,
    url: buildCanonicalUrl(SITE_URL, `/blog/${post.slug}`),
    datePublished: post.date,
    author: [{ name: post.author }],
  });

  return (
    <article>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{
          __html: safeJsonLdSerialize(schema),
        }}
      />
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </article>
  );
}

React Router 7 SSR

Use the <SEOHead> component in your Document (root layout).

root.tsxTSX
import { SEOHead, JsonLd, mergeSEOConfig } from "react-ssr-seo";
import { siteConfig } from "./config/seo";

export default function Root() {
  const seo = mergeSEOConfig(siteConfig, {
    title: "Home",
    canonical: "https://mysite.com",
  });

  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport"
          content="width=device-width, initial-scale=1" />
        <SEOHead {...seo} />
      </head>
      <body>
        {/* Your app content */}
      </body>
    </html>
  );
}

Express / Generic SSR

Use renderToString with the SEOHead component for any Express-based SSR setup.

server.tsxTSX
import express from "express";
import { renderToString } from "react-dom/server";
import { SEOHead, mergeSEOConfig } from "react-ssr-seo";
import { siteConfig } from "./config/seo";

const app = express();

app.get("/", (req, res) => {
  const seo = mergeSEOConfig(siteConfig, {
    title: "Home",
  });

  const html = renderToString(
    <html>
      <head>
        <SEOHead {...seo} />
      </head>
      <body>
        <h1>Welcome</h1>
      </body>
    </html>
  );

  res.send(`<!DOCTYPE html>${html}`);
});

app.listen(3000);
VIEW

This very page has SEO tags! Right-click and select "View Page Source" to see the title template, description, canonical URL, Open Graph, and Twitter Card meta tags generated by react-ssr-seo.