Возьми ту же карточку книги, что мы разметили микроданными в главе 2, и запиши её через JSON-LD:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Book",
  "name": "Мастер и Маргарита",
  "author": {
    "@type": "Person",
    "name": "Михаил Булгаков"
  },
  "publisher": "АСТ",
  "isbn": "978-5-17-090399-7"
}
</script>

Разметка полностью изолирована от HTML: отдельный блок <script type="application/ld+json">, обычный JSON внутри, никаких атрибутов на видимых тегах страницы. Ты меняешь дизайн, тег обёртки, шаблон вёрстки — разметка не ломается. Google с 2015 года рекомендует именно этот формат для новых проектов.

Синтаксис в двух ключевых полях

JSON-LD полагается на два спецполя, начинающихся с @:

  • "@context" — всегда "https://schema.org". Говорит парсеру: «все имена свойств и типов ниже трактуй по словарю Schema.org».
  • "@type" — имя типа Schema.org: Book, Article, Product, Event. Пишется без URL-префикса.

Остальные поля — имена свойств из типа: name, author, datePublished и т. д.

Вложенные типы

Если свойство типа — сама сущность (например, author у книги — это Person), в JSON-LD она записывается как вложенный объект со своим @type:

{
  "@context": "https://schema.org",
  "@type": "Book",
  "name": "Война и мир",
  "author": {
    "@type": "Person",
    "name": "Лев Толстой",
    "birthDate": "1828-09-09",
    "sameAs": "https://ru.wikipedia.org/wiki/Толстой,_Лев_Николаевич"
  },
  "publisher": {
    "@type": "Organization",
    "name": "АСТ",
    "url": "https://ast.ru"
  }
}

Вложенность неограниченная — сущности могут содержать другие сущности с ещё большим уровнем вложенности. На практике 2-3 уровня — норма, глубже редко нужно.

Множественные значения

Свойство может иметь одно или несколько значений. Одно — строка или объект. Несколько — массив. У книги может быть несколько авторов, у товара — несколько offers:

{
  "@type": "Book",
  "name": "Совместное сочинение",
  "author": [
    { "@type": "Person", "name": "Автор 1" },
    { "@type": "Person", "name": "Автор 2" }
  ]
}

{
  "@type": "Product",
  "name": "Наушники",
  "offers": [
    { "@type": "Offer", "price": "14990", "priceCurrency": "RUB", "seller": {"@type":"Organization","name":"Магазин 1"} },
    { "@type": "Offer", "price": "15990", "priceCurrency": "RUB", "seller": {"@type":"Organization","name":"Магазин 2"} }
  ]
}

Где ставить JSON-LD

Технически — в любом месте HTML-документа. По конвенции в <head> или в конце <body>. Оба варианта работают одинаково; поисковики парсят весь документ.

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <title>Мастер и Маргарита — купить книгу</title>
  <script type="application/ld+json">
    { "@context": "https://schema.org", "@type": "Book", ... }
  </script>
</head>
<body>
  <!-- обычный HTML страницы -->
</body>
</html>

На одной странице можно ставить несколько JSON-LD-блоков одновременно — например, разметка автора (Person) отдельно, разметка контента (Article) отдельно. Или разметка списка (ItemList) + разметка отдельных элементов внутри неё. Google находит все и обрабатывает.

Динамические страницы и SPA

Для одностраничных приложений (SPA) JSON-LD особенно удобен. При переходе на новый роут ты просто заменяешь содержимое <script type="application/ld+json"> через JavaScript — и разметка обновляется вместе с контентом:

function updateSchema(data) {
  let el = document.querySelector('script[type="application/ld+json"]');
  if (!el) {
    el = document.createElement('script');
    el.type = 'application/ld+json';
    document.head.appendChild(el);
  }
  el.textContent = JSON.stringify({
    "@context": "https://schema.org",
    "@type": "Product",
    ...data
  });
}

Google Search обрабатывает JavaScript при рендере страниц (через headless Chromium), поэтому такая динамическая разметка попадает в индекс. Правда, с некоторой задержкой — JS-render обычно медленнее HTML-render на 1-2 дня. Если критично — ставь JSON-LD в HTML на server-side render или в статике.

Преимущества JSON-LD над микроданными

Причины, почему Google рекомендует именно этот формат:

  • Разделение разметки и вёрстки. Дизайнер не сломает разметку, поменяв шаблон.
  • Легко шаблонизировать. В любом бэкенде (Next.js, Rails, Laravel, Django) блок JSON-LD генерируется одной функцией из объекта данных — без встраивания в HTML.
  • Работает в SPA. Динамическое обновление через JS не ломает страницу.
  • Читабельно. JSON проще для человеческого глаза, чем разбросанные itemprop на 10 тегах.
  • Валидируется чище. Rich Results Test и Schema Validator показывают ошибки JSON-LD точнее.

В новых проектах выбор очевидный. Микроданные остаются в двух нишах: legacy-код и минималистичные статичные страницы, где отдельный script-блок кажется overkill.