Обсудить задачу

Как настроить структурированные данные на headless-сайте

Структурированные данные на headless-сайте настраиваются вручную: блок application/ld+json собирается из данных фронтматтера или CMS и рендерится на сервере вместе со страницей. В отличие от WordPress, где плагины вроде Yoast генерируют разметку автоматически, headless-стек такого слоя не имеет по умолчанию - его встраивают в шаблоны самостоятельно. Дальше - какие типы разметки нужны B2B-сайту и как их реализовать в Astro и Next.js.

В проектах миграции с WordPress на headless-стек мы регулярно видим одну и ту же картину: разработчик переносит контент, вёрстку и скорость загрузки, а про разметку вспоминает только тогда, когда рич-сниппеты в выдаче исчезают. Плагин, который годами генерировал разметку организации, статьи и хлебных крошек, остаётся в старой CMS - новый сайт на Astro или Next.js про Schema.org и JSON-LD ничего не знает, пока их не добавят руками.

Дальше - что именно даёт структурированная разметка в поиске и в AI-ответах, какие типы схемы нужны маркетинговому B2B-сайту, как собрать JSON-LD из данных шаблона в Astro и Next.js, и как проверить, что разметка действительно работает.

Без структурированных данных поисковая система всё равно проиндексирует страницу, но получит только заголовок и текст - без явного указания, что это статья, у какой организации, с какими вопросами в FAQ. Google не покажет расширенный сниппет, AI-системы вроде ChatGPT и Perplexity с меньшей вероятностью процитируют страницу как источник, а хлебные крошки в выдаче останутся обычным URL вместо читаемого пути. Для B2B-сайта это означает более низкий CTR в выдаче и отсутствие в блоках FAQ или How-to, даже если контент отвечает на вопрос лучше конкурентов.

Структурированные данные (Schema.org): стандартизированный словарь тегов, разработанный Google, Microsoft, Yahoo и Яндексом, который описывает содержимое страницы в формате, понятном поисковым системам и AI-агентам.

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

Что структурированные данные дают вашему сайту в поиске и в AI-ответах

Разметка не меняет то, что видит посетитель на странице - она добавляет машиночитаемый слой рядом с обычным HTML. Поисковая система читает этот слой и решает, показывать ли расширенный результат выдачи вместо обычной синей ссылки.

Практический эффект - это rich results: рейтинг со звёздами у отзывов, раскрывающийся список вопросов у FAQ-страницы, нумерованные шаги у инструкции, хлебные крошки вместо URL. Google формирует эти блоки только из данных, размеченных по словарю Schema.org - без разметки страница остаётся обычной ссылкой, даже если содержание объективно лучше.

Второй эффект относится к AI-поиску. ChatGPT, Perplexity и Google AI Overviews собирают ответ из фрагментов страниц, и явно размеченный факт - автор, дата публикации, структура вопрос-ответ - извлекается точнее и с большей вероятностью попадает в цитируемый источник, чем тот же факт, растворённый в сплошном тексте.

Почему headless-платформа не настраивает разметку сама

На WordPress разметку почти всегда генерирует плагин SEO-пакета: он читает заголовок, автора и дату публикации из базы данных и сам собирает JSON-LD при каждом рендере страницы. Разработчик ничего не пишет вручную - и ровно поэтому команда, переезжающая на headless-стек, часто вообще не вспоминает об этом шаге до релиза.

В headless-архитектуре подобного автоматического слоя нет ни в Astro, ни в Next.js, ни в других SSR- и SSG-фреймворках - оба фреймворка отдают HTML и данные, а какую разметку добавить в <head>, решает команда. Это не недостаток архитектуры, а прямое следствие того, что headless-стек не диктует, откуда берутся заголовок и дата статьи: из фронтматтера Markdown-файла, из Headless CMS или из базы данных - в каждом случае схему данных нужно собрать самостоятельно.

С тем же паттерном сайт уже сталкивается при настройке hreflang для мультиязычной версии: WordPress-плагины вроде WPML собирают альтернативные языковые версии автоматически, а на headless-стеке разработчик прописывает теги вручную в каждом шаблоне. Структурированные данные - тот же класс задачи: SEO-слой, который раньше был скрыт внутри плагина, теперь становится частью кода сайта.

Какие типы разметки нужны B2B-сайту

