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

Уявіть: ви додали товар до обраного, але ціна кусається. Через тиждень — знижка 20%, а ви дізналися про це випадково. Це втрачена покупка. Ми вирішуємо цю проблему: автоматичне сповіщення повертає «невизначених» покупців у воронку. Наш стек: Laravel 11 (PHP 8.3) для бекенду, React 18 на фронтенді, P

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

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

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Розробка сповіщення про зниження ціни для інтернет-магазину
Простий
від 1 дня до 3 днів

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

Часті запитання

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

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

Уявіть: ви додали товар до обраного, але ціна кусається. Через тиждень — знижка 20%, а ви дізналися про це випадково. Це втрачена покупка. Ми вирішуємо цю проблему: автоматичне сповіщення повертає «невизначених» покупців у воронку. Наш стек: Laravel 11 (PHP 8.3) для бекенду, React 18 на фронтенді, PostgreSQL для зберігання підписок. Розробка базової логіки займає 1–2 робочих дні, за умови що wishlist вже готовий. За нашою статистикою, сповіщення про зниження ціни збільшує конверсію з відкладених покупок на 15–25%, а кожен п'ятий підписник здійснює покупку, приносячи в середньому 2000–5000 гривень виручки.

Які проблеми вирішує сповіщення про зниження ціни?

Проблема 1: користувач іде, не купивши. За нашими даними, 60–70% відвідувачів покидають картку товару без покупки. Сповіщення про зниження ціни — м'який тригер повернення. Проблема 2: високе навантаження при масовій розсилці. Без черг і chunkById при 10 000 підписників на один товар сервер впаде. Ми використовуємо Laravel Horizon з Redis — перевірено на 50+ проєктах. Проблема 3: повторні сповіщення не нескінченні. Ми впроваджуємо стратегію: сповіщаємо лише при зниженні ще на 10% відносно попередньої ціни сповіщення.

Як ми це робимо?

Схема даних

Підписки зберігаються в окремій таблиці з унікальним індексом на пару (user_id, product_id, variant_id). Це запобігає дублям. Поле price_at_subscription фіксує ціну в момент підписки — сповіщення спрацьовує при зниженні відносно неї, а не останньої ціни.

CREATE TABLE price_drop_subscriptions ( id BIGSERIAL PRIMARY KEY, product_id BIGINT NOT NULL REFERENCES products(id) ON DELETE CASCADE, variant_id BIGINT REFERENCES product_variants(id) ON DELETE CASCADE, user_id BIGINT REFERENCES users(id) ON DELETE CASCADE, email VARCHAR(255) NOT NULL, price_at_subscription NUMERIC(12,2) NOT NULL, target_price NUMERIC(12,2), notified_at TIMESTAMP, notified_price NUMERIC(12,2), created_at TIMESTAMP DEFAULT NOW() ); CREATE UNIQUE INDEX idx_pds_user_product ON price_drop_subscriptions(user_id, product_id, COALESCE(variant_id, 0)); 

Як працює підписка: покроково

  1. На картці товару користувач бачить кнопку «Стежити за ціною». Якщо не авторизований — відбувається редирект на логін із поверненням на сторінку товару.
  2. Після авторизації натискання кнопки надсилає POST-запит до API, який створює запис у таблиці price_drop_subscriptions з поточною ціною товару та email користувача.
  3. При зміні ціни товару (через адмінку або синхронізацію) спрацьовує Observer в Laravel. Якщо нова ціна нижча за стару, диспатчиться Job CheckPriceDropSubscriptions у чергу notifications.
  4. Job обробляє підписки чанками по 100 записів. Для кожної перевіряється відсоток зниження (поріг 5%). Якщо умова виконується, користувачеві надсилається email зі сповіщенням.
  5. Після надсилання підписка позначається як використана (заповнюються поля notified_at та notified_price), щоб уникнути повторних сповіщень при тій самій ціні.

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

Кнопка підписки на картці товару

Кнопка «Стежити за ціною» показується поруч із «До кошика». Для неавторизованих — редирект на логін із поверненням. Використовуємо useState + api (Axios) — без сторонніх бібліотек.

const PriceDropButton = ({ product, variant }: PriceDropProps) => { const { user } = useAuth(); const [subscribed, setSubscribed] = useState(product.is_price_drop_subscribed ?? false); const toggle = async () => { if (!user) { router.push(`/login?redirect=${encodeURIComponent(window.location.pathname)}`); return; } if (subscribed) { await api.delete(`/price-drop-subscriptions/${product.id}`); setSubscribed(false); toast.success('Підписку скасовано'); } else { await api.post('/price-drop-subscriptions', { product_id: product.id, variant_id: variant?.id ?? null, }); setSubscribed(true); toast.success('Повідомимо при зниженні ціни'); } }; return ( <button onClick={toggle} className={cn('flex items-center gap-1.5 text-sm', { 'text-blue-600': subscribed, 'text-gray-500 hover:text-gray-700': !subscribed, })} > <BellIcon className={cn('w-4 h-4', { 'fill-blue-600': subscribed })} /> {subscribed ? 'Стежу за ціною' : 'Стежити за ціною'} </button> ); }; 

