Сообщение отправлено.

Какая разметка schema.org нужна, чтобы цена и наличие попали в ответ ассистента?

На карточке товара нужен узел Product и Offer с полями price, priceCurrency и availability. Этот JSON-LD должен быть в HTML с сервера, а три значения — теми же, что в фиде. Цена, которая появляется только после JavaScript, не попала в HTML, который сохранил краулер.

Узлы на карточке

schema.org Product — это сам товар. schema.org Offer — коммерческие условия: цена, валюта и можно ли купить. schema.org AggregateRating — сводка отзывов, она необязательна.

Определения: https://schema.org/Product, https://schema.org/Offer и https://schema.org/AggregateRating. JSON-LD ставят в HTML адреса товара, не только на странице категории.

У Google отдельная проверка merchant listings: https://developers.google.com/search/docs/appearance/structured-data/merchant-listing и страница product snippet: https://developers.google.com/search/docs/appearance/structured-data/product. Это список, который Google проверяет сейчас. Это не обещание, что те же поля читают ChatGPT, Perplexity или Gemini.

На странице merchant listing обязательны Product.name, image и вложенный Offer, не AggregateOffer. У Offer цена больше нуля, в price или в priceSpecification.price, и парный priceCurrency. availability там рекомендован.

Offer: цена, валюта, наличие

price — сумма, которую платит покупатель, в основных единицах, с точкой. 18.00 — это восемнадцать, не одна тысяча восемьсот. Символ валюты внутрь price не кладут.

priceCurrency — код ISO 4217, например PLN, EUR или USD. Это отдельное поле. Пара — price 18.00 и priceCurrency PLN. Строка 18.00 PLN годится для файла фида, не для этих двух полей.

availability — это URL типа ItemAvailability. В наличии: https://schema.org/InStock. Нет в наличии: https://schema.org/OutOfStock. Предзаказ: https://schema.org/PreOrder. Ожидание поставки: https://schema.org/BackOrder. Используйте этот полный URL. Страница merchant listing у Google принимает и короткое имя InStock. Статус магазина instock — ни то ни другое.

url у Offer — карточка, с выбранным вариантом, если цена относится к одному варианту. itemCondition может быть https://schema.org/NewCondition, если товар новый. priceValidUntil необязателен и не заменяет обновление фида.

AggregateOffer с lowPrice и highPrice описывает диапазон. Он не говорит, какой вариант в наличии. Его используют, только если нужен диапазон. Для одного варианта — один Offer.

Product и AggregateRating

Product.name — название на странице. image — прямой URL картинки, его можно повторить. description — простой текст. sku — ваш идентификатор. brand — узел Brand с name или текст. offers указывает на Offer или на массив Offer, если вариантов несколько и каждый реально продаётся.

AggregateRating.ratingValue — среднее. reviewCount — сколько отзывов вошло в это среднее. ratingCount в schema.org тоже допустим как другой счётчик. bestRating по умолчанию 5, если поле опущено. Не отдавайте рейтинг, если отзывов нет. Не мешайте в счётчик товара отзывы о магазине.

Те же факты могут лежать в файле OpenAI как star_rating и review_count. Там эти поля необязательны. Если страница и файл оба называют рейтинг, это должна быть одна и та же группа отзывов.

Фид и страница — две копии

У Google Merchant Center свой фид. В спецификации товарных данных есть id, title, description, link, image_link, availability, price и brand. Цена там выглядит как 18.00 PLN. availability использует in_stock, out_of_stock, preorder и backorder. Справка: https://support.google.com/merchants/answer/7052112.

В файле discovery у OpenAI это item_id, url, image_url и price вида 18.00 PLN, а предзаказ пишется pre_order. seller_name там обязателен, и в базовой строке Google пары ему нет.

Offer на странице, фид Google и фид OpenAI — три копии одного факта. Если они расходятся, вы не выбираете, какую копию повторит ассистент.

На странице продавцов OpenAI сказано: фид необязателен, если ChatGPT уже обходит сайт, и фид даёт больше контроля над тем, как выглядят товары. Там не сказано, что фид побеждает, когда две цены разные. Perplexity, Gemini и Google AI Overviews — не этот фид. На странице AI features у Google структурированные данные должны совпадать с видимым текстом.

Полный пример

Один товар, одно предложение, разметка в HTML с сервера. Подставьте свои URL вместо example.com. В price нет символа валюты. availability — полный URL schema.org.

