---
title: "Add JSON-LD Structured Data in Vue"
description: "Learn how to implement Schema.org structured data in Vue using Unhead. Get rich results in Google search with type-safe JSON-LD markup."
canonical_url: "https://nuxtseo.com/learn-seo/vue/mastering-meta/schema-org"
last_updated: "2026-01-29"
---

<key-takeaways>

- Install `@unhead/schema-org` manually in Vue (Nuxt SEO includes it automatically)
- JSON-LD is Google's recommended format for structured data
- Use `useSchemaOrg()` for type-safe markup with automatic graph linking

</key-takeaways>

Schema.org structured data helps Google display [Rich Results](https://developers.google.com/search/docs/appearance/structured-data/search-gallery): stars, FAQs, recipes, product prices. In Vue, you need to install `@unhead/schema-org` separately and configure it in your app entry point. Nuxt SEO handles this automatically, but Vue developers wire up the schema org plugin manually. Rotten Tomatoes saw a [25% higher click-through rate](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data) on pages with structured data compared to pages without.

```html
<!-- JSON-LD structured data in the head -->
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "Add JSON-LD Structured Data in Vue",
  "author": { "@type": "Person", "name": "Your Name" }
}
</script>
```

Google [recommends JSON-LD](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data) as the easiest format to implement and maintain. Google supports rich results for many schema types including Article, Product, FAQ, and Breadcrumb. See [Rich Results](/learn-seo/vue/mastering-meta/rich-results) for the full list of active types and eligibility details.

Rich results aren't guaranteed. Content must match the markup and follow [Google's structured data guidelines](https://developers.google.com/search/docs/appearance/structured-data/sd-policies).

## Setup with Unhead

Vue uses [Unhead](https://unhead.unjs.io/) for head management. You can add JSON-LD via `useHead()`, but `useSchemaOrg()` from `@unhead/schema-org` provides type safety and automatic [graph linking](https://schema.org/docs/data-and-datasets.html).

```bash
pnpm add -D @unhead/schema-org
```

See [Unhead Schema.org setup](https://unhead.unjs.io/schema-org/getting-started/setup) for full install instructions.

<code-group>

```ts [useSchemaOrg (recommended)]
import { defineArticle, useSchemaOrg } from '@unhead/schema-org/vue'

useSchemaOrg([
  defineArticle({
    headline: 'Add JSON-LD Structured Data in Vue',
    author: { name: 'Your Name' },
    datePublished: new Date(2024, 0, 15),
  })
])
```

```ts [useHead (manual)]
useHead({
  script: [
    {
      type: 'application/ld+json',
      innerHTML: JSON.stringify({
        '@context': 'https://schema.org',
        '@type': 'Article',
        'headline': 'Add JSON-LD Structured Data in Vue',
        'author': { '@type': 'Person', 'name': 'Your Name' }
      })
    }
  ],
})
```

</code-group>

The `defineX()` helpers align with [Google's Structured Data Guidelines](https://developers.google.com/search/docs/guides/sd-policies) and handle boilerplate:

<table>
<thead>
  <tr>
    <th>
      Helper
    </th>
    
    <th>
      Rich Result Type
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <a href="https://unhead.unjs.io/schema-org/schema/article" rel="nofollow">
        <code className="language-ts shiki shiki-themes github-light github-light material-theme-palenight" language="ts" style="">
          <span class="s0YkB">
            defineArticle
          </span>
          
          <span class="sqjlB">
            ()
          </span>
        </code>
      </a>
    </td>
    
    <td>
      Article, NewsArticle, BlogPosting
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="https://unhead.unjs.io/schema-org/schema/breadcrumb" rel="nofollow">
        <code className="language-ts shiki shiki-themes github-light github-light material-theme-palenight" language="ts" style="">
          <span class="s0YkB">
            defineBreadcrumb
          </span>
          
          <span class="sqjlB">
            ()
          </span>
        </code>
      </a>
    </td>
    
    <td>
      Breadcrumb navigation
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="https://unhead.unjs.io/schema-org/schema/question" rel="nofollow">
        <code className="language-ts shiki shiki-themes github-light github-light material-theme-palenight" language="ts" style="">
          <span class="s0YkB">
            defineQuestion
          </span>
          
          <span class="sqjlB">
            ()
          </span>
        </code>
      </a>
    </td>
    
    <td>
      FAQ pages (Gov/Health only)
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="https://unhead.unjs.io/schema-org/schema/product" rel="nofollow">
        <code className="language-ts shiki shiki-themes github-light github-light material-theme-palenight" language="ts" style="">
          <span class="s0YkB">
            defineProduct
          </span>
          
          <span class="sqjlB">
            ()
          </span>
        </code>
      </a>
    </td>
    
    <td>
      Product listings
    </td>
  </tr>
</tbody>
</table>

## Reactive Data

`useSchemaOrg()` accepts refs and computed getters:

```vue
<script setup lang="ts">
import { defineArticle, useSchemaOrg } from '@unhead/schema-org/vue'
import { ref } from 'vue'

const article = ref({
  title: 'My Article',
  description: 'Article description'
})

useSchemaOrg([
  defineArticle({
    headline: () => article.value.title,
    description: () => article.value.description,
  })
])
</script>
```

## Entity Linking (The Knowledge Graph)

In 2026, Google prioritizes "Entity SEO" understanding relationships between things. Instead of nesting everything deep inside one object, use `@id` to link separate nodes.

`useSchemaOrg()` handles this automatically when you use the same `@id` reference, or you can link them manually:

```vue
<script setup lang="ts">
import { defineArticle, definePerson, useSchemaOrg } from '@unhead/schema-org/vue'

useSchemaOrg([
  // 1. Define the Person separately
  definePerson({
    '@id': '#harlan', // Unique ID
    'name': 'Harlan Wilton',
    'jobTitle': 'Open Source Developer'
  }),
  // 2. Link the Article to the Person via ID
  defineArticle({
    headline: 'Advanced Schema Patterns',
    author: { '@id': '#harlan' } // Links to the node above
  })
])
</script>
```

This creates a clean, interconnected graph that helps AI understand your content's authority.

## Site-Wide Setup

Set up base schema in your root component. Child components can add specific types that link to this graph automatically.

```vue [app.vue]
<script lang="ts" setup>
import { defineOrganization, defineWebPage, defineWebSite, useSchemaOrg } from '@unhead/schema-org/vue'

const route = useRoute()
useHead({
  templateParams: {
    schemaOrg: {
      host: 'https://mysite.com',
      path: route.path,
      inLanguage: 'en',
    }
  }
})

useSchemaOrg([
  defineWebPage(),
  defineWebSite({
    name: 'My Site',
    description: 'What my site does.',
  }),
  // Use defineOrganization for businesses, definePerson for personal sites
  defineOrganization({
    name: 'My Company',
    logo: '/logo.png',
  })
])
</script>
```

## Blog Article Example

Vue's hierarchical head system means you don't need to repeat `WebSite` and `WebPage` if they're in the layout:

```vue [blog/[slug].vue]
<script lang="ts" setup>
import { defineArticle, useSchemaOrg } from '@unhead/schema-org/vue'

const article = await fetchArticle()

useSchemaOrg([
  defineArticle({
    headline: article.title,
    image: article.image,
    datePublished: article.publishedAt,
    dateModified: article.updatedAt,
    author: {
      name: article.author.name,
      url: article.author.url,
    }
  })
])
</script>
```

## Testing Your Markup

Validate your markup with [Google's Rich Results Test](https://search.google.com/test/rich-results). For a full testing workflow, see [Rich Results](/learn-seo/vue/mastering-meta/rich-results#testing-your-markup).

## Using Nuxt?

Nuxt SEO handles Schema.org [automatically](/docs/schema-org/getting-started/introduction) with zero config. See the [Nuxt Schema.org guide](/learn-seo/nuxt/mastering-meta/schema-org) for the Nuxt-specific approach.
