Kommo + Looker Studio: дашборд продаж без ручного экспорта данных из CRM

Kommo + Looker Studio: дашборд продаж без ручного экспорта данных из CRM

Looker Studio (бывший Google Data Studio) - бесплатный инструмент визуализации данных от Google. Подключить данные Kommo к Looker Studio напрямую нельзя: нативного коннектора нет. Правильная архитектура - через промежуточную базу данных: Kommo API -> ETL-скрипт -> PostgreSQL -> Looker Studio connector. Результат: живые дашборды по воронке, конверсии и KPI команды, обновляющиеся каждый час без ручного экспорта.

Это актуальная задача для кастомных аналитических интеграций Kommo: встроенная аналитика Kommo ограничена, Looker Studio - мощный и бесплатный инструмент, который уже знают маркетологи и CMO.

Почему нельзя подключить Kommo к Looker Studio напрямую

Looker Studio поддерживает подключение через «Community Connectors» - сторонние плагины. В галерее коннекторов нет официального коннектора Kommo. Неофициальные коннекторы, которые иногда появляются в галерее, используют устаревший API или работают нестабильно.

Почему CSV-экспорт не решает задачу. Некоторые команды экспортируют сделки из Kommo в CSV и загружают в Google Sheets, откуда Looker Studio читает данные. Это работает, но:

  • Данные актуальны только на момент экспорта (ручного или по расписанию)
  • Нельзя автоматически загружать исторические данные за разные периоды
  • CSV не содержит всех полей (например, историю смен этапов)
  • При изменении структуры экспорта формула в Google Sheets ломается

Правильный подход - ETL-пайплайн: Kommo API забирает данные раз в час, сохраняет в PostgreSQL (или BigQuery), Looker Studio читает через стандартный SQL-коннектор.

Архитектура интеграции

Компоненты:

  • Python ETL-скрипт (запускается по cron каждый час)
  • Kommo REST API v4: /api/v4/leads, /api/v4/contacts, /api/v4/pipelines
  • PostgreSQL (или BigQuery) как хранилище
  • Looker Studio с подключением к PostgreSQL через Community Connector или напрямую через BigQuery

Схема базы данных (основные таблицы):

