Отметим: когда товар заканчивается на складе — 80% покупателей уходят к конкурентам и не возвращаются. Форма подписки «Уведомить о поступлении» превращает эту потерю в лид: вы получаете контакт заинтересованного человека и можете вернуть его ровно в тот момент, когда товар снова в наличии. Мы реализуем Back in Stock под ключ за 1-2 рабочих дня, с интеграцией в вашу CRM и любыми каналами связи (email, Telegram, SMS). Наши инженеры имеют 5+ лет опыта в e-commerce, гарантируем стабильную работу уведомлений даже при пиковых нагрузках. Свяжитесь с нами для оценки проекта — и получите консультацию бесплатно.
Как работает уведомление Back in Stock?
Система состоит из нескольких модулей: форма на фронтенде, API для подписки, очередь задач для отправки уведомлений и механизм защиты от дубликатов. Рассмотрим каждый на примере стека Laravel + React, но реализация возможна на любой платформе.
Схема данных
CREATE TABLE back_in_stock_requests ( 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 SET NULL, email VARCHAR(255) NOT NULL, notified_at TIMESTAMP, created_at TIMESTAMP DEFAULT NOW() ); CREATE UNIQUE INDEX idx_bis_email_product ON back_in_stock_requests(email, product_id, COALESCE(variant_id, 0)) WHERE notified_at IS NULL; Уникальный индекс предотвращает дублирование подписок от одного email на один товар/вариант, пока уведомление не отправлено.
Форма подписки
Форма показывается вместо кнопки «В корзину» при stock = 0:
const BackInStockForm = ({ product, variant }: BackInStockProps) => { const { user } = useAuth(); const [submitted, setSubmitted] = useState(false); const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm({ defaultValues: { email: user?.email ?? '' }, }); const onSubmit = async (data: { email: string }) => { await api.post('/back-in-stock', { product_id: product.id, variant_id: variant?.id ?? null, email: data.email, }); setSubmitted(true); }; if (submitted) { return ( <div className="flex items-center gap-2 text-green-600 text-sm"> <CheckIcon className="w-4 h-4" /> <span>Мы сообщим, когда товар появится в наличии</span> </div> ); } return ( <form onSubmit={handleSubmit(onSubmit)} className="space-y-2"> <p className="text-sm text-gray-600">Товара нет в наличии. Оставьте email — уведомим при поступлении.</p> <div className="flex gap-2"> <input type="email" placeholder="[email protected]" className="flex-1 border rounded px-3 py-2 text-sm" {...register('email', { required: true, pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ })} /> <Button type="submit" size="sm" loading={isSubmitting}> Уведомить </Button> </div> {errors.email && <p className="text-red-500 text-xs">Введите корректный email</p>} </form> ); }; API-эндпоинт подписки
public function subscribe(Request $request): JsonResponse { $request->validate([ 'product_id' => 'required|exists:products,id', 'variant_id' => 'nullable|exists:product_variants,id', 'email' => 'required|email|max:255', ]); // Проверяем, что товар действительно не в наличии $product = Product::find($request->product_id); if ($product->stock > 0) { return response()->json(['message' => 'Товар уже в наличии'], 422); } BackInStockRequest::firstOrCreate([ 'product_id' => $request->product_id, 'variant_id' => $request->variant_id, 'email' => strtolower($request->email), 'notified_at' => null, ], [ 'user_id' => $request->user()?->id, ]); return response()->json(['message' => 'Подписка оформлена']); } Почему важно уведомлять о поступлении?
Товар с нулевым остатком — не потерянный спрос, а отложенный. Уведомления возвращают до 30% таких клиентов. Подписка через форму эффективнее всплывающих окон в 2–3 раза по конверсии, так как не прерывает пользователя насильно. Кроме того, аналитика подписок помогает прогнозировать спрос: товары с большим количеством ожиданий — сигнал к дозаказу у поставщика.
Как выбрать канал уведомления?
| Канал | Конверсия | Затраты | Скорость |
|---|---|---|---|
| 15-25% | Низкие | Медленный | |
| Telegram | 30-40% | Средние | Быстрый |
| SMS | 50-60% | Высокие | Мгновенный |
Email — экономичный вариант для массовых уведомлений, но открываемость ниже. Telegram и SMS дают более высокую конверсию, особенно для срочных товаров. Мы подключаем любой канал по вашему желанию.
Автоматическая отправка при пополнении склада
Триггер срабатывает при обновлении остатков. Это может происходить через импорт из 1С/ERP, ручное обновление в admin-панели или API поставщика. Используем очередь (Redis/Beanstalkd) для асинхронной отправки, чтобы не блокировать основной поток.
// Observer на модели Product — объединяем проверку и отправку class ProductObserver { public function updated(Product $product): void { if ($product->isDirty('stock') && $product->stock > 0 && $product->getOriginal('stock') === 0) { NotifyBackInStockSubscribers::dispatch($product)->onQueue('notifications'); } } } class NotifyBackInStockSubscribers implements ShouldQueue { public function handle(): void { $requests = BackInStockRequest::where('product_id', $this->product->id) ->whereNull('variant_id') ->whereNull('notified_at') ->get(); foreach ($requests as $request) { Mail::to($request->email)->queue(new BackInStockNotification($this->product, $request)); $request->update(['notified_at' => now()]); } } } Особенности для товаров с вариантами
Если товар имеет размеры или цвета, уведомление должно учитывать конкретный вариант. В схеме данных поле variant_id позволяет подписываться на нужную модификацию. При поступлении только выбранного варианта уведомление получат только те, кто ждал именно его. Это повышает релевантность и конверсию.
Email-уведомление
Письмо содержит:
- Фото и название товара
- Текущую цену с учётом скидок
- Прямую ссылку на товар с UTM-меткой
utm_source=back_in_stock - Предупреждение «Количество ограничено — успейте купить»
Письмо отправляется один раз — notified_at фиксирует факт отправки. Повторных уведомлений не бывает.
Отписка
Ссылка «Отписаться» в письме ведёт на /back-in-stock/unsubscribe?token={token}. Токен — HMAC-подпись от email и product_id, что исключает подделку. После перехода подписка удаляется без необходимости входа.
Аналитика
Метрики блока:
| Метрика | Описание |
|---|---|
| Активные подписки | Количество email, ожидающих поступления товара |
| Конверсия в покупку | % подписчиков, купивших товар после уведомления (через UTM) |
| Среднее время ожидания | От подписки до поступления товара |
| Доля купивших | % успевших купить товар до повторного исчезновения |
Товары с высоким числом подписок — приоритет для дозаказа у поставщика. Например, если на товар подписалось 50 человек, а поступило 10 единиц, стоит увеличить закупку.
Что делать, если подписка не сработала?
Редкая, но возможная ситуация: товар поступил, но уведомление не отправилось. Чаще всего причина — сбой в очереди задач или неверное состояние склада. Мы настраиваем мониторинг (алерты в Telegram/Slack) и автоматический повтор отправки. В базовой реализации очередь использует retry-механизмы Laravel: если письмо не отправлено, оно повторяется через 60 секунд, до 3 попыток.
Что входит в работу
Разработка Back in Stock под ключ включает:
- Интеграцию формы подписки в карточку товара
- API для сохранения подписок с валидацией
- Очередь уведомлений (email, по желанию Telegram/SMS)
- Шаблоны писем с адаптивным дизайном
- Механизм отписки и аналитический дашборд
- Документацию и обучение вашей команды
Пример настройки email-уведомлений
Для отправки используем стандартный Laravel Mail с очередью. Настройка происходит через .env: MAIL_MAILER, MAIL_HOST, MAIL_PORT и т.д. Шаблоны писем — Blade с адаптивным CSS.
Закажите разработку Back in Stock — мы реализуем функционал за 1–2 дня. Свяжитесь с нами, чтобы уточнить детали и получить точную оценку.
Для дополнительной информации о механизме Back in Stock вы можете прочитать на Wikipedia.







