json ld.md

How to add JSON-LD structured data to your website

JSON-LD (JavaScript Object Notation for Linked Data) is the format Google, Bing, and other search engines use to understand your page content. agentmarkup injects schema.org JSON-LD into your HTML pages at build time for Vite, Astro, Next.js, and Nuxt (and via the CLI for any other static build) with XSS-safe serialization and type-safe presets.

In simple terms

Beginner to intermediate Website owners and people who build websites
About 10 minutes

Structured data is a clear label attached to a page: this is a product, an article, a company, or a frequently asked question. It helps search and AI systems interpret the page without guessing.

Check your structured information

What is JSON-LD structured data?

Structured data tells search engines exactly what your page is about. Instead of guessing from HTML content, search engines read your JSON-LD and understand that a page is a Product with a price, an Article with a publish date, or an Organization with a logo.

This powers rich results in Google Search, including star ratings, FAQ dropdowns, product cards, and knowledge panels. Without structured data, search engines can only guess at your page content.

Built-in schema.org presets

agentmarkup includes 6 type-safe presets for common structured data types. Each preset validates required fields at build time and generates spec-compliant JSON-LD.

Preset Schema type Use case
webSite WebSite Site-level schema with optional search action
organization Organization Company or brand identity
article Article Blog posts, news, content pages
faqPage FAQPage Question and answer pages
product Product E-commerce product pages
offer Offer Pricing and availability

Using presets

Apply schemas globally (every page) or per-page. Global schemas like webSite and organization go in globalSchemas. Page-specific schemas go in pages. The schema config is adapter-agnostic, so the same object works with @agentmarkup/vite, @agentmarkup/astro, and @agentmarkup/next.

const agentmarkupConfig = {
  site: 'https://myshop.com',
  name: 'My Shop',
  globalSchemas: [
    { preset: 'webSite', name: 'My Shop', url: 'https://myshop.com' },
    { preset: 'organization', name: 'My Shop', url: 'https://myshop.com', logo: '/logo.png' },
  ],
  pages: [
    {
      path: '/faq',
      schemas: [{
        preset: 'faqPage',
        url: 'https://myshop.com/faq',
        questions: [
          { question: 'Do you ship internationally?', answer: 'Yes, to 50+ countries.' },
        ],
      }],
    },
  ],
}

Framework wrappers

After defining the shared schema config, pass it into the adapter for the framework that owns your final output:

// Vite
import { defineConfig } from 'vite'
import { agentmarkup } from '@agentmarkup/vite'

export default defineConfig({
  plugins: [agentmarkup(agentmarkupConfig)],
})

// Astro
import { defineConfig } from 'astro/config'
import { agentmarkup } from '@agentmarkup/astro'

export default defineConfig({
  integrations: [agentmarkup(agentmarkupConfig)],
})

// Next.js
import type { NextConfig } from 'next'
import { withAgentmarkup } from '@agentmarkup/next'

const nextConfig: NextConfig = {
  output: 'export',
}

export default withAgentmarkup(agentmarkupConfig, nextConfig)

// Nuxt
export default defineNuxtConfig({
  modules: ['@agentmarkup/nuxt'],
  agentmarkup: agentmarkupConfig,
})

// CLI (any other built static site)
// agentmarkup generate ./dist

Custom schemas

You can use any schema.org type by passing an object with an @type field. agentmarkup automatically adds the @context and handles serialization.

pages: [
  {
    path: '/products/wallets',
    schemas: [{
      '@type': 'Product',
      name: 'Classic Leather Wallet',
      description: 'Full-grain leather bifold wallet.',
      image: 'https://myshop.com/images/wallet.jpg',
      sku: 'WALLET-001',
      offers: {
        '@type': 'Offer',
        price: '89',
        priceCurrency: 'USD',
        availability: 'https://schema.org/InStock',
      },
    }],
  },
]

XSS-safe output

agentmarkup escapes dangerous characters (<, >, &, ') to unicode escapes before injecting JSON-LD into HTML. This prevents XSS attacks through structured data injection.

<script type="application/ld+json">
{"@context":"https://schema.org","@type":"WebSite","name":"My Shop","url":"https://myshop.com"}
</script>

Build-time validation

Every schema is validated during build. Missing required fields produce errors. Missing recommended fields produce warnings. You see exactly what needs fixing in your terminal before deploying.

Combined with llms.txt generation, markdown mirrors, and AI crawler management, this gives your website a fuller machine-readable surface instead of relying on structured data alone.

Frequently asked questions

Do I need JSON-LD if I already have meta tags?
Yes. Meta tags (title, description) help search engines understand a single page. JSON-LD tells them what kind of thing the page represents (a product, an article, an FAQ) with structured fields they can use for rich results.

Can I add multiple schemas to one page?
Yes. Use the pages config to add multiple schemas per path. Each schema generates its own <script type="application/ld+json"> tag. Global schemas are also added to every page.

What if I need a schema type that is not a preset?
Pass any object with an @type field. agentmarkup will add @context automatically and serialize it safely. Presets just save you from remembering required fields.