Введение: Зачем нужны триггеры в e-commerce?
Триггерные сценарии (triggers) — это автоматизированные бизнес-процессы, которые срабатывают при определенных событиях в системе. В RetailCRM триггеры работают на языке PipeLang — специальном DSL (Domain Specific Language) для описания бизнес-логики.
Реальные результаты наших клиентов:
- 🎯 Конверсия брошенных корзин выросла с 8% до 23% (+187%)
- 📈 Средний чек увеличился на 32% благодаря upsell-триггерам
- 🔄 Повторные продажи выросли на 47% через реактивацию
- ⏱️ Экономия 4 часов работы менеджера в день на рутине
Архитектура триггерной системы RetailCRM
RetailCRM использует event-driven архитектуру для обработки триггеров:
### 1. События (Events)
Система отслеживает изменения и генерирует события:
order.create— создан новый заказorder.update— изменение заказаcustomer.update— изменение данных клиентаpayment.create— создание платежаshipment.create— создание отгрузки
2. Условия (Conditions)
Триггер проверяет условия на языке PipeLang перед выполнением действий. Синтаксис основан на Symfony Expression Language с расширениями.
### 3. Действия (Actions)
При срабатывании условий выполняются действия:
- Отправка email/SMS
- Создание задачи менеджеру
- Изменение статуса заказа
- HTTP-запрос к внешнему API
- Выполнение webhook
Практические примеры с кодом
### Пример 1: Отслеживание изменения статуса заказа
Задача: Отправить уведомление клиенту при изменении статуса заказа на "Отправлен"
Условие на PipeLang:
changeSet.hasChangedField('status')
and changeSet.getOldValue('status') != null
and changeSet.getNewValue('status').code == 'send-to-delivery'
Разбор кода:
changeSet.hasChangedField('status')— проверяет, изменилось ли поле statuschangeSet.getOldValue('status') != null— исключает создание нового заказа (там old = null)changeSet.getNewValue('status').code == 'send-to-delivery'— новый статус = "Отправлен"
Пример 2: Проверка полной оплаты заказа
Задача: Автоматически перевести заказ в обработку при полной оплате
Условие:
changeSet.hasChangedField("full_paid_at")
and changeSet.getNewValue("full_paid_at") != null
Действие через HTTP API:
{
"type": "http_request",
"method": "POST",
"url": "{{ apiUrl }}/orders/{{ order.id }}/edit",
"headers": {
"X-API-KEY": "{{ apiKey }}"
},
"body": {
"order": {
"status": "assembling"
}
}
}
### Пример 3: Работа с товарами в заказе
Задача: Проверить, что все товары в заказе доступны на складе
Условие с фильтром every:
changeSet.hasChangedField("status")
and changeSet.newValue("status").code == "complete"
and order.availableOrderProducts | every(item => item.status.code == "saled")
Альтернатива с фильтром some:
// Проверить, есть ли хотя бы один товар со скидкой > 30%
order.items | some(item =>
(item.initialPrice - item.purchasePrice) / item.initialPrice > 0.3
)
## Кейс №1: Цепочка триггеров для брошенных корзин
Это самый высокодоходный триггер в e-commerce. Рассмотрим полную реализацию с кодом.
### Шаг 1: Отслеживание брошенной корзины
Условие срабатывания:
// Проверяем, что заказ создан, но не оплачен более 2 часов
changeSet.hasChangedField('created_at')
and order.status.code == 'new'
and order.summ > 0
and now() - order.created_at > duration('2 hours')
Email-шаблон с переменными:
{{ customer.first_name }}, вы забыли завершить заказ!
В вашей корзине {{ order.items | length }} товаров на сумму {{ order.total_summ }} ₽
{% for item in order.items %}
{{ item.offer.name }}
{{ item.quantity }} шт × {{ item.initial_price }} ₽
{% endfor %}
Оформить заказ
### Шаг 2: Эскалация со скидкой (через 24 часа)
Генерация промокода через API:
{
"type": "http_request",
"method": "POST",
"url": "{{ apiUrl }}/store/coupon/create",
"body": {
"code": "CART{{ order.id }}",
"type": "fixed",
"value": 500,
"min_order_sum": {{ order.total_summ }},
"expire_date": "{{ now() + duration('7 days') | date('Y-m-d') }}",
"customer_ids": [{{ customer.id }}]
}
}
Сохранение промокода в кастомное поле:
// В действии "Изменить заказ"
{
"custom_fields": {
"promo_code": "CART{{ order.id }}"
}
}
## Кейс №2: Webhook интеграция с внешними сервисами
Триггеры могут отправлять данные в любую внешнюю систему через webhook.
### Пример: Отправка данных в Telegram при новом заказе
Условие:
changeSet.hasChangedField('status')
and changeSet.getOldValue('status') == null
and order.status.code == 'new'
and order.total_summ > 10000
HTTP-запрос к Telegram Bot API:
{
"type": "http_request",
"method": "POST",
"url": "https://api.telegram.org/bot{{ telegram_token }}/sendMessage",
"headers": {
"Content-Type": "application/json"
},
"body": {
"chat_id": "{{ admin_chat_id }}",
"text": "🎉 Новый крупный заказ!\n\nНомер: #{{ order.number }}\nСумма: {{ order.total_summ }}₽\nКлиент: {{ customer.first_name }} {{ customer.last_name }}\nТелефон: {{ customer.phones[0] }}\n\n{{ site_url }}/orders/{{ order.id }}",
"parse_mode": "HTML"
}
}
### Пример: Интеграция с Google Sheets для аналитики
Отправка данных о продаже в Google Sheets через webhook:
{
"type": "webhook",
"url": "https://script.google.com/macros/s/YOUR_SCRIPT_ID/exec",
"method": "POST",
"body": {
"order_id": "{{ order.id }}",
"order_number": "{{ order.number }}",
"date": "{{ order.created_at | date('Y-m-d H:i:s') }}",
"customer": "{{ customer.first_name }} {{ customer.last_name }}",
"total": {{ order.total_summ }},
"items_count": {{ order.items | length }},
"delivery_type": "{{ order.delivery.code }}",
"payment_type": "{{ order.payment_type }}",
"manager": "{{ order.manager_comment }}"
}
}
Google Apps Script для приема данных:
function doPost(e) {
const data = JSON.parse(e.postData.contents);
const sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow([
data.order_id,
data.order_number,
data.date,
data.customer,
data.total,
data.items_count,
data.delivery_type,
data.payment_type
]);
return ContentService.createTextOutput(JSON.stringify({
'result': 'success'
})).setMimeType(ContentService.MimeType.JSON);
}
## Кейс №3: RFM-сегментация с помощью триггеров
Автоматическая сегментация клиентов по Recency, Frequency, Monetary для персонализированных предложений.
### Расчет RFM-сегментов в триггере
Условие для VIP-клиентов:
// R - последняя покупка менее 30 дней назад
// F - более 10 покупок
// M - средний чек > 5000₽
now() - customer.lastOrderDate 10
and (customer.totalSumm / customer.ordersCount) > 5000
Автоматическое присвоение тега:
{
"type": "customer_tag_add",
"tags": ["VIP", "RFM_111"]
}
### Триггер для реактивации "спящих" клиентов
Условие:
// Клиент не покупал 90+ дней, но раньше был активным
now() - customer.lastOrderDate > duration('90 days')
and customer.ordersCount >= 3
and not customer.tags | contains('reactivation_sent')
Персонализированное предложение:
// Email с персональными товарами на основе истории покупок
{% set favorite_category = customer.favoriteCategory %}
{% set products = getRecommendations(customer.id, favorite_category, 5) %}
{{ customer.first_name }}, мы скучали по вам!
Специально для вас подобрали новинки в категории "{{ favorite_category }}"
{% for product in products %}
{{ product.name }}
{{ product.price }} ₽
{% endfor %}
Промокод COMEBACK20 для скидки 20%
## Продвинутые техники
### 1. Условные ветвления (IF-ELSE)
PipeLang поддерживает сложную логику с множественными условиями:
// Разная логика для разных сегментов
{% if customer.totalSumm > 100000 %}
{% set discount = 20 %}
{% set segment = "VIP" %}
{% elseif customer.totalSumm > 50000 %}
{% set discount = 15 %}
{% set segment = "Premium" %}
{% elseif customer.ordersCount > 5 %}
{% set discount = 10 %}
{% set segment = "Regular" %}
{% else %}
{% set discount = 5 %}
{% set segment = "New" %}
{% endif %}
Для вас скидка {{ discount }}% как для клиента сегмента "{{ segment }}"
### 2. Работа с массивами и фильтрация
Фильтр map - преобразование массива:
// Получить список артикулов всех товаров в заказе
{% set skus = order.items | map(item => item.offer.xmlId) %}
// Отправить в внешнюю систему
{{ skus | join(',') }}
Фильтр filter - фильтрация элементов:
// Товары дороже 1000₽
{% set expensive_items = order.items | filter(item => item.initialPrice > 1000) %}
// Количество дорогих товаров
У вас в заказе {{ expensive_items | length }} премиальных товаров
Фильтр reduce - агрегация:
// Общий вес заказа
{% set total_weight = order.items | reduce(
(sum, item) => sum + (item.quantity * item.offer.weight),
0
) %}
Общий вес вашего заказа: {{ total_weight / 1000 }} кг
### 3. Работа с датами и временем
// Проверка рабочего времени
{% set current_hour = now() | date('H') %}
{% if current_hour >= 9 and current_hour {
const signature = req.headers['x-retailcrm-signature'];
if (!verifyWebhook(req.body, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Обработка webhook
processOrder(req.body.order);
res.json({ success: true });
});
### 2. Обработка ошибок
Используйте try-catch для HTTP-запросов:
{
"type": "http_request",
"url": "{{ external_api }}/process",
"method": "POST",
"retry": {
"max_attempts": 3,
"delay": "5s",
"on_error": "continue"
},
"fallback": {
"type": "task_create",
"task": {
"text": "Ошибка отправки в внешнюю систему для заказа #{{ order.number }}",
"manager_id": "{{ admin_manager_id }}"
}
}
}
### 3. Оптимизация производительности
- Избегайте сложных вычислений в условиях - выносите в кастомные поля
- Кешируйте результаты - используйте переменные для повторяющихся выражений
- Батчинг запросов - группируйте несколько действий в один HTTP-запрос
- Дебаунсинг - избегайте срабатывания триггера при каждом мелком изменении
Типичные ошибки и их решения
### Ошибка 1: Триггер срабатывает многократно
Проблема: При изменении заказа триггер вызывается несколько раз
Решение: Добавить проверку на кастомное поле-флаг:
changeSet.hasChangedField('status')
and order.status.code == 'complete'
and not order.customFields.email_sent
В действиях установить флаг:
{
"type": "order_edit",
"order": {
"custom_fields": {
"email_sent": true
}
}
}
### Ошибка 2: Null pointer exception
Проблема: Обращение к несуществующему полю
Решение: Проверка на существование:
// Неправильно
customer.customFields.birthday
// Правильно
customer.customFields and customer.customFields.birthday
### Ошибка 3: Некорректная работа с timezone
Решение: Явно указывайте timezone:
{% set moscow_time = now() | date('Y-m-d H:i:s', 'Europe/Moscow') %}
{% set utc_time = now() | date('Y-m-d H:i:s', 'UTC') %}
## Инструменты для тестирования триггеров
### 1. Режим отладки в RetailCRM
Включите режим отладки для просмотра логов выполнения:
- Откройте триггер в редакторе
- Нажмите "Тестировать"
- Выберите тестовый заказ/клиента
- Просмотрите лог выполнения с переменными
2. Postman для webhook
Создайте коллекцию запросов для тестирования webhook:
POST https://your-domain.com/webhook/test
Content-Type: application/json
X-RetailCRM-Signature: {{signature}}
{
"event": "order.update",
"order": {
"id": 12345,
"number": "TEST-001",
"status": {
"code": "new"
},
"customer": {
"id": 678,
"email": "test@example.com"
}
}
}
## Метрики эффективности триггеров
### Ключевые показатели для отслеживания:
- Trigger Conversion Rate: % получателей, совершивших целевое действие
- Open Rate: % открытых писем (норма 20-35% для триггерных)
- Click Rate: % кликов по ссылкам (норма 5-15%)
- Revenue Per Trigger: средняя выручка с одного срабатывания
- Time To Action: среднее время до совершения целевого действия
Дашборд в Google Data Studio
Создайте автоматический дашборд для мониторинга триггеров через Google Sheets интеграцию (см. Кейс №2 выше).
## Заключение
Триггеры в RetailCRM — это мощнейший инструмент автоматизации, который при правильной настройке способен:
- 💰 Увеличить выручку на 35-50% без роста рекламного бюджета
- ⏱️ Сэкономить 20-30 часов работы менеджеров в неделю
- 🎯 Повысить конверсию на всех этапах воронки в 2-3 раза
- 🔄 Автоматизировать до 80% рутинных операций
Начните с малого
Неделя 1: Настройте 3 базовых триггера (подтверждение заказа, изменение статуса, брошенные корзины)
Неделя 2: Добавьте персонализацию (день рождения, годовщина)
Неделя 3: Внедрите сегментацию и RFM
Неделя 4: Настройте webhook интеграции с внешними системами
## Нужна профессиональная помощь?
Команда Sideback специализируется на сложных интеграциях и автоматизации RetailCRM:
- 📋 Разработка технического задания на триггеры
- 💻 Программирование сложных сценариев на PipeLang
- 🔗 Интеграция с внешними API (Telegram, Google Sheets, CRM, ERP)
- ✉️ Дизайн и верстка email-шаблонов
- 📊 Настройка аналитики и дашбордов
- 🧪 A/B-тестирование и оптимизация триггеров
- 📚 Обучение команды работе с триггерами
- 🔧 Техническая поддержка 24/7
Стоимость услуг:
- Базовый пакет (10 триггеров): от 30 000₽
- Расширенный пакет (30+ триггеров + интеграции): от 80 000₽
- Enterprise (полная автоматизация + кастомные разработки): от 150 000₽
Срок реализации: 1-3 недели в зависимости от сложности