Для подключения партнерского магазина PowerPartners к прайс-агрегаторам (таким как Я.Маркет, Google Покупки, price.ru и др.) и различным маркетплейсам (беру.ру, CDEK.маркет и др.), от магазина потребуется предоставить доступ к товарному фиду (списку товаров в специальном формате).

Кроме того, фиды понадобятся для создания динамических объявлений и смарт-баннеров в Яндекс.Директ, а так же торговых компаний в Google Ads. Пригодятся фиды и для товарных тизеров, для экспорта товаров и для формирования прайс-листов.

Движок партнерского магазина (начиная с версии 1572) предоставляет расширенные возможности по формированию товарных фидов в различных форматах.

Для получения товарного фида следует использовать URL /feed.php По-умолчанию, фид содержит все товары магазина и отображается в формате YML, пригодном для использования в большинстве российских сервисов, в том числе во всех сервисах Яндекс-а.

Выборка товаров для формирования фида осуществляется из товарного XML-файла магазина при помощи XPath-запроса. По-умолчанию, используется запрос //product, выбирающий все товары магазина без исключения.

Формирование фида осуществляется при помощи шаблонизатора vLib, в шаблон которого передаются данные, полученные из XPath-запроса (с учётом кастомизации XML). По-умолчанию, используется шаблон /theme/feed-yml.tmpl, формирующий фид в формате YML.

Формат фида

При формировании фида в шаблон передаются следующие переменные:

Переменная Назначение Источник
DATE_TIME Дата/время формирования фида в формате Y-m-d H:i web-сервер
HOST Домен магазина web-сервер
BASE_URL Базовый URL магазина web-сервер
LANG_TAG Строка из 2-х символов "<?" Предопредленная строка, позволяющая избежать ограничения vLib
SHOP_NAME Название магазина Определяется в config-local.php, если не определено, используется значенение переменной HOST
categories Массив категорий товаров, попавших в выборку XPath. Кроме названия (аттрибут name), каждой категории инкрементально назначается числовой идентификатор (аттрибут id) Формируется автоматически по результатам выборки товаров
goods Массив товаров, попавших в XPath-выборку. Аттрибутами каждого элемента являются значения из товарного XML-файла, дополненные/переопределенные значениями из кастомного XML.
Кроме этого, каждый элемент дополняется аттрибутом id, получаемым из code путем исключения всех не алфавитно-цифровых символов. И аттрибутом cat_id, обозначающим категорию, к которой относится элемент.
Так же, каждый элемент дополняется аттрибутами, установленными в хуке onFeedItem
Формируется на основе XPath выражения, задаваемого через настройку фидов FEED, или используется значение по-умолчанию //product

Кроме перечисленных выше переменных, в шаблон будут переданы все переменные, определенные в настройке фидов (FEED).

Любой фид может быть сформирован в произвольном формате при помощи кастомных шаблонов. Для этого, необходимо создать файл шаблона /theme/feed-<формат>.tmpl и открыть фид, используя в URL параметр format=<формат>.

Например, для отображения фида в формате CSV, пригодном для открытия в Excel, создадим файл шаблона /theme/feed-csv.tmpl со следующим содержанием:

Код, Артикул, Название, Цена, Ссылка
<TMPL_LOOP NAME="goods">
<TMPL_VAR NAME="code">, <TMPL_VAR NAME="article">, <TMPL_VAR NAME='trademark'> <TMPL_VAR NAME='model'>, <TMPL_VAR NAME="price">, <TMPL_VAR NAME="BASE_URL">product.php?product=<TMPL_VAR NAME='code'>,
</TMPL_LOOP>

Теперь, по URL /feed.php?format=csv откроется тот же самый фид по-умолчанию со всеми товарами магазина, но уже в формате CSV.

Тэг TMPL_HEADER

Кроме базовых тэгов vLib в шаблонах фидов допускается использование расширенного тэга TMPL_HEADER. Тэг позволяет устнавливать заголовки HTTP-ответа.

Например, в шаблоне фида по-умолчанию /theme/feed-yml.tmpl тэг используется для установки в заголовке ответе Content-Type со значением text/xml, что указывает MIME-тип возвращаемых данных и позволяет корректно обработатывать результат, отобразив его в браузере именно как xml.

<TMPL_HEADER NAME="content-type" VALUE="text/xml">

По аналогии, можно доработать пример с форматом CSV:

<TMPL_HEADER NAME="content-type" VALUE="text/csv">
<TMPL_HEADER NAME="Content-Disposition" VALUE="attachment;filename=feed.csv">
Код, Артикул, Название, Цена, Ссылка
<TMPL_LOOP NAME="goods">
<TMPL_VAR NAME="code">, <TMPL_VAR NAME="article">, <TMPL_VAR NAME='trademark'> <TMPL_VAR NAME='model'>, <TMPL_VAR NAME="price">, <TMPL_VAR NAME="BASE_URL">product.php?product=<TMPL_VAR NAME='code'>,
</TMPL_LOOP>