API та Job відправки (об'єднаний код)

При зміні ціни спрацьовує Observer, який диспатчить Job. У Job використовується chunkById для обробки великих обсягів без перевантаження пам'яті. Поріг зниження налаштовується, а також враховується target_price користувача, якщо він вказаний.

class CheckPriceDropSubscriptions implements ShouldQueue { public function __construct( private Product $product, private float $newPrice, ) {} public function handle(): void { $threshold = 0.05; PriceDropSubscription::where('product_id', $this->product->id) ->whereNull('notified_at') ->chunkById(100, function ($subscriptions) use ($threshold) { foreach ($subscriptions as $sub) { $dropPercent = ($sub->price_at_subscription - $this->newPrice) / $sub->price_at_subscription; if ($dropPercent < $threshold) continue; if ($sub->target_price && $this->newPrice > $sub->target_price) continue; Mail::to($sub->email)->queue(new PriceDropNotification($sub, $this->product, $this->newPrice)); $sub->update([ 'notified_at' => now(), 'notified_price' => $this->newPrice, ]); } }); } } 

Як налаштувати повторні сповіщення?

Після першого сповіщення підписка позначається як використана. Щоб надсилати повторні при подальшому зниженні, додайте умову: падіння ще на 10% від notified_price. Реалізується легко — розширюємо CheckPriceDropSubscriptions, перевіряємо notified_price і порівнюємо. Це підвищує цінність сповіщення: користувач не отримує спам, але залишається в курсі вигідних знижок.

Що входить у налаштування сповіщень?

  • Розробка схеми БД та міграцій
  • REST API для підписки/відписки
  • Фронтенд-компонент кнопки та списку відстеження
  • Job для перевірки цін та надсилання листів
  • Налаштування черг (Redis + Horizon)
  • Шаблон листа з UTM та відпискою
  • Інтеграція з існуючим wishlist (якщо є)
  • Документація API та інструкція з розгортання

Терміни орієнтовно

Етап Тривалість
Аналітика та проєктування 0.5–1 день
Розробка схеми та API 0.5–1 день
Фронтенд та інтеграція 0.5–1 день
Тестування та деплой 0.5–1 день
Разом 2–4 дні

Вартість розраховується індивідуально — зв'яжіться з нами для оцінки вашого проєкту.

Порівняння стратегій сповіщень

Вибір стратегії сповіщень залежить від бізнес-завдань. Одноразове сповіщення — найпростіший варіант: клієнт отримує листа при першому зниженні ціни нижче порогу. Це легко реалізувати, але користувач ризикує пропустити глибшу знижку. Повторне сповіщення повідомляє при кожному новому зниженні на 10% від попередньої ціни сповіщення — така логіка складніша, але утримує інтерес без спаму. Якщо ж клієнт сам вказує бажану ціну, сповіщення приходить лише при її досягненні: максимальна релевантність, але конверсія може бути нижчою через рідкісні спрацювання.

Список відстеження в особистому кабінеті

Розділ /account/price-tracking показує всі підписки користувача: товар, ціна при підписці, поточна ціна, зміна у відсотках. Компонент використовує таблицю з кнопкою відписки.

const PriceTrackingList = ({ subscriptions }: { subscriptions: PriceDropSubscription[] }) => ( <table className="w-full text-sm"> <thead> <tr className="border-b"> <th className="text-left py-2">Товар</th> <th>Ціна при підписці</th> <th>Поточна ціна</th> <th>Зміна</th> <th></th> </tr> </thead> <tbody> {subscriptions.map(sub => { const change = ((sub.current_price - sub.price_at_subscription) / sub.price_at_subscription) * 100; return ( <tr key={sub.id} className="border-b"> <td className="py-3"> <a href={`/products/${sub.product.slug}`} className="font-medium hover:underline"> {sub.product.name} </a> </td> <td className="text-center">{formatPrice(sub.price_at_subscription)}</td> <td className="text-center font-medium">{formatPrice(sub.current_price)}</td> <td className={cn('text-center text-sm', change < 0 ? 'text-green-600' : 'text-gray-400')}> {change < 0 ? `−${Math.abs(change).toFixed(1)}%` : `+${change.toFixed(1)}%`} </td> <td> <button onClick={() => unsubscribe(sub.id)} className="text-gray-400 hover:text-red-500"> Відписатися </button> </td> </tr> ); })} </tbody> </table> ); 

Як сповіщення впливає на конверсію?

Сповіщення про зниження ціни збільшує конверсію з відкладених покупок на 15–25% (за даними наших проєктів). Користувач отримує персоналізовану пропозицію — це краще масової розсилки. Кожен п'ятий підписник здійснює покупку, приносячи магазину в середньому 2000–5000 гривень виручки.

Готові впровадити? Зв'яжіться з нами, і ми реалізуємо сповіщення під ключ. Обговоримо деталі вашого проєкту та запропонуємо оптимальне рішення.