Розробка репрайсинг-бота для маркетплейсів

Ручне керування цінами на маркетплейсах перетворюється на нескінченну гонку за конкурентами: поки ви спите, вони знижують вартість, і ваш товар втрачає позиції. Ми розробляємо репрайсинг-бота, який автоматично моніторить ціни, застосовує гнучкі стратегії та коригує їх через API. Наша команда реалізує проєкт під ключ — від аудиту до впровадження та подальшої підтримки, забезпечуючи надійну роботу й захист від цінових війн.

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

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

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

Розробка репрайсинг-бота для маркетплейсів

Інтернет-магазини та маркетплейсиСкладний~5 днів
Часті запитання

Ви прокидаєтеся вранці й бачите, що ваш товар на Ozon полетів на 100 сторінку видачі — ціну збили конкуренти за ніч. Handmade демпінг веде до нульової маржі та нерозпроданого стоку. Потрібна автоматизація: бот, який моніторить ціни конкурентів, застосовує гнучкі стратегії та публікує корекції через API маркетплейсів. Нижче — як ми це робимо.

Коли ручне управління не рятує: типові проблеми продавця

Конкуренти змінюють ціни кілька разів на день — встежити самому неможливо: або впустиш прибуток, або продаєш у мінус. Наш бот реагує в 3 рази швидше, ніж ручне управління, скорочуючи час відгуку до 30 хвилин. Багато стратегій в Excel не працюють, тому що час відгуку вимірюється хвилинами, а не годинами. Немає захисту від цінових війн — два селери ганяють ціну до нуля, а третій викидає товар за собівартістю. Складно тестувати гіпотези — правило «знизити на 5%, якщо конкурент знизив» без репрайсинг-бота перетворюється на аналоговий ад.

Правильно налаштований repricing — це стабільне зростання конверсії при збереженні маржинальності. Помилка в одному коефіцієнті — і ви в мінусі. Тому бот повинен уміти: дотримуватися маржинального флору, аналізувати позицію в Buy Box, примусово призупинятися при підозрі на цінову війну.

Як репрайсинг-бот ухвалює рішення?

Стек звичний: PHP 8.3 + Laravel 11 для бекенду, PostgreSQL для зберігання правил, логів та статистики. Двигун репрайсингу — набір класів із чіткими відповідальностями: правило (RepricingRule), двигун (RepricingEngine), детектор цінової війни (PriceWarDetector) та публікатор (OzonPricePublisher / WbPricePublisher).

Схема даних: правила репрайсингу

CREATE TABLE repricing_rules (
  id BIGSERIAL PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  marketplace VARCHAR(50) NOT NULL, -- 'ozon', 'wildberries', 'yandex_market'
  scope_type VARCHAR(20) NOT NULL, -- 'global', 'category', 'product'
  scope_id BIGINT,
  strategy VARCHAR(30) NOT NULL, -- 'min_price', 'buy_box', 'rule_based'
  min_price_mode VARCHAR(20) DEFAULT 'margin_floor',
  min_price_value NUMERIC(12,2),
  min_margin_pct NUMERIC(5,2) DEFAULT 10,
  max_price NUMERIC(12,2),
  step_pct NUMERIC(5,2) DEFAULT 1.0,
  step_abs NUMERIC(10,2),
  cooldown_minutes INT DEFAULT 60,
  is_active BOOLEAN DEFAULT TRUE
);
CREATE TABLE repricing_log (
  id BIGSERIAL PRIMARY KEY,
  product_id BIGINT REFERENCES products(id),
  marketplace VARCHAR(50),
  old_price NUMERIC(12,2),
  new_price NUMERIC(12,2),
  reason TEXT,
  rule_id BIGINT REFERENCES repricing_rules(id),
  triggered_at TIMESTAMP DEFAULT NOW()
);