Не любой тип схемы из каталога Schema.org одинаково полезен маркетинговому сайту. Для B2B-проекта на headless-стеке практический смысл имеют шесть типов:

  • Organization - название компании, логотип, ссылки на социальные сети и контакты. Ставится один раз глобально, обычно в общем layout-компоненте, и участвует в Knowledge Panel Google.
  • BreadcrumbList - иерархия страницы относительно раздела сайта. Превращает URL в выдаче в читаемую цепочку разделов и облегчает роботу понимание структуры сайта.
  • Article или BlogPosting - заголовок, автор, дата публикации и обновления материала. Основной тип для блога и кейсов, обязателен на каждой публикации.
  • FAQPage - список вопросов и ответов на странице. Даёт раскрывающийся блок прямо в выдаче и один из самых надёжных источников цитирования в AI-поиске.
  • HowTo - пошаговая инструкция с явно перечисленными шагами. Уместен для гайдов и туториалов, где есть последовательность конкретных действий.
  • Product - актуален только для сайтов с e-commerce: цена, наличие, рейтинг товара. Маркетинговому B2B-сайту без витрины товаров этот тип обычно не нужен.

Ставить сразу все шесть типов на одну страницу не нужно - схема должна отражать реальный тип контента: у статьи блога это BlogPosting плюс BreadcrumbList, у страницы с вопросами - FAQPage, у гайда с шагами - HowTo.

Как реализовать JSON-LD в Astro

В Astro разметку удобно вынести в один переиспользуемый компонент, который принимает объект данных и рендерит его как блок <script>. Сама схема при этом собирается из тех же данных, что уже есть во фронтматтере статьи или в Content Collections - дублировать данные вручную не приходится.

Компонент JsonLd.astro
---
interface Props {
  data: Record<string, unknown>;
}
const { data } = Astro.props;
---
<script type="application/ld+json" set:html={JSON.stringify(data)} />

Использование компонента в шаблоне статьи блога выглядит как сборка обычного объекта из уже существующих полей фронтматтера:

Пример для шаблона статьи блога
---
import JsonLd from '../components/JsonLd.astro';
const { title, publishedAt, updatedAt, description } = Astro.props;

const articleSchema = {
  '@context': 'https://schema.org',
  '@type': 'BlogPosting',
  headline: title,
  datePublished: publishedAt,
  dateModified: updatedAt,
  description,
  author: {
    '@type': 'Organization',
    name: 'Exceltic.dev',
  },
};
---
<JsonLd data={articleSchema} />

Тот же принцип масштабируется на FAQPage: вопросы и ответы уже существуют в тексте статьи как заголовки ### Вопрос? с ответом сразу под ними, и схема собирается парсингом этой же секции на этапе сборки - без отдельного источника данных, который придётся поддерживать вручную.

В типовом проекте миграции с WordPress на Astro для B2B-сайта из 30-50 страниц компонент разметки, покрывающий Organization, BreadcrumbList и BlogPosting, занимает разработчику 3-5 часов - вместе с подключением к существующим данным фронтматтера. Отдельная задача - перенести FAQPage и HowTo туда, где в контенте реально есть вопросы или пошаговые инструкции, это не требует нового компонента, только другого набора полей на входе.

Как перенести тот же подход на Next.js

Принцип в Next.js идентичен: схема собирается как обычный JavaScript-объект и рендерится внутри <script type="application/ld+json"> через dangerouslySetInnerHTML. Разница только в синтаксисе компонента - React вместо .astro-файла.

Компонент ArticleJsonLd для App Router
export function ArticleJsonLd({ post }: { post: Post }) {
  const schema = {
    '@context': 'https://schema.org',
    '@type': 'BlogPosting',
    headline: post.title,
    datePublished: post.publishedAt,
    dateModified: post.updatedAt,
    description: post.description,
  };

  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
    />
  );
}

Компонент подключается в layout.tsx или прямо в page.tsx рядом с вызовом встроенного Metadata API, который отвечает за title и meta-теги, но не генерирует JSON-LD сам по себе - схему разметки Metadata API не покрывает, её всегда добавляют отдельным компонентом. Разбор того, чем в целом отличается рендеринг данных в Astro и Next.js, если команда ещё выбирает между фреймворками, - в статье Astro Islands vs Next.js Server Components.

Как проверить что разметка работает

Валидность JSON-LD стоит проверять до релиза, а не после того, как рич-сниппет не появился в выдаче. Google даёт для этого инструмент Rich Results Test: он показывает, какие типы разметки Google распознал на странице и какие поля считает обязательными, но отсутствующими.

Второй инструмент - Schema Markup Validator, независимый от Google валидатор, который проверяет соответствие разметки самому словарю Schema.org, а не только тому подмножеству типов, которое поддерживает конкретная поисковая система. Оба инструмента принимают либо готовый URL, либо вставленный вручную HTML-код - что удобно для проверки страницы ещё до деплоя, прямо из локальной сборки.

