Заказать бота

Чат-бот для интернет-магазина ВК: автоматизация заявок и продаж под ключ

Как сделать чат-бота для интернет-магазина ВКонтакте: FAQ, квалификация лида, сбор заявки и передача менеджеру. Когда достаточно шаблона и когда нужна разработка под ключ.

Содержание статьи

Если интернет-магазин во ВКонтакте отвечает только вручную, часть заявок теряется: клиент уходит, пока ждёт ответ. Чат-бот закрывает этот разрыв: принимает первый контакт, даёт ключевую информацию и передаёт тёплый лид менеджеру.

В этой статье соберём рабочий сценарий: от «Здравствуйте, есть в наличии?» до структуры, которую можно запустить уже сегодня.

Зачем магазину бот, если есть менеджер

Менеджер нужен. Но бот снимает рутину:

  • отвечает мгновенно 24/7;
  • закрывает повторяющиеся вопросы (цена, доставка, оплата);
  • собирает заявку по форме;
  • передаёт менеджеру только готовые лиды.

Итог: меньше ручной переписки, выше конверсия в заказ.

Базовая воронка в сообщениях ВК

Минимальный сценарий для старта:

  1. Приветствие + меню.
  2. Ответы на FAQ (цена, доставка, оплата).
  3. Кнопка «Оставить заявку».
  4. Сбор 3 полей: товар, бюджет, контакт.
  5. Сообщение менеджеру и подтверждение клиенту.

Такой сценарий уже даёт рост заявок без сложных интеграций.

Архитектура проекта

vk-shop-bot/
├─ .env
├─ bot.py
└─ leads.jsonl  # временное хранилище заявок

Установка зависимостей:

pip install vkbottle python-dotenv

.env:

VK_TOKEN=vk1.a.xxxxx
MANAGER_PEER_ID=2000000123

MANAGER_PEER_ID — куда отправлять новые заявки (личка менеджера или рабочая беседа).

Шаг 1. Меню и быстрые ответы

import os
from dotenv import load_dotenv
from vkbottle import Keyboard, Text
from vkbottle.bot import Bot, Message
load_dotenv()
TOKEN = os.environ["VK_TOKEN"]
bot = Bot(token=TOKEN)
menu = (
    Keyboard()
    .add(Text("💰 Цены", payload={"cmd": "prices"}), color="primary")
    .add(Text("🚚 Доставка", payload={"cmd": "delivery"}), color="secondary")
    .row()
    .add(Text("🛒 Оставить заявку", payload={"cmd": "lead"}), color="positive")
    .get_json()
)
@bot.on.message(text=["start", "начать", "меню", "привет"])
async def start(message: Message):
    await message.answer(
        "Здравствуйте! Я помогу с заказом 👋\nВыберите раздел:",
        keyboard=menu,
    )

Шаг 2. FSM для сбора заявки

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

from vkbottle import BaseStateGroup
from vkbottle.dispatch.rules.base import StateRule
class LeadState(BaseStateGroup):
    WAIT_PRODUCT = "wait_product"
    WAIT_BUDGET = "wait_budget"
    WAIT_CONTACT = "wait_contact"

Хранилище данных на время диалога:

lead_buffer: dict[int, dict[str, str]] = {}

Старт сбора лида:

@bot.on.message(payload={"cmd": "lead"})
async def lead_start(message: Message):
    peer_id = message.peer_id
    lead_buffer[peer_id] = {}
    await bot.state_dispenser.set(peer_id, LeadState.WAIT_PRODUCT)
    await message.answer("Что хотите заказать? Напишите товар или услугу.")

Шаги формы:

@bot.on.message(StateRule(LeadState.WAIT_PRODUCT))
async def lead_product(message: Message):
    peer_id = message.peer_id
    lead_buffer.setdefault(peer_id, {})["product"] = (message.text or "").strip()
    await bot.state_dispenser.set(peer_id, LeadState.WAIT_BUDGET)
    await message.answer("Какой у вас ориентир по бюджету?")
@bot.on.message(StateRule(LeadState.WAIT_BUDGET))
async def lead_budget(message: Message):
    peer_id = message.peer_id
    lead_buffer.setdefault(peer_id, {})["budget"] = (message.text or "").strip()
    await bot.state_dispenser.set(peer_id, LeadState.WAIT_CONTACT)
    await message.answer("Оставьте контакт для связи: телефон или @username")

