Полное руководство по триггерам RetailCRM: От теории к практике

15 января 2025 г.
Команда Sideback
Гайд
13 минут чтения
Полное руководство по триггерам RetailCRM: От теории к практике

Введение: Зачем нужны триггеры в 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') — проверяет, изменилось ли поле status
  • changeSet.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 недели в зависимости от сложности

Получить коммерческое предложение

Или получите бесплатный аудит вашей CRM

Поделиться статьей:

ВКонтакте Telegram WhatsApp