Kommo + Amplitude: события воронки продаж в продуктовую аналитику

Kommo + Amplitude: события воронки продаж в продуктовую аналитику

Amplitude — платформа продуктовой аналитики, которая строит когорты, воронки и retention-анализ на основе событий. Без интеграции с Kommo данные о том, какие клиенты дошли до Won и с каким тарифом, недоступны в Amplitude. С интеграцией Won в Kommo передаёт в Amplitude событие deal_won с тарифом, источником и суммой — и продуктовая команда видит, как CRM-когорты конвертируются в продукте.

Что даёт связка Kommo + Amplitude

Без интеграции:
— Продуктовая аналитика строится только на данных из приложения — без CRM-контекста
— Нельзя сравнить retention клиентов, пришедших через enterprise-сделки vs self-serve
— Менеджер не видит в Kommo, как активен клиент в продукте после онбординга

С интеграцией:
— Won -> Amplitude: subscription_started с тарифом, суммой, источником лида
— Amplitude cohort по плану -> сравнение product engagement у Starter vs Pro vs Enterprise
— Amplitude event activation_completed -> Note в Kommo: «Клиент активировался в продукте»
— Amplitude event churned (прогноз по retention) -> задача CS-менеджеру

Что синхронизируется

Kommo -> Amplitude:
— Won -> event subscription_started с свойствами: plan, deal_amount, lead_source, deal_id
— Смена тарифа в Kommo -> event plan_upgraded или plan_downgraded
— Потеря (Lost) -> event deal_lost с причиной

Amplitude -> Kommo:
activation_completed -> Note в сделку: «Клиент активировался»
— Отсутствие активности 14 дней -> задача CSM-у на аутрич
feature_X_used -> Note с деталями (если нужен продакт-ориентированный CS)

Архитектура

Kommo Webhook: сделка перешла в Won
  ↓ Backend
  1. GET /api/v4/leads/{id} + contacts
     -> email контакта, тариф, сумма, источник
  2. Amplitude HTTP API: POST /2/httpapi
     -> event_type: 'subscription_started'
     -> user_id: email контакта
     -> event_properties: {plan, deal_amount, lead_source, kommo_deal_id}
     -> user_properties: {plan, kommo_deal_id} - обновляют профиль в Amplitude

Amplitude Webhook (через Amplitude Data Destinations):
  ↓ Backend
  1. Из payload: user_id (email), event_type, event_properties
  2. Если event_type == 'activation_completed':
     -> найти deal_id по email в Kommo
     -> POST /leads/{deal_id}/notes: «Amplitude: клиент активировался в продукте»
  3. Если нет активности 14 дней:
     -> задача CSM-у

Amplitude HTTP API: ключевые запросы

Base URL: https://api2.amplitude.com/2/httpapi (US) или https://api.eu.amplitude.com/2/httpapi (EU). Аутентификация: api_key в теле запроса (не в заголовке).

Отправить событие из Kommo:

import requests
import uuid
import time

AMPLITUDE_API_KEY = 'your_api_key'
AMPLITUDE_URL = 'https://api2.amplitude.com/2/httpapi'
# EU: AMPLITUDE_URL = 'https://api.eu.amplitude.com/2/httpapi'

def track_amplitude_event(user_id: str, event_type: str,
                           event_properties: dict,
                           user_properties: dict = None) -> None:
    event = {
        'user_id': user_id,
        'event_type': event_type,
        'time': int(time.time() * 1000),  # milliseconds
        'insert_id': str(uuid.uuid4()),   # для идемпотентности
        'event_properties': event_properties,
    }
    if user_properties:
        event['user_properties'] = user_properties

    payload = {
        'api_key': AMPLITUDE_API_KEY,
        'events': [event]
    }

    resp = requests.post(AMPLITUDE_URL, json=payload)
    resp.raise_for_status()

def on_deal_won(lead: dict, contact: dict):
    email = get_contact_email(contact)
    plan = get_custom_field(lead, PLAN_FIELD_ID)
    lead_source = get_custom_field(lead, LEAD_SOURCE_FIELD_ID)

    track_amplitude_event(
        user_id=email,
        event_type='subscription_started',
        event_properties={
            'plan': plan,
            'deal_amount': lead.get('price', 0),
            'lead_source': lead_source,
            'kommo_deal_id': lead['id'],
            'currency': 'USD'
        },
        user_properties={
            'plan': plan,
            'kommo_deal_id': lead['id'],
            'subscription_start_date': int(time.time())
        }
    )

Идентификация пользователя через Identify API:

def identify_amplitude_user(email: str, properties: dict) -> None:
    # Обновить свойства пользователя без привязки к событию
    identify_url = 'https://api2.amplitude.com/identify'
    payload = {
        'api_key': AMPLITUDE_API_KEY,
        'identification': [{
            'user_id': email,
            'user_properties': properties
        }]
    }
    resp = requests.post(identify_url, json=payload)
    resp.raise_for_status()

def on_plan_change(lead: dict, contact: dict, new_plan: str):
    email = get_contact_email(contact)
    identify_amplitude_user(email, {'plan': new_plan})
    track_amplitude_event(email, 'plan_changed', {'new_plan': new_plan})

