Blog
Back to Blog

Complete Guide to Open Graph Meta Tags in Nuxt 3 with useSeoMeta

10/31/2025

Open Graph (OG) meta tags control how your content appears when shared on social platforms like Facebook, LinkedIn, Twitter/X, and Discord. In Nuxt 3, the useSeoMeta composable provides a modern, type-safe way to configure these tags and maximize your social media presence.

Why Open Graph Matters

When someone shares your link on social media, platforms crawl your page for Open Graph meta tags to generate rich preview cards. A well-configured OG image and title can double your click-through rate compared to plain text links.

Without proper OG tags, social platforms display generic previews with broken images or missing descriptions—wasting your content's viral potential.

The Modern Approach: useSeoMeta

Nuxt 3 introduced useSeoMeta, a composable that handles Open Graph tags with full TypeScript support and automatic deduplication. This is the recommended method over manual <meta> tags or the older useHead approach for SEO properties.

Basic Implementation

Use useSeoMeta in any page or component's <script setup>:

<script setup lang="ts">
useSeoMeta({
  // Basic Open Graph tags
  ogTitle: 'Your Engaging Page Title',
  ogDescription: 'A compelling description that makes people want to click',
  ogType: 'website',
  ogUrl: 'https://example.com/page',
  ogImage: 'https://example.com/og-image.png',

  // Twitter/X Card tags
  twitterCard: 'summary_large_image',
  twitterTitle: 'Your Engaging Page Title',
  twitterDescription: 'A compelling description that makes people want to click',
  twitterImage: 'https://example.com/og-image.png'
})
</script>

Key Properties

Property Purpose Best Practices
ogTitle Social share title 40-60 chars; can differ from page <title>
ogDescription Social share description 120-160 characters for optimal display
ogType Content type website, article, book, profile, video.movie
ogUrl Canonical URL Absolute URLs only; match rel="canonical"
ogImage Preview image Critical for CTR—1200x630px min, absolute URL
ogImageAlt Image alt text Accessibility and fallback display
twitterCard Twitter card type Use summary_large_image for rich previews

Open Graph Images

The og:image property has the biggest impact on engagement. Follow these specifications:

