---
title: "Add JSON-LD Structured Data in Vue · Nuxt SEO"
canonical_url: "https://nuxtseo.com/learn-seo/vue/mastering-meta/schema-org"
last_updated: "2026-07-16T12:00:00.000Z"
meta:
  author: "Harlan Wilton"
  description: "Add type-safe JSON-LD to a Vue app with @unhead/schema-org's useSchemaOrg, no Nuxt required."
  "og:description": "Add type-safe JSON-LD to a Vue app with @unhead/schema-org's useSchemaOrg, no Nuxt required."
  "og:title": "Add JSON-LD Structured Data in Vue · Nuxt SEO"
---

Nuxt SEO on GitHub

# **Add JSON-LD Structured Data in Vue**

Add type-safe JSON-LD to a Vue app with @unhead/schema-org's useSchemaOrg, no Nuxt required.

[Harlan Wilton](https://x.com/harlan-zw)8 mins read Published **Nov 5, 2024** Updated **Jul 16, 2026**

**What you'll learn**

- 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

[**~~Schema.org~~**](http://Schema.org) structured data helps Google display [**~~Rich Results~~**](https://developers.google.com/search/docs/appearance/structured-data/search-gallery): star ratings, recipe cards, and 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. Rotten Tomatoes added structured data to 100,000 pages and measured a [**~~25% higher click-through rate~~**](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data) compared to pages without it.

```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, and Breadcrumb. See [**~~Rich Results~~**](https://nuxtseo.com/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/docs/vue/schema-org/guides/get-started/installation) for full install instructions.

```ts
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),
  })
])
```

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

| **Helper** | **Rich Result Type** |
| --- | --- |
| [`**defineArticle()**`](https://unhead.unjs.io/docs/schema-org/api/schema/article) | Article, NewsArticle, BlogPosting |
| [`**defineBreadcrumb()**`](https://unhead.unjs.io/docs/schema-org/api/schema/breadcrumb) | Breadcrumb navigation |
| [`**defineQuestion()**`](https://unhead.unjs.io/docs/schema-org/api/schema/question) | FAQPage markup (no active rich result; [**~~retired May 2026~~**](https://www.searchenginejournal.com/google-drops-faq-rich-results-from-search/574429/)) |
| [`**defineProduct()**`](https://unhead.unjs.io/docs/schema-org/api/schema/product) | Product listings |

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

Instead of nesting everything inside one object, use `**@id**` to link separate nodes into a graph. `**useSchemaOrg()**` does this automatically when you reuse the same `**@id**`, or you can link nodes manually:

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

useSchemaOrg([
  // Define the Person separately
  definePerson({
    '@id': '#jane', // Unique ID
    'name': 'Jane Doe',
    'jobTitle': 'Editor',
  }),
  // Link the Article to the Person via ID
  defineArticle({
    headline: 'Advanced Schema Patterns',
    author: { '@id': '#jane' }, // Links to the node above
  }),
])
</script>
```

This produces one connected JSON-LD graph instead of duplicate, disconnected nodes.

## Site-Wide Setup

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

app.vue

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

blog/\[slug].vue

```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): it renders JavaScript, so it sees JSON-LD injected client-side. A plain `**curl**` request or "View Page Source" won't, since `**useSchemaOrg()**` writes the script tag after hydration in a client-only Vue app. For a full testing workflow, see [**~~Rich Results~~**](https://nuxtseo.com/learn-seo/vue/mastering-meta/rich-results#testing-your-markup).

## Checklist

**Checklist**

- Install `**@unhead/schema-org**` and configure it in your app entry point
- Set up base `**WebSite**`, `**WebPage**`, and `**Organization**`/ `**Person**` schema in your root component
- Add page-specific schema (Article, Product, Breadcrumb) with the `**defineX()**` helpers
- Link related entities with a shared `**@id**` instead of nesting duplicates
- Skip `**FAQPage**` markup if you're chasing a rich result: it no longer produces one
- Validate markup with Google's Rich Results Test

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

[**The 2026 SEO Checklist for Nuxt & Vue ** Pre-launch setup, post-launch verification, and ongoing monitoring. Interactive checklist with links to every guide.](https://nuxtseo.com/learn-seo/checklist) [Haven't launched yet? Start with the **Pre-Launch Warmup**](https://nuxtseo.com/learn-seo/pre-launch-warmup)

---

### **Related **

[**Rich Results in Vue**](https://nuxtseo.com/learn-seo/vue/mastering-meta/rich-results)

[**Social Sharing Tags**](https://nuxtseo.com/learn-seo/vue/mastering-meta/social-sharing)

[**Social Sharing** Set Open Graph and Twitter Card tags in Vue so links preview correctly on Facebook, X, LinkedIn, Slack, and Discord instead of plain text.](https://nuxtseo.com/learn-seo/vue/mastering-meta/social-sharing) [**Migrating vue-meta** Migrate from vue-meta to Unhead in Vue 3, with syntax mapping, breaking changes, and search-and-replace patterns.](https://nuxtseo.com/learn-seo/vue/mastering-meta/migrating-vue-meta)

**On this page**

- [Setup with Unhead](#setup-with-unhead)
- [Reactive Data](#reactive-data)
- [Entity Linking](#entity-linking)
- [Site-Wide Setup](#site-wide-setup)
- [Blog Article Example](#blog-article-example)
- [Testing Your Markup](#testing-your-markup)
- [Checklist](#checklist)