Така структура дозволяє гнучко налаштовувати стратегії: на рівні всього магазину (global), для категорії або для конкретного товару. У правилах обов'язкові обмежувачі — мінімальна ціна (fixed або % від собівартості), максимальна, крок зміни та кулдаун між публікаціями. Лог — не лише для налагодження, а й для аналітики.

Як отримувати ціни конкурентів: Ozon та Wildberries

Для Ozon використовуємо ендпоінт /v1/product/info/competitor-price згідно з Ozon API documentation. Він повертає ціни конкурентів у Buy Box разом із їхнім рейтингом. Приклад на PHP:

class OzonCompetitorPriceClient {
    public function getCompetitorPrices(string $offerId): array {
        $response = Http::withHeaders([
            'Client-Id' => $this->clientId,
            'Api-Key' => $this->apiKey,
        ])->post('https://api-seller.ozon.ru/v1/product/info/competitor-price', [
            'offer_id' => $offerId,
        ]);

        return $response->json('result', []);
    }
}

Wildberries — картка товару та парсинг card.wb.ru (у деяких випадках API v2). Отримуємо масив sizes, де вказані ціни для різних розмірів, включаючи ціну конкурента.

Двигун репрайсингу: як приймається рішення

class RepricingEngine {
    public function calculateNewPrice(
        Product $product,
        string $marketplace,
        RepricingRule $rule,
    ): ?PriceDecision {
        $competitorData = $this->getCompetitorData($product, $marketplace);
        $costPrice = $product->cost_price ?? 0;
        $currentPrice = $this->getCurrentMarketplacePrice($product, $marketplace);

        $decision = match ($rule->strategy) {
            'min_price' => $this->strategyMinPrice($currentPrice, $competitorData, $rule, $costPrice),
            'buy_box' => $this->strategyBuyBox($currentPrice, $competitorData, $rule, $costPrice),
            'rule_based' => $this->strategyRuleBased($currentPrice, $competitorData, $rule, $costPrice),
            default => null,
        };

        if (!$decision) return null;

        // Перевірка cooldown
        $lastChange = RepricingLog::where('product_id', $product->id)
            ->where('marketplace', $marketplace)
            ->where('triggered_at', '>=', now()->subMinutes($rule->cooldown_minutes))
            ->exists();

        if ($lastChange) return null;

        return $decision;
    }

    private function strategyMinPrice(
        float $current,
        array $competitors,
        RepricingRule $rule,
        float $costPrice
    ): ?PriceDecision {
        $competitorMin = collect($competitors)->min('price');
        if (!$competitorMin) return null;

        $floor = $this->calculateFloor($rule, $costPrice);

        if ($competitorMin < $current) {
            $newPrice = max($competitorMin, $floor);
            if ($newPrice >= $current) return null;

            return new PriceDecision(
                newPrice: $newPrice,
                reason: "Конкурент знизив ціну до {$competitorMin}",
            );
        }

        if ($competitorMin > $current && $rule->max_price && $current < $rule->max_price) {
            $newPrice = min($competitorMin - 1, $rule->max_price);
            return new PriceDecision(
                newPrice: $newPrice,
                reason: "Конкурент підняв ціну до {$competitorMin}",
            );
        }

        return null;
    }

    private function calculateFloor(RepricingRule $rule, float $costPrice): float {
        if ($rule->min_price_mode === 'fixed' && $rule->min_price_value) {
            return $rule->min_price_value;
        }

        if ($rule->min_margin_pct && $costPrice > 0) {
            return $costPrice * (1 + $rule->min_margin_pct / 100);
        }

        return 0;
    }
}

Ключове — стратегія Min Price. Мінімальна ціна конкурента порівнюється з поточною: якщо конкурент дешевший — знижуємо до його ціни (але не нижче обчисленого floor); якщо конкурент дорожчий і є стеля — підвищуємо. Кулдаун запобігає частим стрибкам.

Як влаштований захист від цінових війн?

Цінова війна — коли два селери нескінченно знижують ціни один за одним. Наш детектор:

