# Загрузка через XML/YML
- Поддерживаемые кодировки
- Основные элементы
- Элемент xml
- Элемент yml_catalog
- Элемент yml_catalog > shop
- Базовые элементы yml_catalog > shop > *
- Элемент yml_catalog > shop > currencies
- Элемент yml_catalog > shop > categories
- Элемент yml_catalog > shop > locations
- Элемент yml_catalog > shop > offers
- Элемент yml_catalog > shop > offers > offer
- Элемент yml_catalog > shop > offers > offer > locations
- Элемент yml_catalog > shop > offers > offer > tags
- Пример полного XML-файла
- Нишевые параметры
- Рекомендации по генерации товарного фида
- Использование Database Mirroring
Базовый формат товарной выгрузки REES46 основан на YML (Yandex Market Language), более подробное описание которого доступно в разделе помощи Яндекс по ссылке (opens new window).
# Поддерживаемые кодировки
- UTF-8
- Windows-1251 (не рекомендуется с 2010 года)
# Основные элементы
| Элемент | Обязательность | Описание |
|---|---|---|
xml | обязательно | Стандартный XML-заголовок. Должен начинаться с первой строки и нулевого символа в строке. |
yml_catalog | обязательно | Корневой элемент XML-документа товарной выгрузки. |
shop | обязательно | Основной элемент товарной выгрузки, содержащий описание магазина и товаров. |
# Элемент xml
Доступные атрибуты:
| Атрибут | Обязательность | Описание |
|---|---|---|
version | обязательно | Версия языка XML-документа. Необходимо использовать версию "1.0". |
encoding | обязательно | Кодировка, используемая в XML-документе (из доступных). |
Пример:
<?xml version="1.0" encoding="UTF-8"?>
# Элемент yml_catalog
Доступные атрибуты:
| Атрибут | Обязательность | Описание |
|---|---|---|
date | обязательно | Дата создания (генерации) XML-документа в формате YYYY-MM-DD hh:mm. |
Пример:
<?xml version="1.0" encoding="UTF-8"?>
<yml_catalog date="2019-05-16 17:19">
...
</yml_catalog>
# Элемент yml_catalog > shop
Дочерние элементы shop:
| Элемент | Обязательность | Описание |
|---|---|---|
name | обязательно | Краткое название магазина. |
company | обязательно | Наименование компании, владеющей магазином. |
url | обязательно | Ссылка на главную страницу магазина. |
currencies | обязательно | Список курсов валют магазина. |
categories | обязательно | Список категорий магазина. |
locations | не обязательно | Список локаций, в которых представлен магазин. |
offers | обязательно | Список товаров магазина. |
# Базовые элементы yml_catalog > shop > *
Пример:
<?xml version="1.0" encoding="UTF-8"?>
<yml_catalog date="2019-05-16 17:19">
<shop>
<name>Мой магазин</name>
<company>Компания моего магазина</company>
<url>https://my-store.com</url>
...
</shop>
</yml_catalog>
# Элемент yml_catalog > shop > currencies
Элемент currencies задает список курсов валют магазина. Каждая из валют описывается отдельным элементом currency.
Доступные атрибуты элемента currency:
| Атрибут | Обязательность | Описание |
|---|---|---|
id | обязательно | Код валюты. |
rate | обязательно | Курс валюты по отношению к основной валюте. Значение данного атрибута для основной валюты должно быть равно 1 (rate="1"). В качестве десятичного разделителя может использоваться только символ точки. |
Пример:
<?xml version="1.0" encoding="UTF-8"?>
<yml_catalog date="2019-05-16 17:19">
<shop>
<name>Мой магазин</name>
<company>Компания моего магазина</company>
<url>https://my-store.com</url>
<currencies>
<currency id="RUR" rate="1"/>
<currency id="USD" rate="64.45"/>
<currency id="EUR" rate="72.03"/>
...
</currencies>
...
</shop>
</yml_catalog>
# Элемент yml_catalog > shop > categories
Элемент categories содержит список категорий магазина. Каждая категория описывается отдельным элементом category.
Доступные атрибуты элементы category:
| Атрибут | Обязательность | Описание |
|---|---|---|
id | обязательно | Идентификатор категории. |
parentId | не обязательно | Идентификатор родительской категории. |
url | не обязательно | Ссылка на страницу категории. |
alias | не обязательно | Словесный идентификатор категории. |
Пример:
<?xml version="1.0" encoding="UTF-8"?>
<yml_catalog date="2019-05-16 17:19">
<shop>
<name>Мой магазин</name>
<company>Компания моего магазина</company>
<url>https://my-store.com</url>
<currencies>
<currency id="RUR" rate="1"/>
<currency id="USD" rate="64.45"/>
<currency id="EUR" rate="72.03"/>
...
</currencies>
<categories>
<category id="2" url="http://my-store.com/categories/discount/">Распродажа</category>
<category id="8" url="http://my-store.com/categories/men/">Мужчинам</category>
<category id="13" parentId="8" url="http://my-store.com/categories/men/shoes/">Shoes</category>
<category id="97" parentId="13" alias="men/shoes/leather" url="http://my-store.com/categories/men/shoes/leather">Leather Shoes</category>
...
</categories>
...
</shop>
</yml_catalog>
# Элемент yml_catalog > shop > locations
Элемент locations содержит список локаций магазина. Каждая локация описывается отдельным элементом location.
Доступные атрибуты элементы location:
| Атрибут | Обязательность | Описание |
|---|---|---|
id | обязательно | Идентификатор локации. |
name | обязательно | Название локации. |
parentId | не обязательно | Идентификатор родительской локации. |
type | не обязательно | Тип локации. Доступные значения: state, city, store. |
group | не обязательно | Признак группировки нескольких локаций в определенную группу. Любое строковое значение. Пример: ХолодныеРегионы. |
search_level_up | не обязательно | Атрибут определяет возможность расширения поиска вверх по иерархии родительских локаций. Если значение равно 0, поиск не пойдёт выше. Если значение больше ноля, повторный поиск производится в родительских локациях, но будет ограничен существующей иерархией. |
Иерархия локаций
search_level_up работает только с иерархией локаций, заданной в товарном фиде при помощи атрибута parentId. Корректное выстраивание иерархии является ответственностью товарного фида. Если цепочка parentId задана некорректно или обрывается, расширение поиска не выполняется.
То есть, если товар отсутствует в конкретной торговой точке, поиск не будет автоматически выполняться по всему городу или региону без явно заданной иерархии.
Пример:
<?xml version="1.0" encoding="UTF-8"?>
<yml_catalog date="2019-05-16 17:19">
<shop>
<name>Мой магазин</name>
<company>Компания моего магазина</company>
<url>https://my-store.com</url>
<currencies>
<currency id="RUR" rate="1"/>
<currency id="USD" rate="64.45"/>
<currency id="EUR" rate="72.03"/>
...
</currencies>
<categories>
<category id="2" url="http://my-store.com/categories/discount/">Распродажа</category>
<category id="8" url="http://my-store.com/categories/men/">Мужчинам</category>
<category id="13" parentId="8" url="http://my-store.com/categories/men/shoes/">Shoes</category>
<category id="97" parentId="13" alias="men/shoes/leather" url="http://my-store.com/categories/men/shoes/leather">Leather Shoes</category>
...
</categories>
<locations>
<location id="1" type="city" name="Москва" group="ДенежныеГорода" />
<location id="2" type="city" name="Санкт-Петербург" group="ДенежныеГорода" />
<location id="145" parentId="1" type="store" name="Пункт выдачи на Арбате" search_level_up="1" />
...
</locations>
...
</shop>
</yml_catalog>
# Элемент yml_catalog > shop > offers
Элемент offers содержит список товаров магазина. Каждый товар описывается отдельным элементом offer.
Обратите внимание
Элемент offer не может содержать вариант товара, а только сам товар. Если в вашем магазине все варианты одного товара находятся на одной странице сайта и нет общего идентификатора для вариантов товара, то вам необходимо использовать какой-то один из вариантов в качестве основного - его идентификатор, цену и пр. данные. Обычно выбирают самый дешёвый вариант товара в качестве основного, а флаг наличия в данном случае должен вписаться в следующую логику – если хотя бы один вариант товара есть в наличии, то товар должен считаться в наличии.
# Элемент yml_catalog > shop > offers > offer
Доступные атрибуты элемента offer:
| Атрибут | Обязательность | Описание |
|---|---|---|
id | обязательно | Идентификатор товара. |
group_id | обязательно | Идентификатор группы товаров. Необходим для объединения вариантов товаров в одну группу. В ответе блоков рекомендаций и поиска будет возвращен только один из вариантов. |
available | обязательно | Флаг наличия товара. Доступные значения: true, false. |
ignored | не обязательно | Флаг учета товара. Если передан false, товар не будет выводиться в результатах работы инструментов. Доступные значения: true, false. |
leftovers | не обязательно | Остаток товара. Может принимать одно из значений: one (товар доступен в единственном экземпляре), few (товар в ограниченном количестве (до 10 ед.)), lot (доступно от 10 и более единиц товара). |
Лайфхак
На самом деле нет смысла передавать в товарном фиде товары не в наличии. Платформа автоматически сделает не в наличии все товары, которые отсутствуют в фиде. Поэтому для ускорения обработки фида и уменьшения его размера, просто не добавляйте в него товары, которые не в наличии.
Дочерние элементы offer:
| Элемент | Обязательность | Описание |
|---|---|---|
name | обязательно | Полное название товара. Для раздельного написания названия см. элементы: typePrefix, vendor, model. |
picture | обязательно | Ссылка на изображение товара. |
price | обязательно | Базовая цена товара. |
price_with_promocode | обязательно | Базовая цена товара с учетом использования промокода. |
url | обязательно | Ссылка на страницу товара. |
categoryId | обязательно | Категория товара. Этих элементов может быть несколько. |
deeplink_android | не обязательно | Ссылка на страницу товара в приложении (Android). |
deeplink_ios | не обязательно | Ссылка на страницу товара в приложении (Ios). |
locations | не обязательно | Элемент, описывающий свойства товара в разных локациях: наличие, цена. См. таблицу и пример ниже. |
accessories | не обязательно | Элемент, описывающий список аксессуаров текущего товара. См. пример ниже. |
oldprice | не обязательно | Старая цена товара. |
discount_percent | не обязательно | Процент скидки. При отсутствии в импорте данного параметра и наличии oldprice, он будет автоматически рассчитан по формуле: целая часть от ((oldprice - price) / oldprice) * 100 (получается путём округления вниз до целого) |
price_margin | не обязательно | Относительная маржинальность (приоритет) товара (от 0 до 100). |
barcode | не обязательно | Штрих-код товара. |
typePrefix | не обязательно | Тип/категория товара (например, "мобильный телефон", "стиральная машина", "угловой диван"). |
vendor | не обязательно | Производитель/бренд. |
vendorCode | не обязательно | Код производителя для данного товара. |
model | не обязательно | Модель и название товара. |
seasonality | не обязательно | Сезонность товара. В качестве значения используется порядковый номер месяца ( от 1 до 12). Этих элементов может быть несколько. |
is_new | не обязательно | Может принимать только одно значение - "1", означающее, что товар является новинкой. |
rating | не обязательно | Рейтинг товара. Целочисленное значение от 1 до 5. |
description | не обязательно | Описание товара. |
stock_quantity | не обязательно | Количество товара. Целочисленное значение от 1 и более. |
tags | не обязательно | Элемент, описывающий связанные с товаром теги, для точного поиска. См. таблицу и пример ниже. |
merchant | не обязательно | ID продавца. (Актуально для маркетплейсов) |
param | не обязательно | Параметр. |
date | не обязательно | Дата добавления или обновления. |
gift | не обязательно | Информация о подарке. |
installment | не обязательно | Информация о рассрочке. |
promocode | не обязательно | Промокод. |
bonuses_accrual_allowed | не обязательно | Управление возможностью начисления бонусов за товар. Значения: true или false |
bonuses_spending_allowed | не обязательно | Управление возможностью списания бонусов за товар. Значения: true или false |
discounts_allowed | не обязательно | Управление возможностью применения скидок к товару. Значения: true или false |
Примите во внимание
При обработке url к ссылке добавляются параметры вида recommended_by, recommended_code и т.д.
Они необходимы для работы трекинга событий и построения аналитики.
Если вам нужно передать в ссылке собственные параметры, их требуется закодировать.
В противном случае некоторые символы будут некорректно обработаны, например, согласно спецификации RFC3986 знак + распознается как пробел.
Если вам нужно, чтобы при переходе по ссылке в параметре передавался знак +, то его нужно экранировать в %2B.
Пример:
http://test.com?test=+-!ABC -> http://test.com?test=%2B-%21ABC
Сезонность
Если у товара указана сезонность, и она совпадает с текущим месяцем, он получает буст 1.2.
Если сезонность — следующий месяц, буст будет 1.1.
Если указаны оба месяца (текущий и следующий), коэффициенты умножаются. Например: сезонность — июнь и июль, сейчас июнь → буст: 1.2 × 1.1 = 1.32.
Если сезонность не указана — считается универсальным товаром, буст тоже 1.2.
Во всех других случаях — буст 1.0.
# Элемент yml_catalog > shop > offers > offer > locations
Элемент locations содержит список локаций, а также доступность и цену текущего товара в локациях. Каждая локация описывается отдельным элементом location.
Атрибуты элемента location:
| Атрибут | Обязательность | Описание |
|---|---|---|
id | обязательно | Идентификатор, соответствующий локации (идентификатору) из элемента locations элемента shop. Подробнее об описании локации см. в соответствующем подразделе этого документа и в примере ниже. |
weight | не обязательно | Приоритет товара в локации (от 0 до 100). |
Обратите внимание
Товар будет считаться доступным к приобретению только в перечисленных в элементе offer локациях. Во всех остальных известных, но не перечисленных локациях, товар будет считаться не в наличии. Если же у offer отсутствует элемент locations, то товар считается в наличии во всех локациях магазина.
Дочерние элементы:
| Элемент | Обязательность | Описание |
|---|---|---|
price | не обязательно | Цена товара в локации. Если элемент отсутствует, то используется базовая цена товара. |
oldprice | не обязательно | Старая цена товара в локации. Если элемент отсутствует, то используется базовая старая цена товара (при наличии). |
stock_quantity | не обязательно | Количество товара. Целочисленное значение от 1 и более. |
# Элемент yml_catalog > shop > offers > offer > tags
Элемент tags содержит список тегов, соотносящихся с товаром. Каждое значение описывается отдельным элементом tag.
| Элемент | Обязательность | Описание |
|---|---|---|
tag | обязательно | Значение тега. |
# Пример полного XML-файла
<?xml version="1.0" encoding="UTF-8"?>
<yml_catalog date="2019-05-16 17:19">
<shop>
<name>Мой магазин</name>
<company>Компания моего магазина</company>
<url>https://my-store.com</url>
<!-- перечисление валют магазин и курсов валют -->
<currencies>
<currency id="RUR" rate="1"/>
<currency id="USD" rate="64.45"/>
<currency id="EUR" rate="72.03"/>
</currencies>
<!-- перечисление всех категорий магазина, их иерархии и ссылок -->
<categories>
<category id="2" url="http://my-store.com/categories/apple/">Apple</category>
<category id="13" parentId="2" alias="apple/phones" url="http://my-store.com/categories/apple/phones/">Телефоны</category>
</categories>
<!-- перечисление всех локаций магазина -->
<locations>
<location id="1" type="city" name="Москва" />
<location id="2" type="city" name="Санкт-Петербург" />
<location id="3" type="city" name="Новосибирск" />
</locations>
<offers>
<offer id="395532" available="true" leftovers="few">
<url>http://my-store.com/items/395532</url>
<deeplink_android>http://my-store.com/items/395532</deeplink_android>
<deeplink_ios>http://my-store.com/items/395532</deeplink_ios>
<price>50000</price>
<price_with_promocode>40000</priceWithPromocode>
<oldprice>55000</oldprice>
<price_margin>67</price_margin>
<!-- перечисление иерархий категорий, в которых присутствует данный товар -->
<categoryId>2</categoryId>
<categoryId>13</categoryId>
<!-- Указана сезонность. Приоритетные месяцы для данного товара: январь, март, апрель, июнь. -->
<seasonality>1</seasonality>
<seasonality>3</seasonality>
<seasonality>4</seasonality>
<seasonality>6</seasonality>
<!-- перечисление локаций, в которых данный товар доступен к приобретению, а также уточнение цены товара в локации -->
<locations>
<location id="1" weight="80">
<price>70000</price>
<oldprice>75000</oldprice>
<stock_quantity>10</stock_quantity>
</location>
<!-- локация id="2" не указана, значит товар в этой локации отсутствует -->
<!-- в локации id="3" не указан price, значит цена товара соответствует базовой -->
<location id="3"></location>
</location>
<!-- Перечислены ID товаров, являющиеся аксессуарами для текущего товара -->
<accessories>
<accessory id="5574" />
<accessory id="131" />
<accessory id="99444" />
<accessory id="334411" />
</accessories>
<tags>
<tag>телефон</tag>
<tag>смартфон</tag>
</tags>
<barcode>123456</barcode>
<picture>https://my-store.com/items/395532.jpg</picture>
<name>Apple Iphone 6 128 gb</name>
<typePrefix>Смартфон</typePrefix>
<vendor picture="http://example.com/apple.jpg">Apple</vendor>
<vendorCode>APPL</vendorCode>
<model>iPhone 6 128Gb</model>
<is_new>1</is_new>
<rating>5</rating>
<date>2022-01-01</date>
<description><![CDATA[iPhone 6 не просто больше. Он лучше во всех отношениях. 4,7-дюймовый HD-дисплей Retina. Процессор A8 с 64-разрядной архитектурой уровня настольного компьютера. Новая 8-мегапиксельная камера iSight с технологией Focus Pixels. Сенсор идентификации по отпечатку пальца Touch ID. Скорость Wi-Fi выше. Время работы от аккумулятора дольше. А также iOS 8 и iCloud. Все это - в цельном корпусе толщиной всего 6,9 мм.]]></description>
<merchant>abc123xyz789</merchant>
<param name="Color">Black</param>
<!-- Параметр unit указывает на то, что значение параметра числовое и для него можно использовать range фильтрацию -->
<param name="Heigth" unit="mm">140</param>
<!-- Параметр priority позволяет передавать значение для произвольной сортировки параметров в ответе полного поиска -->
<param name="Sim" priority="20">E-sim</param>
<installment>36</installment>
<discount_percent>50</discountPercent>
<promocode>Discount20</promocode>
<gift>true</gift>
<bonuses_accrual_allowed>true</bonuses_accrual_allowed>
<bonuses_spending_allowed>true</bonuses_spending_allowed>
<discounts_allowed>true</discounts_allowed>
</offer>
<offer id="395533" available="false">
...
</offer>
...
</offers>
</shop>
</yml_catalog>
# Нишевые параметры
Для обогащения пользовательских профилей и усиления эффекта персонализации рекомендуется добавлять нишевые параметры товаров в секцию offer.
- Автотовары
- Книги
- Товары для детей
- Косметика и парфюмерия
- Недвижимость
- Одежда, обувь, аксессуары
- Строительные материалы и инструмент
- Товары для взрослых
- Товары для животных
- Товары повседневного спроса (FMCG)
- Фармацевтика и медицина
- Ювелирные украшения
# Рекомендации по генерации товарного фида
# Генерация файла по расписанию
Если XML вашего магазина имеет размер больше 5 мегабайт и режиме реального времени создаётся дольше 20 секунд, будет лучше, если вместо того, чтобы указывать ссылку на скрипт генерации XML, вы поставите задачу генерации XML в расписание. Ваш скрипт должен генерировать статичный XML-файл, скачивание которого начнется сразу при обращении к нему, без затрат времени на генерацию. Это даст вам следующие преимущества:
- снижение нагрузки на ваш сервер при больших XML (иначе будет очень легко устроить вам DDOS-атаку, сделав 20-30 одновременных запросов к этому ресурсоемкому скрипту);
- ускорение загрузки вашего YML нашими серверами – вместо того, чтобы ждать генерации файла по 10-15 минут, REES46 сразу начнет их выкачивать и это повысит актуальность вашей товарной базы платформе.
Пример такого расписания для cron:
0 */2 * * * php /home/myuser/site/docs/xml.php > /home/myuser/site/docs/rees46.xml
Обратите внимание
Если генерация файла занимает больше нескольких секунд, рекомендуем сохранять временный файл отдельно, а потом, когда генерация будет закончена, подменить им тот файл, который доступен снаружи. Иначе может возникнуть ситуация, что файл будет заменен частично в процессе выкачивания его платформой и в платформу попадет неполный файл и обработка закончится с ошибкой.
# Архивы
Для того, чтобы ускорить выкачивание больших XML-файлов, вы можете архивировать их архиватором GZIP. Сервис автоматически определяет архивированный файл, распаковывает его и обрабатывает. Формат архива – GNU Gzip (opens new window).
# Использование Database Mirroring
- Нужно добавить новый режим синхронизации данных о товарах - промежуточная база данных
- При переключении в новый режим создаётся новая база с новым пользователем
- Данные для доступа -
shop_id:shop_secret. Путь к базе выводится на странице настроек магазина - Список таблиц - categories, locations, products
- Структура:
categories
- category_id - varchar(255)
- parent_id - varchar(255)
- active - boolean
- name - varchar(255)
- url - varchar(255)
- updated_at - timestamp(6) = now()
- processed_at - timestamp(6)
locations
- location_id - varchar(255)
- active - boolean
- name - varchar(255)
- updated_at - timestamp(6) = now()
- processed_at - timestamp(6)
products
- product_id - varchar(255)
- active - boolean
- data - jsonb(65,535)
- updated_at - timestamp(6) = now()
- processed_at - timestamp(6)
Колонка active предназначена для обновления сведений о наличии данных, без их удаления.
При каждой обработке система забирает данные а затем фильтрует их по колонкам: updated_at, active.
Они передаются в API порциями по 2000 штук. Время в колонке processed_at обновляется.
Обратите внимание
При каждом обновлении обязательно проставлять текущее время (UTC=0) в колонке updated_at
# Правила работы с таблицами
- Данные могут записываться в любой последовательности
- Строки в таблице можно удалять, либо переключать значение колонки active на false. Такие строки будут игнорироваться
Обратите внимание
При обновлении строки нужно обновить значение колонки updated_at на текущий timestamp и НЕ ОБНОВЛЯТЬ колонку processed_at.
Если данные в строке не обновлялись, обновлять значение колонки updated_at НЕЛЬЗЯ.