Mastering Meta Tags in Vue

Meta tags tell search engines and social platforms what your page is about. Here's how to set them up properly in Vue.

Introduction

Meta tags are HTML elements that describe your page to machines. Search engines use them for rankings and snippets. Social platforms use them for link previews.

<head>
  <title>My Page · My Site</title>
  <meta name="description" content="What this page is about">
  <meta property="og:image" content="https://mysite.com/og.png">
</head>

In Vue, you manage these with useSeoMeta() or useHead() from @unhead/vue:

useSeoMeta({
  title: 'My Page',
  description: 'What this page is about',
  ogImage: 'https://mysite.com/og.png'
})

What Meta Tags Control

Meta TagUsed ByPurpose
<title>Search engines, browsersPage title in search results and browser tab
<meta name="description">Search enginesSnippet text in search results (Google rewrites ~70%)
<meta property="og:*">Facebook, LinkedIn, Discord, SlackLink preview cards
<meta name="twitter:*">Twitter/XTweet cards (falls back to OG tags)
<script type="application/ld+json">Search enginesRich results (stars, FAQs, recipes)

Search Engine Tags

These affect how your pages appear in Google, Bing, and other search results.

  • Page Titles - Your main call-to-action in search results. Keep under 60 characters.
  • Meta Descriptions - The snippet below your title. Google rewrites most of them, but write them anyway for the 30% that stick.

Social Sharing Tags

These control link previews when someone shares your URL.

  • Open Graph - The standard for Facebook, LinkedIn, Discord, and most platforms. Set og:title, og:description, og:image.
  • Twitter Cards - Twitter-specific tags. Falls back to Open Graph if not set, so often you don't need them.
  • Slack Unfurls - Slack uses Open Graph. Same tags, different quirks.

Structured Data

  • Schema.org - JSON-LD markup for rich results. Overkill for most sites, but useful for recipes, products, FAQs.

Quick Setup

Most sites need just this:

// app.vue or main component
useHead({
  title: 'My Site',
  titleTemplate: '%s · My Site',
})
useSeoMeta({
  ogSiteName: 'My Site',
  twitterCard: 'summary_large_image'
})

Then per-component:

<script setup lang="ts">
useSeoMeta({
  title: 'About Us',
  description: 'We build things.',
  ogImage: 'https://mysite.com/about-og.png'
})
</script>

That's it. Twitter falls back to OG tags. Slack uses OG tags. LinkedIn uses OG tags. Don't duplicate unless you need platform-specific content.

Priority Order

When tags conflict, here's what wins:

  1. Component-level useSeoMeta() in your component
  2. Parent component useSeoMeta() in your parent
  3. App-level setup in main.ts or app.vue

Unhead merges these automatically. Child component tags override parent tags.

Common Mistakes

Forgetting absolute URLs for images

// ❌ Won't work - relative path
ogImage: '/og.png'

// ✅ Works - absolute URL
ogImage: 'https://mysite.com/og.png'

Setting the same description everywhere

Each page needs a unique description. Template descriptions like "Welcome to {page}" are lazy and hurt click-through rates.

Ignoring the preview

Test your meta tags before deploying:

Start with Page Titles →

Using Nuxt?

If you're using Nuxt, check out Nuxt SEO which handles much of this automatically.

Learn more about Mastering Meta in Nuxt →