Шаг 3. Передача заявки менеджеру

from datetime import datetime
import json
MANAGER_PEER_ID = int(os.environ["MANAGER_PEER_ID"])
def save_lead_local(payload: dict):
    with open("leads.jsonl", "a", encoding="utf-8") as f:
        f.write(json.dumps(payload, ensure_ascii=False) + "\n")
@bot.on.message(StateRule(LeadState.WAIT_CONTACT))
async def lead_contact(message: Message):
    peer_id = message.peer_id
    user_id = message.from_id or 0
    contact = (message.text or "").strip()
    data = lead_buffer.get(peer_id, {})
    data["contact"] = contact
    data["created_at"] = datetime.now().isoformat(timespec="seconds")
    data["user_id"] = str(user_id)
    data["peer_id"] = str(peer_id)
    text_for_manager = (
        "🔥 Новая заявка из VK-бота\n"
        f"Товар/услуга: {data.get('product', '-') }\n"
        f"Бюджет: {data.get('budget', '-') }\n"
        f"Контакт: {data.get('contact', '-') }\n"
        f"User ID: {data.get('user_id', '-') }"
    )
    await bot.api.messages.send(
        peer_id=MANAGER_PEER_ID,
        random_id=0,
        message=text_for_manager,
    )
    save_lead_local(data)
    await bot.state_dispenser.delete(peer_id)
    lead_buffer.pop(peer_id, None)
    await message.answer(
        "Спасибо! ✅ Заявка отправлена менеджеру.\n"
        "Обычно отвечаем в течение 15–30 минут в рабочее время."
    )

Шаг 4. Обработка кнопок FAQ

@bot.on.message(payload={"cmd": "prices"})
async def prices(message: Message):
    await message.answer(
        "Тарифы:\n• Старт — 4 900 ₽\n• Бизнес — 12 900 ₽\n• Индивидуально — по ТЗ"
    )
@bot.on.message(payload={"cmd": "delivery"})
async def delivery(message: Message):
    await message.answer("Сроки: от 1 до 7 дней, в зависимости от сложности.")

Полный рабочий запуск

В конце файла не забудь:

if __name__ == "__main__":
    bot.run_forever()

Запуск:

python bot.py

Что обязательно улучшить на проде

  1. Хранилище заявок: вместо файла leads.jsonl использовать PostgreSQL/SQLite.
  2. Валидация контакта: проверять телефон/username по regex.
  3. Антиспам: cooldown на пользователя + ограничение частоты.
  4. Журналирование: фиксировать ошибки и шаги FSM для быстрой отладки.

Типовые ошибки

Бот не может отправить менеджеру

Проверь MANAGER_PEER_ID: это должен быть корректный peer лички или беседы. Часто ошибка в том, что ставят from_id вместо peer_id.

FSM «залипает»

Если пользователь прервал сценарий, добавь команду сброса:

@bot.on.message(text=["стоп", "отмена", "cancel"])
async def cancel(message: Message):
    await bot.state_dispenser.delete(message.peer_id)
    lead_buffer.pop(message.peer_id, None)
    await message.answer("Сценарий сброшен. Напишите «меню» для нового запроса.")

Мини-FAQ по демо

Подойдёт ли этот сценарий не только магазину?

Да. Та же схема работает для услуг: запись, консультация, бронирование, предварительный расчёт.

Почему в примере leads.jsonl, а не база данных?

Это учебный формат: проще запустить и понять логику. Для реального проекта лучше SQLite/PostgreSQL.

Что делать, если пользователь прервал диалог посередине?

Держать команду отмены (стоп/отмена) и сбрасывать состояние через state_dispenser.delete.

Можно ли добавить кнопки вместо ввода текста?

Да. Для часто повторяемых шагов (бюджет, категория товара) кнопки с payload даже удобнее и стабильнее.

Сколько стоит внедрение чат-бота для магазина ВК?

Для типового сценария можно стартовать с готового шаблона. Если нужна интеграция с CRM/складом, сложная воронка и поддержка внедрения, стоимость выше и зависит от объёма логики.

Нужен запуск быстрее: готовое решение или разработка под процесс

Если нужна кастомная логика под ваш магазин, интеграции и поддержка внедрения — оставьте заявку на разработку бота под ключ.

Если нужен быстрый старт, можно выбрать шаблон в каталоге готовых ботов.

Что читать дальше

Реклама

Комментарии

Загрузка...