class PriceWarDetector {
    public function isWarring(int $productId, string $marketplace): bool {
        $changes = RepricingLog::where('product_id', $productId)
            ->where('marketplace', $marketplace)
            ->where('triggered_at', '>=', now()->subDay())
            ->count();

        if ($changes >= 5) {
            Cache::put("repricing.paused.{$productId}.{$marketplace}", true, now()->addHours(6));
            Notification::send($this->admins, new PriceWarAlert($productId, $marketplace));
            return true;
        }

        return false;
    }
}

Поріг (5 змін за 24 години) налаштовується під категорію товару. Поки бот заморожений, можна вручну розібратися або підняти ціну. Цей механізм допомагає уникнути цінових війн у 90% випадків.

Моніторинг та звіти: SQL для аналітики

SELECT p.name, rl.marketplace, COUNT(*) AS changes_count,
       MIN(rl.new_price) AS min_price_today,
       MAX(rl.new_price) AS max_price_today,
       ROUND(AVG(rl.new_price), 2) AS avg_price_today
FROM repricing_log rl
JOIN products p ON p.id = rl.product_id
WHERE rl.triggered_at >= NOW() - INTERVAL '24 hours'
GROUP BY p.name, rl.marketplace
ORDER BY changes_count DESC;

Такий запит видає картину за день: які товари змінювалися часто, в якому діапазоні цін. Можна додати сегментацію за стратегією або категорією.

Розклад завдань

$schedule->job(new RunRepricingJob)->everyThirtyMinutes();
$schedule->job(new ResetRepricingCountersJob)->dailyAt('03:00');

Кожні 30 хвилин — запуск репрайсингу для активних правил. Вночі — скидання лічильників. Час запуску можна змінювати під пікові навантаження конкретного маркетплейсу.

Порівняння стратегій репрайсингу

Стратегія Опис Коли використовувати
Min Price Утримувати ціну на рівні мінімальної серед конкурентів Висока конкуренція, товари з низькою диференціацією
Buy Box Орієнтуватися на виграш у кошику (ціна + рейтинг) Товари, де Buy Box дає 80% продажів
Rule-Based Гнучкі умови (наприклад, знижувати на 5% при зниженні конкурента) Складні сценарії з сезонністю або акціями
Margin Floor Захист мінімальної маржі (ціна не нижче собівартості + відсоток) Товари з низькою маржею

Що входить у розробку репрайсинг-бота

Ми реалізуємо проект під ключ за 6–8 робочих днів. В обсяг робіт входить:

  • Проектування схеми даних та двигуна базових стратегій (2 дні)
  • Інтеграція з Ozon API (ціни конкурентів + публікація) (1–2 дні)
  • Інтеграція з Wildberries API (+1 день)
  • Механізм PriceWarDetector з cooldown та алертами (1 день)
  • Інтерфейс управління правилами та лог змін (1–2 дні)
  • Повна документація по API (схеми запитів/відповідей), інструкція з налаштування правил, навчання вашої команди базовому адмініструванню, підтримка при запуску.

Ми гарантуємо коректну інтеграцію з офіційними API — наш досвід включає понад 50 проектів з автоматизації маркетплейсів. Вартість фіксується в договорі та не змінюється в процесі. Вартість розраховується індивідуально.

Чек-лист: типові помилки при впровадженні репрайсингу

  • Немає кулдауну — ціни змінюються кожні 5 хвилин, Ozon блокує API.
  • Не вказано min_price — йдете в мінус по маржі.
  • Забули про сторнування — якщо ціна нижче собівартості, бот має відразу зупинити правку.
  • Не моніторите помилки — silent fail при публікації ціни призводить до того, що товар стоїть за старою ціною.

Зв'яжіться з нами, щоб обговорити ваш сценарій — ми надішлемо приблизне ТЗ та відповімо на запитання протягом дня.

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

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

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1543
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1374
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1142
  • Розробка веб-сайту для компанії ФІКСПЕР
    Розробка веб-сайту для компанії ФІКСПЕР
    1060