Особенности шаблона feed-yml.tmpl

В шаблоне feed-yml.tmpl, применяемом по-умолчанию, используются некоторые переменные, которые в базовом варианте в шаблон не передаются, и, соотвественно, на формате фида не оказывают влияния. Однако, задействовав настройку фидов (FEED), хук onFeedItem или кастомный XML можно настроить передачу этих переменных в шаблон:

Переменная Назначение Значение при отсутвии Способ передачи
COMPANY Полное наименование компании (см. документацию на YML) Интернет-магазин электрооборудования Настройка фидов FEED
bid Размер ставки (см. документацию на YML) Kастомизация XML или хук onFeedItem
typePrefix Тип / категория товара (см. документацию на YML) Дублируется из переменной category Kастомизация XML или хук onFeedItem
sales_notes см. описание элемента в документации на YML Kастомизация XML или хук onFeedItem
purchase_price Закупочная цена. Используется в PriceLabs для статегии "По маржинальности" при импорте закупочных цен. Хук onFeedItem

Настройка фидов

Движок партнерского магазина позволяет настроить использование нескольких фидов с разным товарным составом. Это облегчает создание динамических объявлений и смарт-баннеров в Яндекс.Директ.

Настройка фидов заключается в описании их массивом FEED. Определять массив FEED следует в файле /custom/feeds.php. Имя фида определяется названием ключа элемента, описывающего сам фид, в массиве FEED. Описание фида, должно состоять как минимум из элемента xpath, задающего XPath-запрос для выборки товаров фида.

Доступ к фиду по имени осуществляется по URL /feed.php?feed=<имя_фида>

Рассмотрим пример создания фида boiler-stab со специализированными стабилизаторами для газовых котлов, мощностью не более 1500ВА. Для этого создадим файл /custom/feeds.php со следующим содержимым:

<?php

$FEED['boiler-stab'] = array(
  'xpath' => "//product[(series='KOTEL' or series='APC' or series='IS-1') and power<=1500]",
);

Теперь этот фид доступен по адресу /feed.php?feed=boiler-stab и в нем присутвуют лишь специализированные стабилизаторы для газовых котлов, мощностью не более 1500ВА.

А если вы следовали инструкциям предыдущих разделов и создали CSV-формат отображения фидов (шаблон /theme/feed-csv.tmpl), то по URL /feed.php?feed=boiler-stab&format=csv можно получить фид boiler-stab и в CSV-формате.

Кроме этого, в описании фида можно задать переменные, которые будут переданы в шаблон фида. Для примера, определим для фида boiler-stab переменную COMPANY, которая уже используется в шаблоне по-умолчанию /theme/feed-yml.tmpl выражением <TMPL_VAR NAME="COMPANY">.

Меняем описание фида на:

$FEED['boiler-stab'] = array(
  'xpath' => "//product[(series='KOTEL' or series='APC' or series='IS-1') and power<=1500]",
  'COMPANY' => "Интернет-магазин специализированных стабилизаторов для газовых котлов",
);

И наш фид приобретает следующий вид:

<?xml version="1.0" encoding="windows-1251"?>
<!DOCTYPE yml_catalog SYSTEM "shops.dtd">
<yml_catalog date="2019-04-06 22:06">
<shop>
  <name>stabshop.local</name>
  <company>Интернет-магазин специализированных стабилизаторов для газовых котлов</company>
  <url>http://stabshop.local/</url>
...

Хук onFeedItem

Хук это функция, вызываемая каждый раз при наступлении определенного события. В данном случае, каждый раз при обработке очередного элемента (товара) фида вызывается php-функция onFeedItem().

Хук-функция должна быть определена в файле /custom/hooks.php

В хук-функцию onFeedItem() передаются 3 параметра: item - текущий обрабатываемый элемент, feed - название фида и format - формат фида. Причем, параметр item передается по ссылке, что позволяет изменять и дополнять его аттрибуты в хук-функции. Если был запрошен фид по-умолчанию (без указания имени), то параметр feed имеет значение NULL. Аналогично, если в запросе не указан явно формат, значение параметра format будет NULL.

В качестве примера рассмотрим ситуацию, когда мы добавляем фид в Я.Маркет и хотим прямо в фиде указать ставку клика для каждого товара, вычесленную исходя из желаемой маржи от продажи товара и известной конверсии клики/заказы.

Например, из 15% партнерского вознаграждения мы хотим тратить на клики в Я.Маркет лишь 7%, при этом известно, что средняя конверсия клики/заказы составляет 12:1, т.е. на каждые 12 кликов приходится один заказ. Тогда, ставка за клик должна составлять (7/12)% от стоимости товара.

