Реалізація експорту товарів із сайту в YML-фід

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація експорту товарів із сайту в YML-фід
Середня
~3-5 робочих днів
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація експорту товарів у YML-фід

YML (Yandex Market Language) — XML-формат, який Яндекс.Маркет вимагає для завантаження каталогу. Правильно сформований фід забезпечує індексацію без помилок, коректне відображення офертів та допуск до платних розміщень. Неправильний фід — це відкинені товари, штрафні бали магазину та вивалювання з пошуку.

Структура YML та вимоги Яндекс.Маркету

Формат описаний у офіційній документації. Мінімальна структура:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE yml_catalog SYSTEM "shops.dtd">
<yml_catalog date="2024-01-15 10:00">
  <shop>
    <name>Мій магазин</name>
    <company>ТОВ Компанія</company>
    <url>https://example.com</url>
    <currencies>
      <currency id="RUR" rate="1"/>
    </currencies>
    <categories>
      <category id="10">Електроніка</category>
      <category id="11" parentId="10">Смартфони</category>
    </categories>
    <offers>
      <offer id="12345" available="true">
        <url>https://example.com/product/12345</url>
        <price>29990</price>
        <currencyId>RUR</currencyId>
        <categoryId>11</categoryId>
        <picture>https://example.com/img/12345.jpg</picture>
        <name>Смартфон Samsung Galaxy S24</name>
        <vendor>Samsung</vendor>
        <description>...</description>
        <param name="Колір">Чорний</param>
        <param name="Пам'ять">256 GB</param>
      </offer>
    </offers>
  </shop>
</yml_catalog>

Критичні поля для допуску: url, price, currencyId, categoryId, name. Поле available впливає на відображення — товари з false виключаються з пошуку, але зберігаються в історії цін.

Архітектура генератора фіду

Для невеликих каталогів (до 10 000 товарів) фід можна генерувати на льоту. Для крупних — тільки через фонову задачу з записом на диск або в CDN.

Схема роботи:

Cron/Queue → Builder → XML Writer → Storage (disk/S3) → Public URL

Реалізація на PHP (Laravel):

class YmlFeedBuilder
{
    public function build(string $outputPath): void
    {
        $writer = new XMLWriter();
        $writer->openUri($outputPath);
        $writer->startDocument('1.0', 'UTF-8');
        $writer->writeDtd('yml_catalog', null, 'shops.dtd');

        $writer->startElement('yml_catalog');
        $writer->writeAttribute('date', now()->format('Y-m-d H:i'));

        $this->writeShopInfo($writer);
        $this->writeCurrencies($writer);
        $this->writeCategories($writer);
        $this->writeOffers($writer);

        $writer->endElement();
        $writer->endDocument();
        $writer->flush();
    }

    private function writeOffers(XMLWriter $writer): void
    {
        $writer->startElement('offers');

        Product::with(['category', 'attributes', 'images'])
            ->where('active', true)
            ->where('price', '>', 0)
            ->chunk(500, function ($products) use ($writer) {
                foreach ($products as $product) {
                    $this->writeOffer($writer, $product);
                }
            });

        $writer->endElement();
    }
}

Використання chunk() обов'язково — спроба завантажити 50 000+ товарів одним запитом гарантовано дасть OOM.

Типи офертів

Яндекс.Маркет розрізняє кілька типів, кожен з обов'язковими полями:

Тип Застосування Обов'язкові додаткові поля
vendor.model Електроніка, техніка vendor, model
book Книги author, isbn
audiobook Аудіокниги author, publisher
medicine Ліки vendor, registration-number
artist.title Музика, кіно artist, title
tour Тури worldRegion, country
За замовчуванням Все інше

Для більшості інтернет-магазинів працює vendor.model або тип за замовчуванням.

Валідація фіду

Перед відправкою в Яндекс.Маркет фід потрібно перевіряти локально. Використовуйте Feed Validator або схему shops.dtd.

Власна валідація на етапі збірки:

class YmlFeedValidator
{
    public function validate(string $filePath): array
    {
        $errors = [];
        $dom = new DOMDocument();

        if (!$dom->load($filePath)) {
            return ['XML parse error'];
        }

        $offers = $dom->getElementsByTagName('offer');
        foreach ($offers as $offer) {
            $id = $offer->getAttribute('id');

            if (!$offer->getElementsByTagName('price')->length) {
                $errors[] = "Офер {$id}: відсутня ціна";
            }
            if (!$offer->getElementsByTagName('url')->length) {
                $errors[] = "Офер {$id}: відсутнє посилання";
            }
            // Перевірка довжини description (Яндекс обрізає після 3000 символів)
            $desc = $offer->getElementsByTagName('description')->item(0);
            if ($desc && mb_strlen($desc->textContent) > 3000) {
                $errors[] = "Офер {$id}: опис занадто довгий";
            }
        }

        return $errors;
    }
}

Розписання оновлення

Частота залежить від динаміки каталогу:

  • Ціни та остатки — змінюються часто: рекомендується регенерація кожні 1–4 години
  • Атрибути та описи — змінюються повільно: достатньо 1 раз на день
  • Нові товари — негайно або при наступному годинному циклі

Приклад розписання в Laravel (app/Console/Kernel.php):

$schedule->job(new GenerateYmlFeedJob)->everyFourHours();

Оптимізація розміру фіду

Яндекс.Маркет рекомендує не перевищувати 500 МБ на фід. Якщо каталог більший — розбивайте по категоріям та реєструйте кілька фідів у особистому кабінеті.

Зниження розміру без втрати якості:

  • Виключати товари без ціни (WHERE price > 0)
  • Виключати неактивні категорії
  • Обрізати description до 1000–1500 символів
  • Стискати фід gzip (Content-Encoding: gzip) — Яндекс підтримує
// Стиснення готового фіду
$source = storage_path('app/public/feed.xml');
$compressed = storage_path('app/public/feed.xml.gz');

$fp = gzopen($compressed, 'w9');
gzwrite($fp, file_get_contents($source));
gzclose($fp);

Терміни реалізації

  • Базовий генератор з типом за замовчуванням: 1–2 дні
  • Додавання типізованих офертів (vendor.model): +0.5 дня
  • Валідатор + логування помилок: +0.5 дня
  • Налаштування cron + публічний URL: +0.5 дня

Загалом типовий проект: 2–3 робочих дні.