Идемпотентность через insert_id: Amplitude игнорирует события с одинаковым insert_id для одного device_id в течение 7 дней. При повторной отправке (Kommo webhook retry) одно и то же событие не задублируется если вы сохраняете и переиспользуете insert_id для каждой конкретной операции.

Amplitude -> Kommo: обратная синхронизация

Amplitude отправляет данные наружу через Amplitude Data Destinations (раздел Data в интерфейсе): можно настроить webhook на ваш URL при срабатывании события. Также доступен Amplitude Behavioral Cohort API для получения пользователей из конкретной когорты.

Webhook из Amplitude на ваш backend:

@app.route('/webhooks/amplitude', methods=['POST'])
def amplitude_webhook():
    payload = request.json
    events = payload.get('events', [])

    for event in events:
        event_type = event.get('event_type')
        user_id = event.get('user_id')  # email
        props = event.get('event_properties', {})

        deal_id = find_kommo_deal_by_email(user_id)
        if not deal_id:
            continue

        if event_type == 'activation_completed':
            create_kommo_note(
                deal_id,
                'Amplitude: клиент активировался в продукте - все ключевые шаги выполнены'
            )
        elif event_type == 'feature_report_generated':
            report_name = props.get('report_name', '')
            create_kommo_note(
                deal_id,
                f'Amplitude: клиент создал первый отчёт ({report_name})'
            )

    return '', 200

Маппинг CRM-сегментов в Amplitude cohorts

После интеграции продуктовая команда строит cohorts в Amplitude по свойству plan:

  • Cohort «Enterprise» -> retention-анализ -> если retention ниже у Enterprise, приоритет в roadmap
  • Cohort «Starter» -> funnel «trial -> activation» -> оптимизация onboarding
  • Cohort «по lead_source» -> сравнение engagement paid vs organic vs outbound

Это недостижимо без CRM-данных в Amplitude — именно в этом ценность интеграции.

Реальный кейс

B2B SaaS (US, 60–80 новых клиентов в месяц, Kommo + Amplitude + Stripe):

  • До: продуктовая команда не знала, с какими тарифами приходят клиенты из CRM. Retention строился без сегментации по планам — roadmap принимался вслепую.
  • После: каждый Won в Kommo передаёт plan и deal_amount в Amplitude. Через 3 месяца стало видно: Pro-клиенты с deal_amount > $1000 имеют retention 85%, Starter — 52%. Roadmap пересмотрен в пользу Pro-фич.
  • Дополнительно: при активации клиента в продукте — автоматический Note в Kommo. CS-менеджер видит, когда клиент «ожил» и можно предложить upsell.

Для кого актуально

  • B2B SaaS с продуктовой аналитикой в Amplitude и воронкой продаж в Kommo
  • Продуктовая команда хочет строить retention по CRM-сегментам (тариф, размер сделки)
  • CS-команда должна видеть активность клиентов в продукте прямо в Kommo
  • 20+ новых клиентов в месяц — достаточно для значимых когорт

Часто задаваемые вопросы

Amplitude API — нужен ли специальный ключ для каждого проекта?

Да. В Amplitude каждый проект имеет свой API Key (для записи событий) и Secret Key (для Data API). API Key берётся в Settings -> Projects -> API Keys. EU-проекты используют другой endpoint: api.eu.amplitude.com.

Как Amplitude принимает исторические события из Kommo?

Для исторической загрузки (сделки Won за прошлые периоды) используйте time в событии — UNIX timestamp в миллисекундах даты Won. Amplitude принимает события с задержкой до 365 дней. Для батчевой загрузки используйте Batch Event Upload API (/batch).

Как настроить Amplitude Data Destinations для webhook?

Data -> Destinations -> Add Destination -> HTTP destination. Указать URL, выбрать events для отправки. Amplitude отправляет события в формате JSON-массива на ваш endpoint. Аутентификацию настраивается через заголовки.

Что такое insert_id и зачем он нужен?

insert_id — уникальный идентификатор события (например, UUID). Amplitude дедуплицирует события с одинаковым insert_id + device_id в течение 7 дней. Это защита от дублей при повторной отправке (Kommo webhook retry или ваш retry-механизм).

Amplitude vs Mixpanel для интеграции с Kommo?

Оба работают на HTTP API с api_key в теле запроса. Mixpanel имеет более сильный People API для управления профилями пользователей. Amplitude сильнее в retention-анализе и cohort-сравнении. Если команда уже использует один из них — интегрируйте его.

Итого

  • Amplitude HTTP API: api_key в теле, Base URL https://api2.amplitude.com/2/httpapi (EU: api.eu.amplitude.com)
  • Track event: POST с user_id = email, event_type, event_properties, insert_id для идемпотентности
  • Identify: POST https://api2.amplitude.com/identify для обновления user properties
  • Обратная синхронизация: Amplitude Data Destinations -> HTTP webhook -> Notes в Kommo
  • Типовой срок разработки — 1 неделя

Если у вас Amplitude и Kommo и вы хотите видеть retention по CRM-сегментам — опишите структуру планов и ключевые product events. Exceltic.dev настроит маппинг событий и обратную синхронизацию активации клиентов.

Ещё статьи

Все →