После первого деплоя разметки стоит вернуться в Rich Results Test через одну-две недели: Google не показывает расширенный сниппет мгновенно после появления валидной схемы, индексация и повторное сканирование страницы занимают время.

Частые ошибки при внедрении разметки

Три ошибки встречаются на headless-проектах чаще остальных, и все три не ловятся валидатором:

  • Разметка контента, которого нет на странице. Схема указывает рейтинг, цену или автора, которых пользователь не видит в интерфейсе - Google формально это не запрещает валидатором, но это прямое нарушение правил структурированных данных, за которое применяются ручные санкции.
  • Дублирующая или противоречащая разметка. Одна и та же страница получает два конфликтующих блока BlogPosting, например при переезде, когда старый компонент не удалили, а новый уже добавили - Google в таком случае может проигнорировать оба.
  • Устаревшая схема после правки контента. Дата обновления, заголовок или автор в JSON-LD не совпадают с текстом на странице, потому что схема собиралась один раз вручную, а не из тех же данных, что и остальной шаблон - собирать схему из единого источника данных, а не дублировать значения, снимает эту проблему целиком.

Кому это особенно важно

Разметка особенно ощутимо влияет на видимость у B2B-компаний с блогом и разделом кейсов - именно там играют роль BlogPosting и FAQPage, а конкуренция за featured snippet и AI-цитирование в нишевых B2B-запросах ниже, чем в массовых потребительских темах. Компаниям, которые только переезжают с WordPress на headless-стек, стоит закладывать разметку в план миграции с самого начала, а не добавлять её отдельным спринтом после релиза - тогда просадки в выдаче на переходный период вообще не будет.

Часто задаваемые вопросы

Что такое JSON-LD и чем он отличается от микроразметки в самом HTML?

JSON-LD - это отдельный блок JSON внутри тега <script type="application/ld+json">, который не встроен в видимую вёрстку страницы. Микроразметка через микроданные (itemprop, itemscope) добавляется прямо в HTML-теги контента и требует править саму разметку страницы при любом изменении схемы. Google официально рекомендует именно JSON-LD, потому что он проще генерируется программно и не ломает вёрстку при обновлении.

Нужна ли разметка Schema.org небольшому сайту с десятком страниц?

Да, но в ограниченном объёме. Даже небольшому сайту стоит добавить Organization на главной странице и BreadcrumbList на внутренних - это минимальный набор, который не требует поддержки данных сверх того, что уже есть в шаблоне. FAQPage и HowTo добавляются точечно там, где на странице реально есть вопросы или пошаговая инструкция, а не для всех страниц подряд.

Как часто нужно обновлять структурированные данные?

Разметку не нужно обновлять вручную отдельным действием, если она собирается программно из тех же данных, что и остальной контент страницы - дата обновления, заголовок или автор меняются один раз в источнике данных и автоматически попадают в схему при следующей сборке. Ручного обновления схема требует только в проектах, где JSON-LD прописан статично прямо в шаблоне, а не собирается из фронтматтера или CMS.

Можно ли использовать несколько типов схемы на одной странице?

Можно, и для статьи блога это обычная практика: BlogPosting и BreadcrumbList на одной странице не конфликтуют, потому что описывают разные аспекты страницы - контент и её место в структуре сайта. Проблема возникает не от количества типов, а от дублирования одного и того же типа схемы двумя независимыми блоками кода.

Влияет ли Schema.org напрямую на позиции сайта в поиске?

Напрямую - нет: Google неоднократно подтверждал, что валидная разметка сама по себе не поднимает страницу в ранжировании. Косвенное влияние ощутимее: расширенный сниппет с рейтингом или FAQ-блоком увеличивает CTR по клику из выдачи, а более точное машиночитаемое описание контента повышает шанс попасть в цитируемые источники AI-поиска - оба эффекта в итоге сказываются на трафике.

Если вы переезжаете с WordPress на headless-стек и не хотите терять рич-сниппеты на переходный период - заложите структурированные данные в план миграции заранее, а не отдельным спринтом после релиза. Три вещи стоит сделать в первую очередь: собрать Organization и BreadcrumbList в общий layout-компонент, подключить BlogPosting и FAQPage к данным, которые уже есть в шаблонах статей, и проверить обе схемы через Rich Results Test до деплоя, а не после.

Если сейчас проектируете архитектуру сайта с нуля или уже мигрировали на headless-стек без разметки - опишите задачу команде Exceltic.dev. Разберём, какие типы схемы нужны именно вашему контенту, и подключим их к существующим шаблонам.

Ещё статьи

Все →