Analytics API — Аналитика и отчёты

Справочник API аналитики: дашборд, временные ряды, топ событий, выручка, кампании, рост клиентов. ClickHouse + PostgreSQL.

Обзор модуля аналитики

Модуль аналитики Trigly предоставляет сводные данные по всем аспектам маркетинга: события, выручка, кампании, рост клиентской базы. Данные агрегируются из двух источников:

  • ClickHouse — события (events), метрики доставки (delivery_events), ежедневные агрегаты (events_daily_mv, delivery_stats_daily)
  • PostgreSQL — метаданные кампаний, контактов, сегментов

API prefix: /api/v1/analytics

6 эндпоинтов для ключевых аналитических запросов.

ClickHouse-таблицы

events

Основная таблица событий (создаётся модулем CDP):

CREATE TABLE events (
    organization_id UUID,
    customer_id UUID,
    event_type String,
    event_name String,
    properties String,      -- JSON
    page_url String,
    referrer String,
    session_id String,
    revenue Float64,
    created_at DateTime
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(created_at)
ORDER BY (organization_id, created_at, event_type)
TTL created_at + INTERVAL 365 DAY

events_daily_mv

Материализованное представление для быстрых ежедневных агрегатов:

CREATE MATERIALIZED VIEW events_daily_mv
ENGINE = SummingMergeTree()
ORDER BY (organization_id, event_date, event_type)
AS SELECT
    organization_id,
    toDate(created_at) AS event_date,
    event_type,
    count() AS event_count,
    uniqExact(customer_id) AS unique_customers,
    sum(revenue) AS total_revenue
FROM events
GROUP BY organization_id, event_date, event_type

delivery_events

Таблица событий доставки (создаётся модулем Channels):

CREATE TABLE delivery_events (
    organization_id UUID,
    channel String,
    event_type String,       -- sent, delivered, opened, clicked, bounced, failed
    campaign_id UUID,
    customer_id UUID,
    message_id UUID,
    cost Float64,
    error String,
    created_at DateTime
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(created_at)
ORDER BY (organization_id, created_at, channel)
TTL created_at + INTERVAL 365 DAY

delivery_stats_daily

Материализованное представление для ежедневной статистики доставки:

CREATE MATERIALIZED VIEW delivery_stats_daily
ENGINE = SummingMergeTree()
ORDER BY (organization_id, event_date, channel, event_type)
AS SELECT
    organization_id,
    toDate(created_at) AS event_date,
    channel,
    event_type,
    count() AS event_count,
    sum(cost) AS total_cost
FROM delivery_events
GROUP BY organization_id, event_date, channel, event_type

Эндпоинты

Дашборд

GET /api/v1/analytics/dashboard?period=30d

Сводная статистика по организации за период.

Параметры:

  • period — период: 7d, 30d, 90d, 365d (по умолчанию 30d)

Ответ:

{
  "total_customers": 15000,
  "new_customers_period": 1200,
  "total_events": 450000,
  "total_revenue": 2500000.0,
  "active_campaigns": 5,
  "total_sent": 85000,
  "delivery_rate": 96.5,
  "open_rate": 24.3,
  "click_rate": 3.8,
  "unsubscribe_rate": 0.2,
  "channels": {
    "email": {"sent": 50000, "delivered": 48500, "opened": 12000},
    "sms": {"sent": 10000, "delivered": 9800},
    "telegram": {"sent": 15000, "delivered": 14900, "opened": 11000},
    "push": {"sent": 10000, "delivered": 9500, "opened": 4500}
  }
}

Источники данных:

  • total_customers, new_customers_period — PostgreSQL (таблица customers)
  • total_events, total_revenue — ClickHouse (events_daily_mv)
  • active_campaigns — PostgreSQL (таблица campaigns, status = running)
  • total_sent, delivery_rate, open_rate — ClickHouse (delivery_stats_daily)

Временные ряды

GET /api/v1/analytics/time-series?period=30d&event_type=purchase&granularity=day

Временной ряд событий с заполнением пропущенных дней нулями.

Параметры:

  • period — период: 7d, 30d, 90d
  • event_type — тип события (опционально, по умолчанию — все типы)
  • granularity — гранулярность: hour, day, week (по умолчанию day)

Ответ:

{
  "data": [
    {"date": "2026-03-01", "event_count": 1500, "unique_customers": 800, "revenue": 125000.0},
    {"date": "2026-03-02", "event_count": 1650, "unique_customers": 850, "revenue": 140000.0},
    {"date": "2026-03-03", "event_count": 0, "unique_customers": 0, "revenue": 0.0}
  ],
  "period": "30d",
  "event_type": "purchase",
  "granularity": "day"
}

Важно: пропущенные дни автоматически заполняются нулями. Это обеспечивает корректное отображение графиков без разрывов.

Источник: ClickHouse (events_daily_mv).

Топ событий

GET /api/v1/analytics/top-events?period=30d&limit=10

Самые частые типы событий за период.

Параметры:

  • period — период
  • limit — количество (по умолчанию 10)

Ответ:

{
  "events": [
    {"event_type": "page_view", "count": 250000, "unique_customers": 12000},
    {"event_type": "purchase", "count": 5000, "unique_customers": 3200},
    {"event_type": "add_to_cart", "count": 15000, "unique_customers": 8000},
    {"event_type": "search", "count": 12000, "unique_customers": 5500},
    {"event_type": "product_view", "count": 80000, "unique_customers": 10000}
  ]
}

Источник: ClickHouse (events).

Выручка по дням

GET /api/v1/analytics/revenue?period=30d

Ежедневная выручка с разбивкой по дням.

Ответ:

{
  "data": [
    {"date": "2026-03-01", "revenue": 125000.0, "orders": 150},
    {"date": "2026-03-02", "revenue": 140000.0, "orders": 165}
  ],
  "total_revenue": 2500000.0,
  "total_orders": 4500,
  "avg_order_value": 555.56,
  "period": "30d"
}

Источник: ClickHouse (events_daily_mv, фильтр по event_type содержащим revenue > 0).

Аналитика кампаний

GET /api/v1/analytics/campaigns?period=30d

Сводка по кампаниям: сколько запущено, завершено, открытия, клики.

Ответ:

{
  "total_campaigns": 25,
  "active": 5,
  "completed": 18,
  "draft": 2,
  "total_sent": 85000,
  "total_delivered": 82000,
  "total_opened": 20000,
  "total_clicked": 3200,
  "avg_open_rate": 24.4,
  "avg_click_rate": 3.9,
  "top_campaigns": [
    {
      "id": "uuid",
      "name": "Весенняя распродажа",
      "channel": "email",
      "sent": 15000,
      "open_rate": 32.5,
      "click_rate": 5.2
    }
  ]
}

Источник: PostgreSQL (таблица campaigns с агрегированными полями).

Рост клиентской базы

GET /api/v1/analytics/customer-growth?period=90d&granularity=week

Кумулятивный рост клиентской базы.

Параметры:

  • period — период: 30d, 90d, 365d
  • granularityday, week, month (по умолчанию day)

Ответ:

{
  "data": [
    {"date": "2026-01-01", "new_customers": 150, "cumulative_total": 10150},
    {"date": "2026-01-08", "new_customers": 180, "cumulative_total": 10330},
    {"date": "2026-01-15", "new_customers": 200, "cumulative_total": 10530}
  ],
  "total_growth": 1200,
  "growth_rate": 8.5,
  "period": "90d"
}

growth_rate — процент роста за период: (new_customers / total_at_start) * 100.

Источник: PostgreSQL (таблица customers, GROUP BY created_at с кумулятивной суммой).

Расширенная аналитика (модуль Campaigns)

Помимо базовой аналитики, модуль кампаний предоставляет дополнительные аналитические эндпоинты:

Live Stats

GET /api/v1/campaigns/{campaign_id}/analytics/live

Статистика кампании в реальном времени: sent, delivered, opened, clicked, bounced, failed — с обновлением каждые 10 секунд.

Сравнение кампаний

GET /api/v1/campaigns/analytics/compare?campaign_ids=uuid1,uuid2,uuid3

Попарное сравнение метрик нескольких кампаний.

Revenue Attribution

GET /api/v1/campaigns/{campaign_id}/analytics/revenue

Атрибуция выручки к конкретной кампании: сколько дохода принесла кампания.

Heatmap

GET /api/v1/campaigns/analytics/heatmap?period=30d

Тепловая карта активности аудитории: в какие дни недели и часы наибольший engagement.

Deliverability

GET /api/v1/campaigns/analytics/deliverability?period=30d

Метрики доставляемости: delivery rate, bounce rate, spam complaint rate по дням.

Когортный анализ

GET /api/v1/campaigns/analytics/cohort?period=90d&granularity=month

Retention-таблица по когортам (месяц первой покупки): какой процент клиентов остаётся активным в каждый последующий месяц.

Календарь кампаний

GET /api/v1/campaigns/analytics/calendar?month=2026-03

Календарное представление запланированных и завершённых кампаний.

Расширенная аналитика (модуль Channels)

Модуль каналов предоставляет 7 аналитических эндпоинтов (см. Channels API Reference):

  • Dashboard — сводка по каналам
  • Compare — сравнение каналов
  • Timeline — временной ряд по каналам
  • Funnel — воронка доставки
  • Costs — отчёт по расходам
  • Errors — анализ ошибок
  • Health Timeline — история uptime

Расширенная аналитика (модуль CDP)

Модуль CDP предоставляет специализированные аналитические эндпоинты:

Heatmap активности

GET /api/v1/cdp/analytics/heatmap?period=30d

Тепловая карта активности клиентов по часам и дням недели (ClickHouse).

Data Quality

GET /api/v1/cdp/analytics/data-quality

Оценка качества данных: процент заполненности полей, data_quality_score по базе.

Sources

GET /api/v1/cdp/analytics/sources?period=30d

Распределение источников привлечения клиентов: organic, paid, referral, social, utm-разбивка.

Производительность запросов

ClickHouse-оптимизации

Все аналитические запросы к ClickHouse оптимизированы:

  1. Партиционирование по месяцам — запросы за 30 дней читают только 1-2 партиции
  2. Материализованные представления — events_daily_mv и delivery_stats_daily предагрегируют данные
  3. ORDER BY ключи — запросы фильтруют по organization_id (первый ключ сортировки)
  4. TTL 365 дней — старые данные удаляются автоматически
  5. run_in_executor — ClickHouse-запросы выполняются в thread pool, не блокируют event loop

Типичное время ответа

Запрос Объём данных Время ответа
Dashboard (30d) 100K событий < 200 мс
Time Series (30d, day) 100K событий < 100 мс
Top Events (30d) 1M событий < 300 мс
Revenue (90d) 500K событий < 150 мс
Campaign Analytics 50 кампаний < 100 мс
Customer Growth (365d) 50K контактов < 200 мс

Кэширование

В текущей версии аналитические запросы не кэшируются на уровне API. Рекомендации:

  • Фронтенд кэширует через React Query (staleTime: 60 секунд)
  • Для тяжёлых отчётов (когорты, heatmap) — staleTime: 300 секунд
  • ClickHouse сам кэширует результаты повторных запросов

Безопасность

Все аналитические эндпоинты:

  • Требуют JWT-аутентификации
  • Фильтруют данные по organization_id из токена
  • Не допускают cross-tenant доступ к данным

Известные ограничения

  1. ClickHouse SQL: запросы формируются через f-string (не параметризованы). В production рекомендуется перейти на параметризованные запросы для защиты от SQL injection.
  2. TTL 365 дней: исторические данные старше 1 года удаляются автоматически. Для длительного хранения настройте экспорт в S3/MinIO.
  3. Реальное время: данные в материализованных представлениях могут отставать на 1-2 секунды от основных таблиц (eventual consistency ClickHouse MergeTree).

Не нашли ответ?

Swagger UI с интерактивной документацией и поддержка в Telegram.