Если у кружки есть синий и белый вариант с разными ценами, не прячьте обе цены из HTML и не подменяйте их скриптом. Либо у каждого варианта свой URL и свой Offer, либо в массиве offers по одному Offer на вариант, со своими price, availability и url.

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Ceramic mug, 350 ml",
  "image": "https://example.com/images/mug.jpg",
  "description": "Glazed ceramic mug with a handle. Dishwasher safe.",
  "sku": "MUG-350",
  "brand": { "@type": "Brand", "name": "Northline" },
  "offers": {
    "@type": "Offer",
    "url": "https://example.com/products/mug",
    "priceCurrency": "PLN",
    "price": "72.00",
    "availability": "https://schema.org/InStock",
    "itemCondition": "https://schema.org/NewCondition"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.6",
    "reviewCount": "28"
  }
}

Как проверить

Откройте URL товара в Rich Results Test: https://search.google.com/test/rich-results. Сервис заберёт URL, либо можно вставить HTML. Прочитайте объект Product. price, priceCurrency и availability должны быть сегодняшними значениями со страницы, а не старым значением из шаблона.

Валидатор schema.org https://validator.schema.org/ проверяет словарь. Граф может быть верным и при этом содержать не ту цену. Сравните извлечённую цену с ценой, которую видит покупатель.

Запросите и сырой HTML. Сделайте curl адреса товара или откройте view-source и найдите строку цены и schema.org/InStock. Если они появляются только после гидрации, в первом ответе их не было.

Что ломает цену

Цена, которую пишет только клиентский JavaScript, отсутствует в первом HTML. Google пишет, что Googlebot исполняет JavaScript: https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics. Этот документ про Googlebot. Он не говорит того же про каждый ИИ-краулер.

OpenAI, Perplexity и Anthropic не описывают движок JavaScript для GPTBot, OAI-SearchBot, ChatGPT-User, PerplexityBot и ClaudeBot. Кладите цену в HTML, который отдаёт сервер.

Дальше ломает расхождение с фидом. На странице 72.00 PLN, а в файле 79.99 USD, или страница «в наличии», а файл говорит out_of_stock. Чиньте источник, из которого читают обе копии. Не правьте только разметку.

Варианты ломают цену, когда один URL отдаёт много цен, а Offer называет только первую. Цвет, выбранный в браузере и не меняющий HTML сервера, оставляет ассистенту вариант по умолчанию. Дайте варианту стабильный URL и поставьте его в Offer.url.

Другие тихие сбои: availability словом магазина вместо URL schema.org, цена с десятичной запятой, Offer на категории и отсутствие его на URL товара, AggregateRating с ratingValue и reviewCount, равным нулю.

OpenAI пишет про примерно 24 часа, чтобы правка robots.txt повлияла на поиск. Срока для исправленной цены нет. Загружайте полный снимок не реже раза в день и снова проверьте тот же SKU.

  • В HTML адреса товара есть Product и Offer до запуска скриптов.
  • price — десятичное число в основных единицах, priceCurrency — код ISO.
  • availability — это https://schema.org/InStock или соответствующий URL для отсутствия, предзаказа или ожидания поставки.
  • У варианта со своей ценой свой Offer или свой URL.
  • AggregateRating нет, если отзывов нет.
  • Цена в Offer совпадает с ценой Google Merchant и с фидом OpenAI.
  • Rich Results Test показывает ту цену, которую видит покупатель.
Нужен именно JSON-LD или хватит Microdata?

schema.org допускает больше одного синтаксиса. JSON-LD в HTML с сервера проще сверять с фидом. Проверка одна: есть ли цена и наличие в полученном HTML под именами, которые читает разбор.

Нужен ли Offer каждого товара на странице категории?

Предложение живёт на URL, где товар продают. Сетка категории может повторять названия. Она не должна быть единственным местом, где есть цена. Ассистенты цитируют URL товара.

Какой URL наличия, если товара нет?

https://schema.org/OutOfStock. Offer оставьте на странице, с текущей ценой. Если убрать Offer, это не значит «нет в наличии». Это значит «ничего».

Меняет ли AggregateRating цену, которую называет ассистент?

Нет. Цена берётся из Offer.price и priceCurrency. AggregateRating — сводка отзывов. Не ставьте её, если reviewCount был бы нулём.