Kommo + Amplitude: Sales Pipeline Events to Product Analytics

Amplitude is a product analytics platform that builds cohorts, funnels, and retention analysis based on events. Without integration with Kommo, data about which clients reached Won and on which plan is unavailable in Amplitude. With the integration, Won in Kommo sends a deal_won event to Amplitude with the plan, source, and amount — and the product team can see how CRM cohorts convert within the product.

What the Kommo + Amplitude connection provides

Without integration:
— Product analytics is built only on in-app data — without CRM context
— It’s impossible to compare retention of clients from enterprise deals vs self-serve
— Managers don’t see in Kommo how active a client is in the product after onboarding

With integration:
— Won -> Amplitude: subscription_started with plan, amount, and lead source
— Amplitude cohort by plan -> compare product engagement across Starter vs Pro vs Enterprise
— Amplitude event activation_completed -> Note in Kommo: “Client activated in the product”
— Amplitude event churned (retention forecast) -> task for the CS manager

What gets synced

Kommo -> Amplitude:
— Won -> event subscription_started with properties: plan, deal_amount, lead_source, deal_id
— Plan change in Kommo -> event plan_upgraded or plan_downgraded
— Lost -> event deal_lost with reason

Amplitude -> Kommo:
activation_completed -> Note on the deal: “Client activated”
— No activity for 14 days -> task for CSM to do outreach
feature_X_used -> Note with details (if product-led CS is needed)

Architecture

Kommo Webhook: deal moved to Won
  ↓ Backend
  1. GET /api/v4/leads/{id} + contacts
     -> contact email, plan, amount, source
  2. Amplitude HTTP API: POST /2/httpapi
     -> event_type: 'subscription_started'
     -> user_id: contact email
     -> event_properties: {plan, deal_amount, lead_source, kommo_deal_id}
     -> user_properties: {plan, kommo_deal_id} - update user profile in Amplitude

Amplitude Webhook (via Amplitude Data Destinations):
  ↓ Backend
  1. From payload: user_id (email), event_type, event_properties
  2. If event_type == 'activation_completed':
     -> find deal_id by email in Kommo
     -> POST /leads/{deal_id}/notes: "Amplitude: client activated in the product"
  3. If no activity for 14 days:
     -> task for CSM

Amplitude HTTP API: key requests

Base URL: https://api2.amplitude.com/2/httpapi (US) or https://api.eu.amplitude.com/2/httpapi (EU). Authentication: api_key in the request body (not in the header).

Sending an event from 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()),   # for idempotency
        '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())
        }
    )

User identification via Identify API:

def identify_amplitude_user(email: str, properties: dict) -> None:
    # Update user properties without tying them to an event
    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})

Idempotency via insert_id: Amplitude ignores events with the same insert_id for the same device_id within 7 days. On retry (Kommo webhook retry), the same event won’t be duplicated if you save and reuse the insert_id for each specific operation.

Amplitude -> Kommo: reverse sync

Amplitude sends data outward via Amplitude Data Destinations (Data section in the UI): you can configure a webhook to your URL when an event fires. The Amplitude Behavioral Cohort API is also available for retrieving users from a specific cohort.

Webhook from Amplitude to your 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: client activated in the product - all key steps completed'
            )
        elif event_type == 'feature_report_generated':
            report_name = props.get('report_name', '')
            create_kommo_note(
                deal_id,
                f'Amplitude: client generated their first report ({report_name})'
            )

    return '', 200

Mapping CRM segments to Amplitude cohorts

After integration, the product team builds cohorts in Amplitude using the plan property:

  • Cohort “Enterprise” -> retention analysis -> if Enterprise retention is lower, it becomes a roadmap priority
  • Cohort “Starter” -> funnel “trial -> activation” -> onboarding optimization
  • Cohort “by lead_source” -> compare engagement of paid vs organic vs outbound

This is not achievable without CRM data in Amplitude — that’s exactly the value of the integration.

Real-world case study

B2B SaaS (US, 60–80 new clients per month, Kommo + Amplitude + Stripe):

  • Before: the product team had no visibility into which plans clients were coming in on from the CRM. Retention was built without plan-based segmentation — roadmap decisions were made blind.
  • After: every Won in Kommo passes plan and deal_amount to Amplitude. After 3 months, a clear pattern emerged: Pro clients with deal_amount > $1,000 had 85% retention, Starter clients — 52%. The roadmap was reprioritized toward Pro features.
  • Additionally: when a client activates in the product — automatic Note in Kommo. The CS manager sees when a client “comes alive” and can propose an upsell.

Who benefits from this integration

  • B2B SaaS with product analytics in Amplitude and a sales pipeline in Kommo
  • Product team wants to build retention analysis by CRM segments (plan, deal size)
  • CS team needs visibility into client product activity directly in Kommo
  • 20+ new clients per month — enough for statistically meaningful cohorts

Frequently asked questions

Does Amplitude API require a separate key for each project?

Yes. In Amplitude, each project has its own API Key (for writing events) and Secret Key (for Data API). The API Key is found in Settings -> Projects -> API Keys. EU projects use a different endpoint: api.eu.amplitude.com.

How does Amplitude accept historical events from Kommo?

For historical loading (Won deals from past periods), use the time field in the event — UNIX timestamp in milliseconds of the Won date. Amplitude accepts events up to 365 days in the past. For batch uploads, use the Batch Event Upload API (/batch).

How to configure Amplitude Data Destinations for a webhook?

Data -> Destinations -> Add Destination -> HTTP destination. Specify the URL and select the events to send. Amplitude sends events as a JSON array to your endpoint. Authentication is configured via request headers.

What is insert_id and why is it needed?

insert_id is a unique event identifier (e.g., a UUID). Amplitude deduplicates events with the same insert_id + device_id within 7 days. This protects against duplicates on retry (Kommo webhook retry or your own retry mechanism).

Amplitude vs Mixpanel for Kommo integration?

Both work via HTTP API with api_key in the request body. Mixpanel has a stronger People API for user profile management. Amplitude is stronger for retention analysis and cohort comparison. If the team already uses one of them — integrate with that one.

Summary

  • Amplitude HTTP API: api_key in body, Base URL https://api2.amplitude.com/2/httpapi (EU: api.eu.amplitude.com)
  • Track event: POST with user_id = email, event_type, event_properties, insert_id for idempotency
  • Identify: POST https://api2.amplitude.com/identify to update user properties
  • Reverse sync: Amplitude Data Destinations -> HTTP webhook -> Notes in Kommo
  • Typical development timeline — 1 week

If you have Amplitude and Kommo and want to see retention by CRM segments — describe your plan structure and key product events. Exceltic.dev will set up the event mapping and client activation reverse sync.

More articles

All →