How to add Open Graph tags in Nuxt

Nuxt ships a first-class API for social tags: useSeoMeta. It is typed, per-page, and renders server-side — exactly what scrapers need. The two things it does not do for you: absolute image URLs and a sensible default for pages that forget to set anything.

Want to see how your page looks right now?

The free checker shows your previews for nine platforms — from X and WhatsApp to iMessage, Discord and Bluesky.

Check your URL

Set global defaults in app.vue

Call useSeoMeta in app.vue with your site-wide fallbacks (site name, default description, default og:image). Pages then override only what differs — no page can end up with an empty preview.

Override per page with useSeoMeta

In each page component, call useSeoMeta({ title, ogTitle, description, ogDescription, ogImage, twitterCard: "summary_large_image" }). For dynamic routes, compute the values from the fetched data (works fine inside async setup).

Keep og:image absolute

ogImage must be a full https URL. Store your canonical site URL once (e.g. in runtimeConfig.public.siteUrl) and prefix image paths with it — scrapers ignore relative paths.

Verify the server-rendered HTML

Tags added only on the client are invisible to scrapers. Check a deployed URL with the MetaPeek checker (it fetches like a scraper does); if the tags are missing there but visible in your browser, they are being set client-side.

Code example

<script setup>
// pages/blog/[slug].vue (Nuxt 3/4)
const route = useRoute()
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`)
const siteUrl = useRuntimeConfig().public.siteUrl

useSeoMeta({
  title: () => post.value.title,
  description: () => post.value.excerpt,
  ogTitle: () => post.value.title,
  ogDescription: () => post.value.excerpt,
  ogImage: () => siteUrl + post.value.ogImage, // absolute!
  ogUrl: () => siteUrl + route.path,
  twitterCard: 'summary_large_image',
})
</script>

Common mistakes

Frequently asked questions

useSeoMeta or useHead?

useSeoMeta is the flat, typed shortcut for exactly this job and protects against typos like og:titel. useHead remains useful for non-meta head tags.

Can Nuxt generate og:images automatically?

Yes — the nuxt-og-image module renders 1200×630 images from Vue templates at request or build time. Set it up once, get a branded image per page.

Why do my tags show in devtools but not to scrapers?

They are being injected client-side (wrong lifecycle, or a client-only plugin). View the page source (Ctrl+U) — what you see there is what scrapers get.

Changed your tags? Verify the result.

Paste your URL and see within two seconds whether everything is right — on every platform.

Open the checker

Related guides