Маппинг полей коннектора
Поэтапный маппинг сущностей: товары, категории, варианты, цены, остатки, изображения и локали. Контракт каждого CMS-модуля при отправке данных в AACsearch.
Эта страница — окончательный справочник по тому, что CMS-модуль должен отправлять в AACsearch. Формы эндпоинтов — в Жизненном цикле Connector API; здесь — семантика: какое поле в CMS какому полю AACsearch соответствует и почему.
Каждый коннектор шлёт документы SyncProductInput. Форма умышленно узкая (это индекс товаров, а не общий контентный стор), но достаточно гибкая, чтобы через attributes хранить статьи, рецепты или любые другие сущности.
Поля товара
| Поле | Тип | Обязательно | Замечания |
|---|---|---|---|
external_id | string | да | Стабильный первичный ключ платформы. Не slug, не SKU. |
title | string | да | Чистый текст в настроенной locale. Стрипнуть HTML и шорткоды. |
description | string | нет | Чистый текст. Стрипнуть HTML, развернуть rich-text JSON / markdown. |
sku | string | нет | Основной SKU или SKU дефолтного варианта. |
brand | string | нет | Имя производителя / вендора. Пустая строка → удалить поле. |
categories | string[] | нет | См. Категории. |
category_ids | string[] | нет | ID категорий платформы для фильтров. Стабильные при переименовании. |
tags | string[] | нет | Плоский список ярлыков. |
price | number | нет | Основные единицы. См. Цены. |
sale_price | number | нет | Основные единицы. См. Цены. |
currency | string | нет | ISO 4217, 3 буквы в верхнем регистре. Нижний регистр валидатор не примет. |
image_url | string (URL) | нет | Основное изображение. См. Изображения. |
product_url | string (URL) | нет | URL витрины — используется виджетом для перехода. |
availability | enum | нет | "in_stock", "out_of_stock", "preorder". См. Остатки. |
stock_quantity | number | нет | Сумма доступных единиц по всем локациям. |
attributes | Record<string,unknown> | нет | Произвольные фасетные/display-поля. См. Атрибуты. |
locale | enum | нет | en, de, es, fr, ru. По документу на локаль. |
created_at | string (ISO 8601) | нет | Используется для сортировки «Недавно добавлено». |
updated_at | string (ISO 8601) | нет | Применяется для детекции изменений в буфере; рекомендуется. |
Правила external_id
Берите первичный ключ CMS:
- WooCommerce / WordPress:
post_id(число) - PrestaShop:
id_product - Bitrix:
iblock_element_id - Shopify: числовой product ID, не handle
- Magento:
entity_id, не SKU
Если платформа хранит локали как отдельные строки таблицы, добавьте суффикс локали: prod-123:en. Не переиспользуйте external_id между типами товаров и локалями — поиски схлопнутся.
Категории
Два поля, используются вместе:
categories— полный путь крошек, корень → лист, человекочитаемые строки.["Обувь", "Беговая", "Трейл"], а не["Трейл"]. Виджет рендерит путь в фильтрах.category_ids— стабильные ID того же пути, корень → лист. Используется для фильтров, переживающих переименование категорий.
Если товар лежит в нескольких категориях, передавайте каждый путь отдельной строкой в categories. Порядок массива для ранкинга не важен — только идентичность строк для счётчиков фасетов.
| CMS | Источник categories | Источник category_ids |
|---|---|---|
| PrestaShop | ps_category_lang.name по пути | ps_category.id_category по пути |
| Bitrix | имена iblock-разделов | ID iblock-разделов |
| WordPress | термы таксономии «category» | ID термов |
| Shopify | product_type + названия коллекций | ID коллекций |
| Strapi | reference-поле, развёрнутое рекурсивно | document-ID |
| Sanity | references(), развёрнутые рекурсивно | _id категорий |
Варианты
Дефолтная модель — документы на уровне товара. Данные вариантов (размер, цвет, материал, SKU варианта, остатки по варианту) уезжают в attributes. Один товар = один документ.
Это правильный выбор для большинства e-commerce: покупатели ищут «синие беговые кроссовки», а не «синие беговые кроссовки размер 9.5 узкие». Виджет показывает карточку родительского товара; выбор варианта — на странице товара.
Когда отправлять документы на уровне вариантов
Стройте отдельный mapper, шлющий по документу на вариант, когда:
- Поиск должен поднимать конкретные SKU (B2B-каталоги, магазины запчастей).
- Заголовки или картинки вариантов сильно различаются (комплект vs одиночный товар).
- Варианты живут в разных категориях.
В этом случае:
external_id— ID варианта с суффиксом родителя:prod-123:variant-7.titleвключает атрибуты варианта: «Синие беговые кроссовки — размер 9.5 узкие».image_url— картинка варианта, а не родителя.- Добавьте
attributes.parent_external_id, чтобы дедуплицированный «по товару» поиск мог схлопывать результаты.
Эталонный Shopify-коннектор использует уровень товара по умолчанию; см. Custom Connector для варианта-mapper'а.
Цены
Формат на проводе
price и sale_price — это основные единицы, десятичные числа. 99.99 USD шлётся как 99.99, а не 9999. Connector API сам конвертирует в минорные единицы (kopecks-style BigInt) внутри ингест-пайплайна. Если отправить 9999, индексируется цена 9 999.00 USD.
Двухценовая модель
price— основная цена без активной акции.sale_price— акционная цена, если активна. При заполненномsale_priceвиджет рендерит обе со страйком наprice.
Когда цен много
В CMS с группами клиентов, B2B-тарифами и динамическим ценообразованием товар один, а цен много. Простая конвенция:
{
"price": 99.99,
"sale_price": 79.99,
"currency": "USD",
"attributes": {
"price_by_group": {
"retail": 99.99,
"wholesale": 79.99,
"vip": 69.99
}
}
}price — дефолтная витринная цена. Остальные тарифы — в attributes.price_by_group. Витрина фильтрует или сортирует по нужной группе на стороне запроса.
Мультивалютные каталоги
Шлите валюту, которую видит клиент, в currency, остальные — в attributes.price_by_currency:
{
"currency": "USD",
"price": 99.99,
"attributes": {
"price_by_currency": { "EUR": 92.5, "GBP": 79.99 }
}
}AACsearch проиндексирует альтернативные цены как числовые атрибуты, и витрина сможет менять валюту без переиндексации.
Остатки
Два поля, которые виджет использует для бейджа доступности:
availability—"in_stock"/"out_of_stock"/"preorder". Определяет бейдж на карточке.stock_quantity— общее число единиц по локациям. Определяет подсказку «Осталось 3 штуки».
Правила маппинга
| Платформа | Откуда брать availability |
|---|---|
| PrestaShop | ps_stock_available.quantity > 0 AND политика out_of_stock → in_stock |
| Bitrix | хэндлер OnPriceUpdate; CATALOG_AVAILABLE = 'Y' → in_stock |
| WooCommerce | post meta _stock_status: instock / outofstock / onbackorder (→ preorder) |
| Shopify | сумма inventory_quantity по whitelist-локациям |
| Strapi | кастомное поле content-type или значение по умолчанию in_stock |
Товар «в наличии», если хотя бы одна whitelist-локация имеет количество > 0. Whitelist локаций настраивается в конфиге коннектора.
Backorder и pre-order
Если платформа поддерживает backorder или предзаказ, мапьте их в preorder. Виджет рендерит отдельный лейбл. Товар остаётся в результатах поиска — полезно для сценариев «скоро в продаже».
Изображения
image_url — это основное display-изображение, полный URL со схемой. Виджет рендерит его на карточке.
Если у товара несколько картинок, полный список — в attributes.images:
{
"image_url": "https://cdn.example.com/products/brs-42/main.jpg",
"attributes": {
"images": [
{ "url": "https://cdn.example.com/products/brs-42/main.jpg", "alt": "Спереди" },
{ "url": "https://cdn.example.com/products/brs-42/side.jpg", "alt": "Сбоку" }
]
}
}Правила для картинок
- Полные URL (https://...). Относительные ломаются, когда виджет работает на CDN edge.
- Шлите версию того размера, что показывает витрина. AACsearch не ресайзит.
- Если платформа отдаёт WebP / AVIF, шлите URL того формата, который реально использует витрина.
- Пустая строка невалидна — удалите поле, если картинки нет.
Фолбэки изображений
Виджет рендерит плейсхолдер при отсутствии image_url. Если у вас плейсхолдеры по типу товара, настройте их через тему виджета, а не синтезируйте URL плейсхолдера на стороне коннектора.
Локали
AACsearch принимает пять локалей: en, de, es, fr, ru. Если в CMS есть локаль вне этого набора, шлите ближайшего соседа, а оригинальный код кладите в attributes.language:
{
"locale": "en",
"attributes": {
"language": "pt-BR",
"language_label": "Português (Brasil)"
}
}Разделение на документы
Для платформ с локализованными каталогами (Polylang, WPML, Shopify Markets, мультимагазин PrestaShop, i18n Strapi):
- По документу на локаль на сущность.
external_idсуффиксирован локалью:prod-123:en,prod-123:de.- Заголовок и описание — на языке локали.
- Категории — тоже на языке локали, никогда не строками дефолтной локали.
Обновление одной локали не затрагивает документы других локалей. Обработчик событий должен слать только изменившуюся локаль.
Резолв локали на витрине
Виджет получает локаль с витрины — обычно из префикса URL (/en/, /ru/) или атрибута lang HTML. Виджет шлёт locale=<code> в каждом запросе, AACsearch фильтрует документы по полю locale. Документы без locale матчатся под все локали.
Атрибуты
Любое поле, которое фильтруется, фасетится или нужно только для отображения, уходит в attributes. Ключи произвольные; значения — примитивы или массивы примитивов.
Вывод типа
AACsearch выводит тип индекса из первого батча в свежем индексе:
| Форма поля | Индексируется как |
|---|---|
"red" (string) | facet, exact match |
42 (number) | numeric, sort + range |
42.5 (number) | float, sort + range |
true (boolean) | только filter |
["red", "blue"] (array) | multi-facet |
[1, 2, 3] (массив чисел) | не поддерживается — разделить или сплитить |
Если поменять тип атрибута на лету (например, после 42 отправить "42"), AACsearch отбракует документ. Выбирайте тип на атрибут и не меняйте его.
Конвенции именования
- Lowercase. Подчёркивания для разделения слов.
option_color, неOptionColor. - Опции вариантов с префиксом
option_:option_color,option_size. Виджет рендерит их в секции «Варианты» автоматически. - Производные поля — с префиксом домена:
price_by_currency,price_by_group,stock_by_location. - Не занимайте имена верхнего уровня (из таблицы выше). Не кладите
titleвattributes.
Референсы по платформам
| Платформа | Файл маппера |
|---|---|
| PrestaShop | modules/prestashop/aacsearch/src/Exporter/ |
| Bitrix | modules/bitrix/aac.search/lib/ProductExporter.php |
| WordPress | modules/wordpress/aacsearch-search/src/Mapper/ |
| Shopify | packages/shopify-connector/src/product-mapper.ts |
| Strapi | packages/strapi-plugin/src/server/services/aacsearch.ts |
Читайте их как канонические примеры. Новые коннекторы должны следовать той же семантике полей — обратное отображение (CMS → SyncProductInput) платформо-специфично, но wire-формат инвариантен.
Связанные страницы
- Жизненный цикл Connector API
- Custom Connector
- Диагностика — включая примеры sync-ошибок
- Ротация токенов
Пользовательский коннектор — руководство разработчика
Сборка CMS-коннектора поверх Connector API AACsearch. Использование токенов, full/delta/delete-синхронизация, формат документа, правила маппинга и обязательная обработка ошибок.
Ротация токенов коннектора
Жизненный цикл токена: создание, область, процедура ротации, отзыв и реакция на утечку.