Image Requirements

  • Dimensions: 1200x630px minimum (1200x630 or 1200x1200 recommended)
  • File size: ~1MB maximum (smaller loads faster)
  • Format: PNG for graphics, JPEG for photos
  • URL: Must be absolute (https://example.com/image.png)
  • Alt text: Always include ogImageAlt for accessibility

Image Configuration Example

<script setup lang="ts">
useSeoMeta({
  ogImage: 'https://example.com/og-image.png',
  ogImageAlt: 'Descriptive text for the image',
  ogImageWidth: '1200',
  ogImageHeight: '630',
  ogImageType: 'image/png',

  // For Twitter/X
  twitterCard: 'summary_large_image',
  twitterImage: 'https://example.com/og-image.png',
  twitterImageAlt: 'Descriptive text for the image'
})
</script>

Dynamic and Reactive Tags

Nuxt's useSeoMeta supports reactive values—perfect for dynamic routes like blog posts or product pages:

<script setup lang="ts">
const route = useRoute()
const { data: article } = await useFetch(`/api/articles/${route.params.slug}`)

useSeoMeta({
  ogTitle: () => article.value?.title,
  ogDescription: () => article.value?.excerpt,
  ogImage: () => `https://example.com/api/og?title=${encodeURIComponent(article.value?.title)}`,
  ogType: 'article',
  ogUrl: () => `https://example.com${route.fullPath}`,

  // Article-specific properties
  articlePublishedTime: () => article.value?.publishedAt,
  articleAuthor: () => article.value?.author,
  articleTag: () => article.value?.tags
})
</script>

Critical Warning: Never set OG tags in onMounted() or client-side only code. Social media crawlers don't execute JavaScript, so tags must be rendered server-side.

Global Defaults and Page Overrides

Global Configuration

export default defineNuxtConfig({
  app: {
    head: {
      meta: [
        { property: 'og:site_name', content: 'Your Site Name' },
        { property: 'og:type', content: 'website' },
        { property: 'og:locale', content: 'en_US' }
      ]
    }
  }
})

Page-Level Overrides

<!-- pages/about.vue -->
<script setup lang="ts">
useSeoMeta({
  ogTitle: 'About Us - Your Site Name',
  ogDescription: 'Learn about our mission and team',
  ogImage: 'https://example.com/about-og.png'
})
</script>

Or set defaults in your root layout:

<!-- layouts/default.vue -->
<script setup lang="ts">
const config = useRuntimeConfig()

useSeoMeta({
  ogSiteName: 'Your Site Name',
  ogType: 'website',
  ogLocale: 'en_US'
})
</script>

Multiple Images

For articles or products with multiple preview images:

<script setup lang="ts">
useHead({
  meta: [
    { property: 'og:image', content: 'https://example.com/image1.png' },
    { property: 'og:image', content: 'https://example.com/image2.png' },
    { property: 'og:image', content: 'https://example.com/image3.png' }
  ]
})
</script>

Platform Caching Behavior

Different social platforms handle Open Graph caching differently:

  • Facebook: ~30 days cache; force refresh via Sharing Debugger
  • LinkedIn: 7+ days aggressive caching; images must be publicly accessible
  • Twitter/X: Respects OG tags but prioritizes Twitter Card tags
  • Discord: Real-time previews with animated GIF support
  • Slack: Weekly cache refresh

Always test your OG tags with platform debuggers after deployment.

Complete Example

<!-- pages/blog/[slug].vue -->
<script setup lang="ts">
const route = useRoute()
const config = useRuntimeConfig()
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`)

if (!post.value) {
  throw createError({ statusCode: 404 })
}

const ogImageUrl = `${config.public.siteUrl}/api/og?title=${encodeURIComponent(post.value.title)}&author=${encodeURIComponent(post.value.author)}`

useSeoMeta({
  title: post.value.title,
  description: post.value.excerpt,

  // Open Graph
  ogTitle: post.value.title,
  ogDescription: post.value.excerpt,
  ogType: 'article',
  ogUrl: `${config.public.siteUrl}${route.fullPath}`,
  ogImage: ogImageUrl,
  ogImageAlt: post.value.title,
  ogImageWidth: '1200',
  ogImageHeight: '630',

  // Article metadata
  articlePublishedTime: post.value.publishedAt,
  articleModifiedTime: post.value.updatedAt,
  articleAuthor: post.value.author,
  articleSection: post.value.category,
  articleTag: post.value.tags,

  // Twitter Card
  twitterCard: 'summary_large_image',
  twitterTitle: post.value.title,
  twitterDescription: post.value.excerpt,
  twitterImage: ogImageUrl,
  twitterImageAlt: post.value.title
})
</script>

Testing and Debugging

Verify Server-Side Rendering

Check your HTML source (View Page Source):

<meta property="og:title" content="Your Page Title">
<meta property="og:image" content="https://example.com/og-image.png">

If tags are missing, ensure SSR is enabled (not SPA mode) and tags are set in <script setup>.

Platform Debuggers

Common Issues

Problem Solution
Image not showing Verify absolute URL, check HTTPS, ensure public access
Wrong image appears Clear platform cache with debugger tools
Title/description truncated Reduce character count (title: 40-60, description: 120-160)
Tags not updating Ensure SSR is enabled; avoid setting in onMounted()

Pre-Launch Checklist

Before publishing:

  • ogTitle: 40-60 characters, compelling
  • ogDescription: 120-160 characters, descriptive
  • ogImage: Absolute URL, 1200x630px minimum, under 1MB
  • ogImageAlt: Meaningful description provided
  • ogUrl: Absolute path matching canonical URL
  • ogType: Correct content type (website, article, etc.)
  • twitterCard: Set to summary_large_image
  • Twitter tags mirror Open Graph tags
  • Tested with 2+ platform debuggers
  • SSR verified (view HTML source)

Next Steps

Validate your Open Graph tags with OG Check to preview how they appear across Facebook, Twitter, LinkedIn, and Discord. Get instant visual feedback and copy-ready meta tag code.

For dynamic OG images, implement an API route that generates images on-the-fly using @vercel/og or satori.

References

OG Check

© 2025 OG Check. All rights reserved.