✨ Strapi MCP is now Generally Available - let your agents manage your Strapi content ✨

Ecosystem14 min read

Strapi SEO Plugins: The Complete Guide for Strapi 5

April 22, 2026Updated on May 22, 2026
Top Strapi SEO Plugins

A headless CMS delivers content through APIs, not rendered HTML. That architectural choice gives you full front-end freedom, but it also means no theme layer is automatically injecting your meta tags, generating sitemaps, or wiring up structured data. SEO becomes your responsibility, and without the right tooling, it becomes a manual grind.

This guide covers every piece of the Strapi 5 SEO puzzle: the community SEO plugin, sitemap generation, structured data, API fetching patterns for both REST and GraphQL, front-end rendering in Next.js and Nuxt, and a migration checklist for teams moving from v4.

In brief:

  • The @strapi-community/plugin-seo package provides meta tag management, SERP previews, social previews, and SEO analysis directly in the Strapi Admin Panel.
  • Two sitemap plugins serve different needs: Webtools for more complex requirements, and a standalone plugin for simpler projects.
  • Strapi 5's flattened API responses and documentId system require updated front-end code for SEO data fetching.
  • Structured data, rendering strategy, and Core Web Vitals matter just as much as plugins for search visibility.

Why SEO in a Headless CMS Requires Plugins

When you build with Strapi, your CMS serves raw JSON through REST and GraphQL APIs. There's no theme rendering layer, no automatic <title> tag injection, and no built-in sitemap generator. The CMS also has no knowledge of your front-end routes or how pages appear to users and crawlers.

In practice, that means you need to handle a few things yourself:

  • Fetch SEO fields from Strapi with explicit populate queries
  • Render metadata in your front-end's server-side HTML
  • Generate sitemaps based on your public routes
  • Add structured data where search engines expect it

This is the trade-off of headless CMS: you get complete flexibility over your front-end framework choice and presentation layer, but every SEO element requires explicit implementation. Meta titles, descriptions, canonical URLs, OpenGraph tags, robots directives, XML sitemaps, and structured data all need to be handled by your front-end or through dedicated plugins.

Strapi SEO plugins help by giving editors an Admin Panel UI for managing SEO metadata without touching code. Editors fill in fields, preview how content will appear in search results, and get optimization feedback. You then fetch that data through the API and render it on the front-end. This works well with reusable content modeling guide in Strapi.

Strapi Community SEO Plugin (Official)

The Strapi community SEO plugin is the primary tool for managing search engine optimization within Strapi 5. It integrates directly into the Content Manager, giving editors control over SEO fields without leaving the admin interface.

What It Does

The plugin adds a dedicated SEO panel to any Content-Type that includes the SEO component. Core capabilities include:

  • Meta title and description management with character count limits following SEO best practices.
  • SERP preview showing how content appears in Google results on both desktop and mobile.
  • OpenGraph social previews displaying how shared links render on social platforms.
  • SEO content analysis with green, orange, and red scoring that highlights optimization opportunities and issues.
  • Canonical URL support to prevent duplicate content problems across your site.
  • i18n support for per-locale SEO fields, so each language version of your content gets its own meta title, description, and social preview data.

The analysis engine checks your content against common SEO criteria and points out what to improve directly in the Admin Panel. That gives content teams faster feedback and removes a lot of back-and-forth with developers. For deeper optimization techniques, explore the plugin README.

Installation on Strapi 5

The correct package for Strapi 5 is @strapi-community/plugin-seo. The original strapi-plugin-seo repository was archived, and the maintained package for current Strapi 5 projects is the community fork.

# Yarn
yarn add @strapi-community/plugin-seo

# npm
npm install @strapi-community/plugin-seo

# pnpm
pnpm add @strapi-community/plugin-seo

Register the plugin in ./config/plugins.ts:

export default () => ({
  seo: {
    enabled: true,
  },
});

Rebuild the Admin Panel after installation:

yarn build

Without this rebuild step, the SEO panel won't appear. Use yarn develop during development for hot module reloading.

Setting Up the SEO Component

On first access to the SEO plugin homepage in the Admin Panel, the plugin automatically checks for a shared.seo component. If it doesn't exist, the plugin creates it for you, along with its shared.meta-social subcomponent.

To add the SEO component to a Content-Type manually, include it in your schema's attributes:

{
  "attributes": {
    "seo": {
      "type": "component",
      "repeatable": false,
      "component": "shared.seo"
    }
  }
}

