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, and Next.js with XSS-safe serialization and type-safe presets.

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.

PresetSchema typeUse case
webSiteWebSiteSite-level schema with optional search action
organizationOrganizationCompany or brand identity
articleArticleBlog posts, news, content pages
faqPageFAQPageQuestion and answer pages
productProductE-commerce product pages
offerOfferPricing 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)

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.

  • Required field errors: Product without name, Article without headline
  • Recommended field warnings: Organization without logo, Product without sku
  • Custom schema checks: Every custom schema must have an @type field

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.