CREATE TABLE kommo_leads (
    id BIGINT PRIMARY KEY,
    name TEXT,
    status_id INT,
    pipeline_id INT,
    price NUMERIC(12,2),
    responsible_user_id INT,
    created_at TIMESTAMPTZ,
    updated_at TIMESTAMPTZ,
    closed_at TIMESTAMPTZ,
    loss_reason_id INT,
    -- кастомные поля (пример)
    custom_source TEXT,
    custom_country TEXT,
    synced_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE kommo_lead_status_history (
    id BIGSERIAL PRIMARY KEY,
    lead_id BIGINT REFERENCES kommo_leads(id),
    from_status_id INT,
    to_status_id INT,
    changed_at TIMESTAMPTZ,
    responsible_user_id INT
);

CREATE TABLE kommo_pipelines (
    id INT PRIMARY KEY,
    name TEXT
);

CREATE TABLE kommo_statuses (
    id INT PRIMARY KEY,
    pipeline_id INT,
    name TEXT,
    sort INT,
    is_won BOOLEAN,
    is_lost BOOLEAN
);

Python ETL-скрипт:

import requests
import psycopg2
from datetime import datetime, timezone
import time

KOMMO_BASE = "https://YOUR_ACCOUNT.kommo.com"

def fetch_leads_page(token: str, page: int, updated_since: int = None) -> list:
    headers = {"Authorization": f"Bearer {token}"}
    params = {"page": page, "limit": 250, "with": "contacts,loss_reason"}
    if updated_since:
        params["filter[updated_at][from]"] = updated_since
    
    resp = requests.get(
        f"{KOMMO_BASE}/api/v4/leads",
        headers=headers,
        params=params
    )
    if resp.status_code == 204:
        return []  # Нет данных
    resp.raise_for_status()
    return resp.json().get("_embedded", {}).get("leads", [])

def upsert_lead(conn, lead: dict):
    custom_fields = {cf["field_id"]: cf.get("values", [{}])[0].get("value") 
                     for cf in lead.get("custom_fields_values") or []}
    
    with conn.cursor() as cur:
        cur.execute("""
            INSERT INTO kommo_leads (
                id, name, status_id, pipeline_id, price, 
                responsible_user_id, created_at, updated_at, closed_at,
                loss_reason_id, custom_source, custom_country, synced_at
            ) VALUES (%s,%s,%s,%s,%s,%s,
                to_timestamp(%s), to_timestamp(%s), to_timestamp(%s),
                %s,%s,%s, NOW())
            ON CONFLICT (id) DO UPDATE SET
                name=EXCLUDED.name, status_id=EXCLUDED.status_id,
                pipeline_id=EXCLUDED.pipeline_id, price=EXCLUDED.price,
                updated_at=EXCLUDED.updated_at, closed_at=EXCLUDED.closed_at,
                loss_reason_id=EXCLUDED.loss_reason_id,
                custom_source=EXCLUDED.custom_source,
                custom_country=EXCLUDED.custom_country,
                synced_at=EXCLUDED.synced_at
        """, (
            lead["id"], lead["name"], lead["status_id"], lead["pipeline_id"],
            lead["price"], lead["responsible_user_id"],
            lead["created_at"], lead["updated_at"],
            lead.get("closed_at"), lead.get("loss_reason_id"),
            custom_fields.get(SOURCE_FIELD_ID),
            custom_fields.get(COUNTRY_FIELD_ID),
        ))
    conn.commit()

def run_etl(token: str, db_url: str, updated_since: int = None):
    conn = psycopg2.connect(db_url)
    page = 1
    total = 0
    while True:
        leads = fetch_leads_page(token, page, updated_since)
        if not leads:
            break
        for lead in leads:
            upsert_lead(conn, lead)
        total += len(leads)
        page += 1
        time.sleep(0.1)  # Rate limiting
    conn.close()
    print(f"ETL complete: {total} leads synced")

Подключение PostgreSQL к Looker Studio

Looker Studio не имеет встроенного PostgreSQL-коннектора, но есть несколько вариантов:

Вариант A - Google BigQuery (рекомендуемый). Вместо PostgreSQL используйте BigQuery как хранилище. Looker Studio имеет нативный бесплатный коннектор к BigQuery. ETL-скрипт пишет в BigQuery через google-cloud-bigquery клиент.

Вариант B - Community Connector для PostgreSQL. В галерее Looker Studio есть сторонние коннекторы (например, Supermetrics PostgreSQL Connector). Они платные (~$50/мес), но работают стабильно.

Вариант C - Google Sheets как промежуточный слой. ETL-скрипт экспортирует агрегированные данные в Google Sheets через Sheets API. Looker Studio читает из Sheets. Работает, но ограничен 10 миллионами ячеек.

Примеры дашбордов в Looker Studio

Дашборд «Воронка по этапам»: количество сделок на каждом этапе, средний чек, время в этапе. SQL:

SELECT s.name AS stage, COUNT(l.id) AS deals,
       AVG(l.price) AS avg_deal_value
FROM kommo_leads l
JOIN kommo_statuses s ON l.status_id = s.id
WHERE l.pipeline_id = 1 AND NOT s.is_lost
GROUP BY s.name, s.sort ORDER BY s.sort;

Дашборд «KPI менеджеров»: количество закрытых сделок, сумма, конверсия - в разбивке по менеджерам за выбранный период.

Дашборд «Конверсия по источнику»: откуда приходят лиды (поле custom_source) и какой процент переходит в Won.

Реальный кейс: IT-консалтинг, 18 человек

Компания ИТ-консалтинга, продажи в EU и US. CMO хотел видеть еженедельный отчёт по воронке в Looker Studio - чтобы шарить с борд-членами без доступа к Kommo.

До интеграции: CFO каждую пятницу вручную выгружал CSV из Kommo, загружал в Google Sheets, обновлял формулы. 2-3 часа работы, данные всегда немного устаревшие.

После интеграции: ETL-пайплайн забирает данные из Kommo в BigQuery каждые 2 часа. Looker Studio дашборд всегда актуален. Борд-члены смотрят его по ссылке без доступа в Kommo. Фильтр по периоду, по менеджеру, по источнику - всё в один клик.

Результат: 2-3 часа/нед -> 0 ручной работы. Дашборд шарится по ссылке, обновляется автоматически.

Для кого подходит

Интеграция Kommo с Looker Studio актуальна для:

  • Компаний, где CMO или финансовый директор хотят видеть данные продаж без доступа в CRM
  • Команд, которые уже используют Google Workspace и BigQuery
  • Организаций с требованием регулярной отчётности для борда или инвесторов
  • Тех, кто хочет совместить данные Kommo с рекламной аналитикой в одном дашборде

Для более продвинутой аналитики продаж рекомендуем также посмотреть на Prooflytics - платформу, которая объединяет данные CRM и рекламных кабинетов без необходимости строить ETL вручную.

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

Насколько часто обновляются данные в дашборде?

Частота обновления зависит от настройки ETL-крона. Обычно запускают раз в час. Для отчётов реального времени (например, для колл-центра) можно настроить каждые 5 минут, но нужно следить за rate limits Kommo API (60 запросов/минуту). Looker Studio кеширует данные 12 часов по умолчанию - это значение можно уменьшить в настройках источника данных.

Нужен ли выделенный сервер для ETL?

Нет. ETL-скрипт можно запустить как Google Cloud Function по расписанию (Cloud Scheduler). Стоимость - несколько долларов в месяц при ежечасном запуске. Альтернативно - простой VPS или даже локальная машина с cron. BigQuery хранилище бесплатно до 10 ГБ.

Как подключить данные из нескольких воронок Kommo?

Kommo API возвращает pipeline_id с каждой сделкой. В PostgreSQL таблица kommo_pipelines хранит название каждой воронки. В Looker Studio создаёте фильтр по pipeline - и можно переключаться между воронками в одном дашборде или создавать отдельные страницы.

Можно ли добавить данные из других источников в тот же дашборд?

Да. BigQuery позволяет объединять данные из разных источников через JOIN. Если у вас есть данные из Google Ads, Meta Ads или других источников - их можно загрузить в тот же BigQuery и строить объединённые дашборды: «стоимость лида из каждого канала с конверсией в CRM».

Looker Studio vs Metabase: что выбрать?

Looker Studio бесплатен и хорошо интегрируется с Google-экосистемой. Metabase лучше для команд, которым нужно сложное SQL и self-hosted развёртывание. Для шаринга дашбордов с внешними стейкхолдерами (борд, инвесторы) Looker Studio удобнее - ссылка работает без авторизации. Разбор кастомной интеграции Kommo + Metabase есть на Exceltic.dev.

Следующий шаг

Если вам нужен дашборд Kommo в Looker Studio - опишите задачу команде Exceltic.dev. Разберём нужные метрики, структуру данных и выберем подходящий тип хранилища (BigQuery vs PostgreSQL). Стандартный проект - 2-3 недели включая настройку дашбордов.

Ещё статьи

Все →