You can also add it through the Content-Type Builder UI: navigate to your Content-Type, add a component field, and select shared.seo. Once the component exists at the root level, the SEO panel appears automatically in the Content Manager's right-side panel for that Content-Type. No additional configuration is needed.

The OpenGraph Component (Replacing metaSocial)

Version 2.0.2 introduced a breaking change: the old metaSocial repeatable component was replaced by a single, non-repeatable openGraph component. If you're migrating from an earlier version, this requires updating your schema and writing a custom data migration script. No automated migration is provided.

The current OpenGraph component schema uses these fields:

FieldTypeMax LengthRequired
og_titlestring70Yes
og_descriptionstring200Yes
og_imagemedia (single)No
og_urlstringNo
og_typestringNo

Note the underscore naming convention (og_title instead of og:title). The initial release used colon notation following the OpenGraph Protocol standard, but this GraphQL issue broke type generation because GraphQL field names don't allow colons. The fix in PR #97 renamed all fields to use underscores. If you're using GraphQL, this matters.

Sitemap Generation in Strapi 5

Strapi doesn't generate sitemaps natively since it has no awareness of your front-end URL structure. Two Strapi plugins solve this with different approaches.

For larger or more complex sites, the Webtools ecosystem provides robust sitemap functionality. It requires two packages: the core strapi-plugin-webtools and the webtools-addon-sitemap extension.

npm install strapi-plugin-webtools --save
npm install webtools-addon-sitemap --save

Key capabilities include sitemap splitting, a sitemap index at /api/sitemap/index.xml, URL aliasing integration, configurable <lastmod>, <priority>, and <changefreq> attributes, cron-based regeneration, and multilingual support.

This is the better choice if you're managing content at scale or need URL aliasing across multiple Content-Types and locales.

Strapi 5 Sitemap Plugin (Standalone)

For simpler projects, the standalone strapi-5-sitemap-plugin requires no additional dependencies:

npm install strapi-5-sitemap-plugin

It provides an Admin Panel UI to select Collection Types, define URL patterns using template syntax (/blog/[slug]), and add custom static links for pages outside the CMS. The sitemap is served at /api/strapi-5-sitemap-plugin/sitemap.xml.

This plugin is a practical fit when you have a straightforward site architecture and fewer URLs to manage. It does not clearly document auto-splitting behavior at scale or multilingual support, so consider the Webtools add-on if those features matter to your project.

Structured Data and Schema Markup

Structured data tells search engines what your content represents, which helps with rich snippets and other enhanced results. Strapi doesn't generate Schema.org markup automatically, but its content modeling guide maps well to structured data types.

Mapping Content Types to Schema.org

Strapi 5 content models align well with common Schema.org types. An Article Content-Type with title, description, publishedAt, author, and coverImage fields maps directly to Article properties like headline, description, datePublished, author, and image. The same pattern applies to Product, with name, price, and availability, Event, with startDateTime, location, and organizer, and other types.

Design reusable Strapi components for nested Schema.org types: a Person component (name, email, image), an Organization component (name, url, logo), and an Offer component (price, currency, availability). These can be embedded across multiple Content-Types while maintaining consistent structured data output.

Generating JSON-LD from Strapi API Responses

The recommended approach is JSON-LD injected during server-side rendering. Fetch your content from the Strapi API, map the response fields to Schema.org properties, and inject the result as a <script type="application/ld+json"> tag in your HTML.

const { data } = await response.json();

const articleJsonLd = {
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": data.title,
  "description": data.description,
  "image": data.coverImage?.url
    ? `${STRAPI_URL}${data.coverImage.url}`
    : undefined,
  "datePublished": data.publishedAt,
  "dateModified": data.updatedAt,
  "author": {
    "@type": "Person",
    "name": data.author?.name
  }
};

Validate your output with Google's Rich Results Test or the Schema Validator. For a deeper implementation walkthrough, see Strapi's structured data guide.

Fetching SEO Data via the Strapi 5 API

Strapi 5 introduced significant changes to API response structures. You need to account for them when you fetch SEO fields and render metadata on the front-end.

REST API Examples

By default, Strapi 5 returns only top-level scalar fields. SEO components and their nested relations must be explicitly populated:

GET /api/articles?populate[0]=seo&populate[1]=seo.openGraph

For complex queries, the qs library keeps things readable:

const qs = require('qs');
const query = qs.stringify({
  populate: ['seo', 'seo.openGraph']
}, { encodeValuesOnly: true });

const response = await fetch(`/api/articles?${query}`);

Strapi 5 responses are flattened. There's no data.attributes wrapper anymore:

{
  "data": {
    "documentId": "clkgylmcc000008lcdd868feh",
    "title": "Article A",
    "seo": {
      "metaTitle": "SEO Title",
      "metaDescription": "...",
      "openGraph": {
        "og_title": "OG Title",
        "og_description": "OG Desc",
        "og_image": { "url": "/uploads/og_image.jpg" }
      }
    }
  }
}

Access fields directly: data.seo.metaTitle, not data.attributes.seo.metaTitle. The documentId field replaces id for all lookups. For more on populate queries, the Strapi blog has detailed examples.

GraphQL API Examples

Query a single document by documentId:

{
  article(documentId: "a1b2c3d4e5d6f7g8h9i0jkl") {
    documentId
    title
    seo {
      metaTitle
      metaDescription
      keywords
      openGraph {
        og_title
        og_description
        og_image { url }
      }
    }
  }
}

For paginated collections, Strapi 5 supports Relay-style _connection queries:

{
  articles_connection(first: 5, after: "cursor") {
    nodes {
      documentId
      title
      seo { metaTitle }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

Flat queries return a list only, while _connection queries include both nodes and pageInfo. Understanding how REST and GraphQL work together in Strapi helps you choose the right approach for each use case.

Rendering Meta Tags on the Frontend

In Next.js App Router, use the generateMetadata export to map Strapi SEO fields to HTML meta tags. This runs server-side, which ensures metadata is present in the initial HTML for crawlers:

export async function generateMetadata({ params }): Promise<Metadata> {
  const pageData = await getPageData(params.slug);
  const seo = pageData.seo || {};
  const og = seo.openGraph || {};

  return {
    title: seo.metaTitle || pageData.title,
    description: seo.metaDescription,
    openGraph: {
      title: og.og_title || seo.metaTitle,
      description: og.og_description || seo.metaDescription,
      images: og.og_image
        ? [{ url: `${process.env.STRAPI_URL}${og.og_image.url}` }]
        : undefined,
    },
  };
}

In Nuxt, the useSeoMeta composable provides TypeScript-safe, XSS-protected meta tag rendering:

useSeoMeta({
  title: seo.metaTitle || pageData?.title,
  description: seo.metaDescription,
  ogTitle: og.og_title || seo.metaTitle,
  ogDescription: og.og_description || seo.metaDescription,
  ogImage: og.og_image?.url
    ? `${config.public.strapiUrl}${og.og_image.url}`
    : undefined,
});

A few implementation details matter here:

  • Always use the explicit populate parameter because SEO components aren't returned by default
  • Prepend your Strapi URL to media fields so OpenGraph images use absolute URLs
  • Render metadata server-side so crawlers see it in the initial HTML

Those three checks prevent a lot of the SEO issues teams usually spot late in QA. For a practical walkthrough of Next.js integration, the tutorial series covers these patterns in depth.

SEO Best Practices Beyond Plugins

Plugins handle metadata, but search visibility depends on broader architectural decisions too.

URL Slugs and Flat Site Architecture

Use human-readable slugs in public URLs, not Strapi's documentId. A URL like /blog/strapi-seo-guide is preferable to /blog/clkgylmcc000008lcdd868feh for both users and search engines. Store a slug field in your Content-Types and keep your URL structure aligned with simple, descriptive paths.

SSR, SSG, and Rendering Strategy

Rendering strategy is non-negotiable for headless SEO. Client-side rendering alone is risky because content isn't visible until JavaScript executes. Server-side rendering or pre-rendering is the safer default for reliable indexing.

ISR (Incremental Static Regeneration) is the practical sweet spot for most Strapi content sites. Pages stay cached for performance but revalidate when content changes. Combine ISR with Strapi webhooks to trigger revalidation after content updates. Next.js ISR, Nuxt static generation, and Astro all work well as front-end choices paired with Strapi.

Core Web Vitals and Performance

API response times directly impact page load speed. Keep Strapi queries efficient by populating only the fields you need.

A solid baseline looks like this:

  • Cache API responses and static assets behind a CDN
  • Optimize images to reduce payload size
  • Set explicit width and height values for CMS-driven images to avoid layout shifts
  • Avoid over-populating relations when a smaller query will do

These are small implementation details, but they directly affect Core Web Vitals and how stable the page feels to users. Optimizing image optimization and performance guide supports better user experience and aligns with Google's Core Web Vitals.

Internationalized SEO with Strapi 5 i18n

Strapi 5's i18n support uses locale as a top-level API parameter:

GET /api/articles?locale=fr&populate=seo.openGraph

Enable field-level localization on seo.metaTitle, seo.metaDescription, slug, and OpenGraph fields so each language gets distinct SEO metadata. Implement hreflang tags on the front-end, linking every locale variant to all others, including an x-default. Use localized slugs and localized subdirectories (/en/, /fr/) for the cleanest URL pattern. For more details, see the i18n guide.

Migrating SEO Setup from Strapi v4 to v5

If you're upgrading an existing Strapi 4 project, SEO-related code needs specific attention. Here's a checklist of the breaking changes that affect your SEO implementation:

Changev4v5
SEO plugin packagestrapi-plugin-seo@strapi-community/plugin-seo
Social componentmetaSocial (repeatable)openGraph (non-repeatable)
Service layerEntity ServiceDocument Service
Content identifieriddocumentId
Response shapedata.attributes.fielddata.field (flat)
Publication filterpublicationState: 'live'status: 'published'

Start with Strapi's automated upgrade tool, which handles dependency updates and some syntax transformations. The codemods insert __TODO__ placeholders wherever automatic conversion isn't possible, especially around id to documentId changes. Resolve every one of these manually.

From there, work through the front-end pieces in order:

  • Remove .attributes from every response access path
  • Update sitemap scripts, canonical URL logic, and JSON-LD generators for flat responses
  • Replace id lookups with documentId
  • Migrate metaSocial data into the new openGraph structure with a custom script

That order keeps the migration manageable and helps you catch broken SEO output before it reaches production. With TypeScript support in Strapi 5, type-checking catches many of these structural issues at build time.

During the transition, you can send the Strapi-Response-Format: v4 header to temporarily receive old-format responses while updating front-end code incrementally.

Bringing It All Together: Building a Complete Strapi 5 SEO Stack

A production-ready Strapi 5 SEO setup combines several pieces: @strapi-community/plugin-seo for meta tag management and content analysis, a sitemap plugin, Webtools for complex sites, the standalone plugin for simpler ones, custom JSON-LD generation for structured data, and an SSR or SSG front-end that renders everything into crawler-accessible HTML.

The plugin improves the editor workflow. Your front-end renders the actual SEO output. If URLs, rendering, or performance are off, search engines will still struggle to index and rank your pages.

Browse the Strapi Marketplace for additional plugins that complement your SEO stack, and explore Strapi features to see how the platform's flexible, API-first architecture supports your search visibility goals.

Frequently Asked Questions

Is the Strapi SEO plugin free?

Yes. The @strapi-community/plugin-seo package is free and open source, available on the Strapi Marketplace. It works with both self-hosted Strapi and Strapi Cloud deployments.

What happened to the original strapi-plugin-seo?

The original repository under the strapi organization was archived, and the actively maintained package for Strapi 5 is @strapi-community/plugin-seo. If your project still references the old package, remove it and install the new one.

How do I generate a sitemap in Strapi 5?

Two options: install strapi-plugin-webtools plus webtools-addon-sitemap for complex sites with sitemap indexing and broader configuration options, or use strapi-5-sitemap-plugin for simpler projects needing basic XML generation. Neither is included with Strapi by default.

Can I use Strapi SEO plugins with Next.js?

Yes. Fetch SEO data from the Strapi API using populate queries, then map the fields to Next.js's generateMetadata export in App Router. The metadata renders server-side, ensuring crawlers see it in the initial HTML. The same pattern works with Nuxt using useSeoMeta. For a deeper dive into populate queries, see the Strapi blog.

Are older third-party SEO plugins compatible with Strapi 5?

Some older third-party SEO plugins have not been updated for Strapi 5 compatibility. Before installing any plugin, check its package version, maintenance status, and published compatibility notes for Strapi 5.

Paul BratslavskyDeveloper Advocate
Build a Gift Registry Platform
Ecosystem·20 min read

How to Build a Gift Registry and Wishlist Platform with Next.js 16 and Strapi 5

Gift registries have a tricky requirement most apps don't: the owner should never know who claimed what. A wedding...

·June 26, 2026
Build a Mental Health Journal
Ecosystem·23 min read

How to Build a Mental Health Journal and Mood Tracker with Next.js 16 and Strapi 5

Tracking your mood over time sounds simple until you try to build it: every entry has to stay private, the trends need...

·June 26, 2026
Ecosystem·22 min read

How to Build a Webinar and Workshop Registration Platform with Next.js 16 and Strapi 5

Running webinars and workshops sounds simple until you hit the operational details: capacity limits that need...

·June 26, 2026