<!-- Canonical: https://docs.shopstory.live/docs/guide/feed-requirements -->

# Требования к товарному фиду

ShopStory использует товарный фид для каталога, связки товаров с эфирами и состояния кнопки покупки. Одно строковое значение `feedProductId` связывает товар в фиде, на web-PDP, в Mobile SDK и в product action. Основной формат — YML. Другие XML-схемы подключаются после согласования маппинга полей.

Фид передаёт снимок данных

Значение наличия обновляется при очередной успешной синхронизации фида и не учитывает магазин покупателя. Для остатка выбранного магазина SDK использует обработчик наличия на стороне сайта ритейлера, а окончательный результат подтверждает его cart-команда: [Наличие товара и остатки](<https://docs.shopstory.live/docs/guide/product-availability>).

## Доступ к источнику

Фид должен быть доступен ShopStory по HTTPS одним из способов:

- публичный URL;
- URL с HTTP Basic Auth.

Для защищённого фида передайте реквизиты через согласованный защищённый канал. Не добавляйте логин и пароль в URL вида `https://user:password@example.ru/feed.xml`.

Источник должен возвращать валидный XML с кодировкой UTF-8. URL карточек и изображений также должны использовать HTTPS и открываться без пользовательской сессии.

## Несколько версий фида

Каталог часто выгружается в нескольких версиях — по ценовым зонам, регионам или каналам продаж. Такие выгрузки различаются не только ценой: **состав товаров в них тоже разный**, вплоть до категорий, которые в отдельных версиях отсутствуют целиком.

Проект подключается к одной согласованной версии. Её цена и её состав отображаются в плеере и mini-player всем зрителям, независимо от того, где находится зритель.

Поэтому передайте при подключении:

| Что сообщить | Зачем |
| --- | --- |
| Полный список версий выгрузки и правило «регион или зона → версия» | Чтобы выбрать подключаемую версию осознанно, а не по первой ссылке |
| Какие версии рабочие | Пустая или неполная выгрузка проходит загрузку, но оставляет товары эфира без карточек |
| Зависит ли цена от региона покупателя и насколько | Определяет, допустимо ли показывать всем цену одной зоны |

Если цена или ассортимент зависят от региона покупателя, поведение для зрителей из других зон согласуется отдельно. [Обработчик наличия](<https://docs.shopstory.live/docs/guide/product-availability>) эту разницу не покрывает: он отвечает за доступность покупки и не меняет цену, название и состав каталога.

### Мастер-фид для расширенной интеграции

В расширенном commerce-контракте товарные данные могут поступать из фида, API магазина или их сочетания. Если структура вариантов передаётся фидом, он содержит товары подключаемого ассортимента, все их SKU и опции, включая временно отсутствующие варианты. При API как источнике структуры эти данные возвращает обработчик магазина; мастер-фид для этого режима не обязателен.

Таблица YML ниже описывает базовый товарный фид. Структура вариантов передаётся по согласованному маппингу, а актуальные условия — через обработчик магазина. Источники данных, поля карточки и обработчики описаны в разделе [Интеграция с интернет-магазином](<https://docs.shopstory.live/docs/guide/custom-commerce-integrations>).

## Идентификаторы товара

Для каждой позиции требуется стабильный строковый идентификатор:

- `id` у элемента `offer` — рекомендуемый источник `feedProductId`;
- `vendorCode` — артикул или SKU продавца.

Рекомендуется передавать оба поля, но во время подключения ShopStory и клиент выбирают одно значение как `feedProductId`. Оно без изменения формата используется в ShopStory, на сайте, в приложении и в действиях с товаром. `vendorCode` может оставаться внутренним SKU продавца; если commerce API принимает другой ключ, маппинг выполняется на стороне системы продавца.

Для ранее подключённых проектов может быть согласован поиск по `vendorCode`. Не смешивайте этот legacy-мэппинг с новым `feedProductId` в одной интеграции.

Правила для идентификаторов:

- не переиспользуйте значение для другого товара;
- не меняйте формат между выгрузками;
- сохраняйте ведущие нули и регистр, если они значимы;
- передавайте их как строки, даже если значение состоит только из цифр.

Изменение `id` или `vendorCode` может создать новую товарную запись. Уже существующая связка товара с эфиром автоматически на неё не переносится.

## Поля YML

| Поле | Требование | Назначение |
| --- | --- | --- |
| `offer/@id` или `vendorCode` | Хотя бы одно | Стабильная идентификация товара. |
| `name` | Для публикации | Название товара. |
| `url` | Для публикации | HTTPS-ссылка на карточку товара. |
| `picture` | Для публикации | Прямая HTTPS-ссылка на изображение. Можно передать несколько элементов. |
| `price` | Для публикации | Текущая цена. Правило для скидочной цены согласуется при подключении. |
| `currencyId` | Для публикации | Валюта цены, например `RUB`. |
| `available` | Если фид управляет доступностью | Булево значение `true` или `false` в атрибуте `offer`. |
| `oldprice` | Нет | Цена до скидки. |
| `vendor` | Нет | Бренд или производитель. |
| `categoryId` | Нет | Идентификатор категории в фиде. |
| `barcode` | Нет | Штрихкод. |
| `description` | Нет | Описание товара. |

«Для публикации» означает, что технически строка может быть прочитана без поля, но корректную карточку товара из неё сформировать нельзя. ShopStory проверяет состав полей и маппинг до первой синхронизации.

## Минимальный YML-пример

```xml
<?xml version="1.0" encoding="UTF-8"?>
<yml_catalog date="2026-09-04 10:00:00">
  <shop>
    <offers>
      <offer id="0001001" available="true">
        <name>Крем для рук</name>
        <url>https://example.ru/products/0001001</url>
        <price>299.00</price>
        <oldprice>349.00</oldprice>
        <currencyId>RUB</currencyId>
        <picture>https://cdn.example.ru/products/0001001.webp</picture>
        <vendor>Example Brand</vendor>
        <vendorCode>ART-0001001</vendorCode>
      </offer>
    </offers>
  </shop>
</yml_catalog>
```

Не копируйте пример как готовый маппинг цен. Если ERP передаёт текущую и старую цену иначе, это фиксируется в клиентском приложении к интеграции.

## Как обновляется доступность

При стандартной синхронизации:

1. ShopStory успешно загружает и проверяет новую версию фида.
2. Для товара с теми же согласованными идентификаторами обновляются цена, карточка и `available`.
3. Оффер с `available="false"` становится недоступным для покупки.
4. Товар, исчезнувший из успешно обработанного полного фида, также может быть отмечен недоступным согласно согласованному правилу импорта.
5. Live и VOD используют одно состояние доступности: товар остаётся в эфире, но кнопка покупки блокируется.

Уже открытый плеер использует полученный ранее снимок товарных данных. Новое значение появляется после следующей полной загрузки данных или перезагрузки страницы; фид не опрашивается в реальном времени.

В Public API этот снимок возвращается в `body.products[].feedProductAvailable` ответа `GET /v3/streams`. Поле не содержит количество единиц и не подтверждает наличие в выбранном магазине.

Если требуется остаток конкретного магазина, снимок фида дополняется live-проверкой: Web SDK запрашивает наличие у обработчика на сайте ритейлера и обновляет карточки его ответом. Семантика `available` в вашем фиде при этом определяет приоритет источников — остаток или вывод товара из ассортимента. Оба режима описаны в разделе [Наличие товара и остатки](<https://docs.shopstory.live/docs/guide/product-availability>).

## Проверка перед подключением

1. URL открывается из внешней сети по HTTPS и возвращает XML, а не HTML-страницу входа.
2. XML проходит синтаксическую проверку.
3. В каждом `offer` есть значение в поле, выбранном источником `feedProductId`; оно совпадает с тестовой web- или mobile-PDP.
4. Ведущие нули в идентификаторах не потеряны.
5. `url` и `picture` доступны без cookie пользовательской сессии.
6. `available` принимает только согласованные значения и проверен на нескольких доступных и недоступных товарах.
7. Тестовый импорт подтверждён до включения регулярной синхронизации.

## Связанные разделы

- [Наличие товара и остатки](<https://docs.shopstory.live/docs/guide/product-availability>)
- [Каталог эфиров](<https://docs.shopstory.live/docs/guide/catalog-streams>)
- [Mini-player](<https://docs.shopstory.live/docs/guide/mini-player>)
- [Mobile SDK](<https://docs.shopstory.live/docs/guide/mobile-sdk>)
- [Добавление товара в корзину](<https://docs.shopstory.live/docs/guide/add-to-cart>)
