Mastering Open Graph Tags in Vue & Nuxt
Introduction
Open Graph (OG) tags mainly control how your content appears when shared on social platforms. However, they can also provide better content understanding for web crawlers, similar to Schema.org.
There are 60+ possible OG tags but most have specific use cases.
<meta property="og:title" content="Your title that matters">
<meta property="og:description" content="Short description">
<meta property="og:image" content="https://mysite.com/og.png">
<meta property="og:url" content="https://mysite.com/page">
Quick Tips
- Images matter: A good og:image can double your click-through rate, they must be an absolute URL and at least 1200x600px.
- Make the title engaging: Your og:title doesn't have to match your page title. While page titles need to be SEO-friendly, your og:title can be casual and provocative. Use emojis, numbers, and conversational language - social isn't search.
- Leverage Contextual OG Types: You can mark up articles and author pages to provide more context for crawlers.
Implementation in Vue
You should handle your OG tags with
useSeoMeta({
ogTitle: 'Hey! Open graph images are important, check them out.',
ogDescription: 'But who reads the description anyway?',
ogImage: 'https://mysite.com/og.png', // must be absolute URL
ogUrl: 'https://mysite.com/products/item' // this is your canonical url
})
Useful Open Graph Tags
See the dedicated
og:image
The most important tag - invest time here.
Some rules:
- Must be an absolute URL
- Should be at least 1200x600px
- Set a
twitter:card tag for X - Use
og:image:alt for accessibility
There are several other properties, including them can be useful to ensure the image is being displayed correctly.
useSeoMeta({
// ✅ use absolute URLs
ogImage: 'https://mysite.com/og-images/product-preview.jpg',
ogImageAlt: '3 boxes on top of each other',
// Optional
ogImageWidth: 1200,
ogImageHeight: 600,
ogImageType: 'image/jpeg',
ogImageUrl: 'https://mysite.com/og-images/product-preview.jpg',
// X specific tags
twitterCard: 'summary_large_image',
twitterImage: 'https://mysite.com/og-images/product-preview.jpg',
twitterImageSrc: 'https://mysite.com/og-images/product-preview.jpg'
})
Create dynamic images using Nuxt OG Image.
og:type {lang="ts}
og:url {lang="ts}
Use this when setting your canonical URL, they should match exactly.
useHead({
link: [
{ rel: 'canonical', href: 'https://mysite.com/products/item' }
]
})
useSeoMeta({
ogUrl: 'https://mysite.com/products/item',
})
Dynamic OG Tags
Use Vue's reactivity to handle dynamic content.
- Do not set
og data withinonMounted as it won't be available to crawlers.
<script setup lang="ts">
const { data: product } = await useAsyncData(() => fetchProduct())
useSeoMeta({
// Computed syntax keeps it reactive
ogTitle: () => product.value.name,
ogDescription: () => product.value.shortPitch,
// Generate dynamic OG images - must be absolute
ogImage: () => `https://mysite.com/api/og?title=${product.value.name}`
})
</script>
Platform Specific Notes
- Uses their own crawler
- Cache time: ~30 days
- Force refresh: Use Sharing Debugger
- Aggressive caching (7+ days)
- Images must be public (no auth)
- Clear cache: Post Inspector
Discord
- Real-time preview
- Supports animated GIFs
- No cache clearing needed
Twitter (X)
- Prefers Twitter Cards
- Only uses og:image from OG tags
- Test with Card Validator
Testing & Verification
Always test your OG tags:
- Use the Facebook Sharing Debugger
- Check LinkedIn Post Inspector
- Share in Discord (real-time preview)
Common Patterns
Blog Posts
useSeoMeta({
ogType: 'article',
author: 'Harlan Wilton',
// open graph
articleAuthor: ['Harlan Wilton'],
articleSection: 'SEO Tutorials for Vue and Nuxt',
articleTag: page.value.keywords,
articlePublishedTime,
articleModifiedTime,
// slack unfurling
twitterData1: 'Harlan Wilton',
twitterLabel1: 'Author',
twitterData2: page.value.readTime,
twitterLabel2: 'Read Time',
})