# Missing structured data (JSON-LD)

> Answer engines extract facts from schema.org JSON-LD. Without it they guess from prose. Add JSON-LD so AI and Google read your page correctly.

_Category: AI readiness · Detector `aeo` · Check `structured-data-missing` · Severity: warning_

Answer engines and rich-result crawlers pull entities, facts, and answers out of `schema.org` `JSON-LD` — an author, a price, a rating, a FAQ. Without it they fall back to guessing from your prose, which is lossy and easy to get wrong. As AI assistants become how people find things, a page with no machine-readable summary is one they’re more likely to skip or misquote.

## Symptoms

- No rich results (FAQ, breadcrumb, product, article) in Google
- AI assistants summarise the page inaccurately or not at all
- Google’s Rich Results Test reports "No items detected"
- Competitors with the same content show richer search snippets

## How VibeCheck detects it

The `aeo` detector flags this live in the browser and reports it to the widget's Problems list — and to your coding agent over MCP.

- **Issue string:** `No structured data (JSON-LD)`
- **Threshold:** No <script type="application/ld+json"> present on the page

## Root causes

- No `JSON-LD` was ever added to the templates
- Relying on Open Graph/meta tags alone, which don’t describe entities
- A CMS or generator that outputs prose but no schema

## The fix

Add a `<script type="application/ld+json">` describing the page with the `schema.org` type that fits — `Article`/`TechArticle` for content, `Product` for a product, `FAQPage` for a Q&A, `Organization` for the site. Include a `@context` of `https://schema.org` and the fields relevant to that type.

### Steps

1. Pick the `schema.org` type that matches the page (`Article`, `Product`, `FAQPage`, …)
2. Emit a `JSON-LD` script with `@context` `"https://schema.org"` and the key fields
3. Validate with Google’s Rich Results Test and `schema.org` validator

_A minimal Article JSON-LD_

```html
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "How to fix cumulative layout shift",
  "author": { "@type": "Person", "name": "Jane Dev" },
  "datePublished": "2026-01-15"
}
</script>
```

## Framework-specific fixes

### React

In React 19 a `<script>` in your component is hoisted correctly, but for crawlers that don’t run JS you should render it during SSR/prerender. Stringify the object rather than hand-writing JSON.

```tsx
const jsonLd = { '@context': 'https://schema.org', '@type': 'Article', headline: title }
return <script type="application/ld+json">{JSON.stringify(jsonLd)}</script>
```

### Next.js

Render the `JSON-LD` as a `<script>` in the component tree (Server Component). Next streams it into the HTML so crawlers see it without running JS. Build the object in TypeScript and stringify it.

```tsx
export default function Page() {
  const jsonLd = {
    '@context': 'https://schema.org',
    '@type': 'Article',
    headline: 'How to fix CLS',
  }
  return (
    <>
      <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
      <article>…</article>
    </>
  )
}
```

[Next.js docs](https://nextjs.org/docs/app/guides/json-ld)

### Vue

Inject the script with `@unhead/vue`’s `useHead` so it lands in `<head>` during SSR.

```vue
<script setup lang="ts">
import { useHead } from '@unhead/vue'
useHead({
  script: [{ type: 'application/ld+json', innerHTML: JSON.stringify({
    '@context': 'https://schema.org', '@type': 'Article', headline: 'How to fix CLS',
  }) }],
})
</script>
```

[Vue docs](https://unhead.unjs.io/)

### Svelte

Place the `JSON-LD` in `<svelte:head>`; SvelteKit renders it server-side so crawlers see it.

```svelte
<svelte:head>
  {@html '<script type="application/ld+json">' + JSON.stringify(jsonLd) + '<\/script>'}
</svelte:head>
```

### Vanilla JS

Emit the script directly in server-rendered HTML (or static HTML). Keep it in the markup so non-JS crawlers read it.

```html
<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "Organization", "name": "Acme", "url": "https://acme.com" }
</script>
```

## FAQ

### Which `schema.org` type should I use?

Match the page: `Article`/`TechArticle`/`BlogPosting` for content, `Product` for a product, `FAQPage` for Q&A, `Organization`/`WebSite` for the site itself. You can include several types on one page.

### Does `JSON-LD` help with AI answer engines specifically?

Yes. Assistants like ChatGPT, Perplexity, and Google’s AI Overviews extract structured facts far more reliably than prose. Clean `JSON-LD` makes your page easier to cite accurately.

### `JSON-LD`, Microdata, or RDFa?

Google recommends `JSON-LD` — it’s a single script block separate from your markup, so it’s the easiest to add and maintain, and it’s what VibeCheck checks for.

## Related problems

- [Invalid structured data (JSON-LD)](https://vibecheck.wcgw.fun/fix/invalid-structured-data.md) — AI readiness
- [Missing author and date signals](https://vibecheck.wcgw.fun/fix/missing-author-metadata.md) — AI readiness
- [Missing meta description](https://vibecheck.wcgw.fun/fix/missing-meta-description.md) — Search visibility
- [Content only renders with JavaScript](https://vibecheck.wcgw.fun/fix/content-requires-javascript.md) — AI readiness

---

Fix guide from VibeCheck — https://vibecheck.wcgw.fun/fix/missing-structured-data. Full site index for LLMs: https://vibecheck.wcgw.fun/llms.txt
