Strapi Open Graph Tags: Add OG Meta to Your Headless CMS Site
Set og:title, og:image, og:description and Twitter card meta tags on a Next.js or Nuxt frontend backed by Strapi CMS — step-by-step with API examples.
How OG tags work with Strapi
Strapi is a headless CMS — it manages your content and exposes it via REST or GraphQL. Your frontend (Next.js, Nuxt, Astro, etc.) fetches this content and renders HTML. Open Graph tags are the frontend's responsibility. Strapi helps by letting you define SEO fields on your content types that your frontend reads and injects into the HTML head.
Step 1: Add SEO component to Strapi content type
Create a reusable SEO component in Strapi (v4+):
- Go to Content-Type Builder → Components → Create component
- Name it
shared.seo - Add fields:
metaTitle(text),metaDescription(text),ogImage(media) - Add the component to your Article/Page content type as a repeatable or single component
Alternatively, use the official @strapi/plugin-seo which provides a built-in SEO UI panel with live preview.
Step 2: Fetch SEO data via Strapi REST API
// Populate the seo component in your API request
const res = await fetch(
`${process.env.STRAPI_URL}/api/articles?filters[slug][$eq]=${slug}&populate[seo][populate]=ogImage`,
{ headers: { Authorization: `Bearer ${process.env.STRAPI_TOKEN}` } }
);
const { data } = await res.json();
const article = data[0]?.attributes;
const seo = article?.seo;
// seo.ogImage.data.attributes.url is the raw Strapi media URL
const ogImageUrl = seo?.ogImage?.data?.attributes?.url
? `${process.env.STRAPI_URL}${seo.ogImage.data.attributes.url}`
: undefined;Step 3: generateMetadata in Next.js
// app/articles/[slug]/page.tsx
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const article = await getArticle(params.slug);
const seo = article.seo;
return {
title: seo?.metaTitle || article.title,
description: seo?.metaDescription || article.excerpt,
openGraph: {
title: seo?.metaTitle || article.title,
description: seo?.metaDescription || article.excerpt,
images: ogImageUrl ? [{ url: ogImageUrl, width: 1200, height: 630 }] : [],
type: 'article',
url: `https://yourdomain.com/articles/${params.slug}`,
},
twitter: {
card: 'summary_large_image',
title: seo?.metaTitle || article.title,
description: seo?.metaDescription || article.excerpt,
images: ogImageUrl ? [ogImageUrl] : [],
},
};
}Nuxt + Strapi: useSeoMeta
// pages/articles/[slug].vue (Nuxt 3)
<script setup>
const { params } = useRoute();
const { data: article } = await useAsyncData(() =>
$fetch(`${strapiUrl}/api/articles?filters[slug][$eq]=${params.slug}&populate[seo][populate]=ogImage`)
);
const seo = computed(() => article.value?.data[0]?.attributes?.seo);
useSeoMeta({
title: () => seo.value?.metaTitle || article.value?.data[0]?.attributes?.title,
ogTitle: () => seo.value?.metaTitle,
ogDescription: () => seo.value?.metaDescription,
ogImage: () => seo.value?.ogImage?.data?.attributes?.url
? `${strapiUrl}${seo.value.ogImage.data.attributes.url}` : undefined,
twitterCard: 'summary_large_image',
});
</script>Verify your Strapi OG tags
After deploying, paste your URL into OGFixer to preview how Twitter, Slack, Discord, and LinkedIn will render your links.