---
title: "Vue SEO Meta Tags Guide"
description: "Set titles, descriptions, Open Graph, and Schema.org in Vue 3 with @unhead/vue, since Vue needs manual setup Nuxt gives you for free."
canonical_url: "https://nuxtseo.com/learn-seo/vue/mastering-meta"
last_updated: "2026-07-16"
---

<key-takeaways>

- Install `@unhead/vue` manually in Vue (Nuxt includes it automatically)
- Use `useSeoMeta()` from @unhead/vue for type-safe meta tag management
- Meta tags must render server-side; client only SPAs show empty `<head>` to crawlers
- Twitter, Slack, and [LinkedIn](https://linkedin.com) all use Open Graph tags, so you only need to set `twitterCard` separately

</key-takeaways>

A client-rendered Vue SPA ships an empty `<head>` in its initial HTML response; meta tags only exist once JavaScript runs, and AI crawlers like GPTBot never run it. Unlike Nuxt, which integrates Unhead automatically, Vue requires you to [install and configure @unhead/vue manually](https://unhead.unjs.io/docs/vue/head/guides/get-started/installation) in your `main.ts`. This guide covers SSR-compatible patterns using [Unhead](https://unhead.unjs.io/).

```html
<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:

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

## What Meta Tags Control

<table>
<thead>
  <tr>
    <th>
      Meta Tag
    </th>
    
    <th>
      Used By
    </th>
    
    <th>
      Purpose
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <a href="/learn-seo/vue/mastering-meta/titles">
        <code className="language-html shiki shiki-themes github-light github-light material-theme-palenight" language="html" style="">
          <span class="sx-uw">
            <
          </span>
          
          <span class="sV-QU">
            title
          </span>
          
          <span class="sx-uw">
            >
          </span>
        </code>
      </a>
    </td>
    
    <td>
      Search engines, browsers
    </td>
    
    <td>
      Page title in search results and browser tab
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="/learn-seo/vue/mastering-meta/descriptions">
        <code className="language-html shiki shiki-themes github-light github-light material-theme-palenight" language="html" style="">
          <span class="sx-uw">
            <
          </span>
          
          <span class="sV-QU">
            meta
          </span>
          
          <span class="sg-iE">
            name
          </span>
          
          <span class="sx-uw">
            =
          </span>
          
          <span class="sbw7o">
            "
          </span>
          
          <span class="sJnJ8">
            description
          </span>
          
          <span class="sbw7o">
            "
          </span>
          
          <span class="sx-uw">
            >
          </span>
        </code>
      </a>
    </td>
    
    <td>
      Search engines
    </td>
    
    <td>
      Snippet text in search results (<a href="https://ahrefs.com/blog/meta-description-study/" rel="nofollow">
        Google rewrites ~63%
      </a>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="/learn-seo/vue/mastering-meta/social-sharing">
        <code className="language-html shiki shiki-themes github-light github-light material-theme-palenight" language="html" style="">
          <span class="sx-uw">
            <
          </span>
          
          <span class="sV-QU">
            meta
          </span>
          
          <span class="sg-iE">
            property
          </span>
          
          <span class="sx-uw">
            =
          </span>
          
          <span class="sbw7o">
            "
          </span>
          
          <span class="sJnJ8">
            og:*
          </span>
          
          <span class="sbw7o">
            "
          </span>
          
          <span class="sx-uw">
            >
          </span>
        </code>
      </a>
    </td>
    
    <td>
      Facebook, LinkedIn, Discord, Slack
    </td>
    
    <td>
      Link preview cards
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="/learn-seo/vue/mastering-meta/social-sharing">
        <code className="language-html shiki shiki-themes github-light github-light material-theme-palenight" language="html" style="">
          <span class="sx-uw">
            <
          </span>
          
          <span class="sV-QU">
            meta
          </span>
          
          <span class="sg-iE">
            name
          </span>
          
          <span class="sx-uw">
            =
          </span>
          
          <span class="sbw7o">
            "
          </span>
          
          <span class="sJnJ8">
            twitter:*
          </span>
          
          <span class="sbw7o">
            "
          </span>
          
          <span class="sx-uw">
            >
          </span>
        </code>
      </a>
    </td>
    
    <td>
      Twitter/X
    </td>
    
    <td>
      Tweet cards (falls back to OG tags)
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="/learn-seo/vue/mastering-meta/schema-org">
        <code className="language-html shiki shiki-themes github-light github-light material-theme-palenight" language="html" style="">
          <span class="sx-uw">
            <
          </span>
          
          <span class="sV-QU">
            script
          </span>
          
          <span class="sg-iE">
            type
          </span>
          
          <span class="sx-uw">
            =
          </span>
          
          <span class="sbw7o">
            "
          </span>
          
          <span class="sJnJ8">
            application/ld+json
          </span>
          
          <span class="sbw7o">
            "
          </span>
          
          <span class="sx-uw">
            >
          </span>
        </code>
      </a>
    </td>
    
    <td>
      Search engines
    </td>
    
    <td>
      Rich results (stars, recipes, products)
    </td>
  </tr>
</tbody>
</table>

### Search Engine Tags

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

- [**Page Titles**](/learn-seo/vue/mastering-meta/titles): Your main call-to-action in search results. Keep under 60 characters.
- [**Meta Descriptions**](/learn-seo/vue/mastering-meta/descriptions): The snippet below your title. Google rewrites most of them, but write them anyway for the ones it keeps as-is.
- [**Image Alt Text**](/learn-seo/vue/mastering-meta/alt-text): Alt text for accessibility, Google Images ranking, and AI understanding. The #1 accessibility failure on the web.

### Social Sharing Tags

These control link previews when someone shares your URL.

- [**Social Sharing**](/learn-seo/vue/mastering-meta/social-sharing): Open Graph (Facebook, LinkedIn, Discord, Slack) and Twitter Cards in one guide. Set `og:title`, `og:description`, `og:image`, and `twitterCard`.

### Structured Data

- [**Schema.org**](/learn-seo/vue/mastering-meta/schema-org): JSON-LD markup for rich results. Overkill for most sites, but useful for recipes, products, events.

Migrating from vue-meta? It was the Vue 2 standard but never shipped Vue 3 support. See [Migrating from vue-meta](/learn-seo/vue/mastering-meta/migrating-vue-meta) for side-by-side syntax and migration steps.

## Quick Setup

Most sites need this:

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

Then set per-page meta using the patterns described in each guide below.

## 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.

## Performance & Scripts

Meta tags are fast, but third-party scripts (analytics, ads) hurt performance. A blocked main thread delays Interaction to Next Paint (INP), a Core Web Vital Google's ranking systems use as a tiebreaker between similarly relevant pages.

Use Unhead's [`useScript()`](https://unhead.unjs.io/docs/head/api/composables/use-script) to load third-party scripts without blocking the main thread:

```ts
import { useScript } from '@unhead/vue'

// Loads Google Analytics lazily, improving initial load
useScript({
  src: 'https://www.googletagmanager.com/gtag/js?id=G-cwv',
  async: true,
  defer: true,
})
```

## Common Mistakes

**Forgetting absolute URLs for images**: OG images require absolute URLs. See [Social Sharing](/learn-seo/vue/mastering-meta/social-sharing) for details.

**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 with the tools listed in each guide below.

[Start with Page Titles →](/learn-seo/vue/mastering-meta/titles)

Using Nuxt instead of plain Vue? [Nuxt SEO](/docs/nuxt-seo/getting-started/introduction) handles meta tags automatically. See the [Nuxt meta tags guide](/learn-seo/nuxt/mastering-meta) for the framework-specific setup.