В соотвествии с документацией на формат YML ставка клика задается аттрибутом bid ноды offer

Для начала, создадим фид market (ведь для Я.Директ нам может потребоваться другой фид, с другими ставками). Для этого добавляем в /custom/feeds.php:

$FEED['market'] = array(
  'xpath' => "//product",
);

Затем в файле /custom/hooks.php определим хук-функцию onFeedItem(), вычисляющую ставку клика для каждого товара фида market и заносящую это значение в параметр bid каждого товара:

<?php

function onFeedItem(&$item, $feed, $format) {
  if ($feed == "market")
    $item['bid'] = (int)($item['price'] * 0.07 / 12 / 30 * 100);
}

Дополнительные делитель 30 и множитель 100 появились в формуле из-за того, что аттрибут bid должен быть выражен в "условных центах" (a 1у.е. Я.Маркета = 30руб.)

Теперь добавляем в шаблон /theme/feed-yml.tmpl использование переменной bid как одноименного аттрибута ноды offer. Причем, используем условие TMPL_IF, поскольку этим же шаблоном будут генерироваться и фиды без переменной bid:

...
    <offer ... <TMPL_IF NAME="bid">bid="<TMPL_VAR NAME='bid'>"</TMPL_IF>>
...

Проверяем получившийся результат по URL /feed.php?feed=market:

...
    <offer id="is350" type="vendor.model" available="true" bid="93">
...
    <offer id="kotel400" type="vendor.model" available="true" bid="65">
...

Все отлично, можно добавлять в Я.Маркет фид /feed.php?feed=market, ставки кликов в котором уже прописаны.

Хук onFeed

Хук onFeed() вызывается, когда массив товаров для фида полностью сформирован и готов к отображению при помощи указанного шаблона или шаблона по-умолчанию.

Хук может быть использован для обработки всего массива товаров, например, для его сортировки.

В хук-функцию onFeed() передаются 3 параметра: goods - массив товаров, feed - название фида и format - формат фида. Причем, параметр goods передается по ссылке, что позволяет изменять и дополнять этот массив в хук-функции. Если был запрошен фид по-умолчанию (без указания имени), то параметр feed имеет значение NULL. Аналогично, если в запросе не указан явно формат, значение параметра format будет NULL.

В качестве примера разберём способ создания прайс-листа магазина на основе фида. Для этого, сформируем новый формат фида, например price-list, создав файл /theme/feed-price-list.tmpl со следующим содержимым:

<TMPL_HEADER NAME="content-type" VALUE="text/csv">
<TMPL_HEADER NAME="Content-Disposition" VALUE="attachment;filename=price-list.csv">
Категория, Торговая марка, Название, Цена, Артикул
<TMPL_LOOP NAME="goods">
<TMPL_VAR NAME="category">,<TMPL_VAR NAME='trademark'>,<TMPL_VAR NAME='trademark'> <TMPL_VAR NAME='model'>,<TMPL_VAR NAME="price">,<TMPL_VAR NAME="article">,
</TMPL_LOOP>

Затем, в файл /custom/hooks.php добавляем хук-функцию onFeed(), производящую сортировку товаров в массиве $goods по аттрибутам элементов cat_id, phases, trademark, series, power. Причем сортировка осуществляется исключительно для формата price-list и, в процессе сортировки отключаются сообщения об ошибках, поскольку нужных для сортировки аттрибутов может не оказаться у некоторых элементов:

function onFeed(&$goods, $feed, $format) {		// Пример использует анонимную функцию и будет работать лишь на PHP >= 5.4
  if ($format == 'price-list') {			// Сортировать будем лишь фиды в формате отображения "price-list"
    $de = ini_get('display_errors');			// Запоминаем настройку отображения ошибок
    ini_set('display_errors', false);			// Устанавливаем запрет на отображение ошибок
    usort($goods, function($a, $b) {			// Сортируем массив $goods по cat_id, phases, trademark, series, power
      if ($a['cat_id'] == $b['cat_id']) {
        if ($a['phases'] == $b['phases']) {
          if ($a['trademark'] == $b['trademark']) {
            if ($a['series'] == $b['series']) {
              if ($a['power'] == $b['power']) {
                return 0;
              } else
                return ($a['power'] < $b['power']) ? -1 : 1;
            } else
              return ($a['series'] < $b['series']) ? -1 : 1;
          } else
            return ($a['trademark'] < $b['trademark']) ? -1 : 1;
          } else
            return ($a['phases'] < $b['phases']) ? -1 : 1;
      } else
        return ($a['cat_id'] < $b['cat_id']) ? -1 : 1;
    });
    ini_set('display_errors', $de);			// Восстанавливаем настройку отображения ошибок
  }
}

Теперь, при открытии URL /feed.php?format=price-list, мы получим запрос на сохранение CSV-файла price-list.csv, который, после открытия его в Excel, будет выглядеть следующим образом: