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.
The free checker shows your previews for nine platforms — from X and WhatsApp to iMessage, Discord and Bluesky.
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
- Setting meta in onMountedonMounted runs only in the browser — scrapers never execute it. Keep useSeoMeta in setup so it renders on the server.
- Relative ogImageogImage: "/og.png" produces a tag most platforms ignore. Always prefix with your full site URL.
- Static generation with stale dataWith nuxi generate, tags are frozen at build time. Rebuild (or use ISR/SSR) when preview-relevant content changes.
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.
Paste your URL and see within two seconds whether everything is right — on every platform.