UTM Tracking
1. Summary
Goal: Система отслеживания маркетинговых кампаний — позволяет создавать короткие ссылки с UTM-параметрами, отслеживать переходы и конверсии, анализировать эффективность каналов привлечения.
User Value: Маркетолог получает точную аналитику по каждому источнику трафика: сколько кликов, сколько регистраций, какая конверсия. Красивые короткие ссылки (goloot.online/influencer/code) вместо длинных Telegram URL.
2. Business Logic
UTM Parameters
- Required
- Optional
Обязательные параметры:
| Параметр | Описание | Пример |
|---|---|---|
source | Источник трафика | telegram, youtube, vk |
medium | Способ размещения | cpc, social, influencer, banner |
campaign | Название кампании | winter_sale, new_users_2024 |
Ограничения: 1-20 символов (source/medium), 1-100 символов (campaign)
Опциональные параметры:
| Параметр | Описание | Пример |
|---|---|---|
term | Ключевое слово (для поиска) | rust skins |
content | Вариант объявления (A/B тест) | banner_v2 |
adType | Тип рекламы | video_horizontal, stories, banner |
influencer | Имя инфлюенсера | @blogger_name |
Ограничения: 1-50 символов
Short Link Format
Формат короткой ссылки: goloot.online/{influencer}/{code}
Внутреннее хранение: {influencer}_{code} (с underscore)
Отображение: {influencer}/{code} (со slash)
- Базовый код из первых символов параметров:
tel_vid_winter - При коллизии: добавляется счётчик
tel_vid_winter_1,tel_vid_winter_2 - При переполнении (>999): fallback на случайный 6-символьный код
Click Tracking Flow
Redirect сервис НЕ записывает клики в БД. Это "чистый редирект" для максимальной производительности. Клики подсчитываются при старте Mini App через /auth endpoint.
InviteSession (Activation Domain)
UTM и Referrals используют сервисы из домена activation:
InviteSessionService— создание и поиск сессийActivationRewardService— активация и распределение наград
Модель InviteSession:
type: InviteType— UTM или REFERRALtelegramId— ID пользователя до регистрацииmetadata: Json— UTM параметры или referralCodestate— PENDING → ACTIVATED / EXPIRED
InviteSession — это общий механизм для трекинга любых "приглашений". UTM и Referrals — два варианта использования. Подробнее см. Activation.
Conversion Tracking
Конверсия считается когда:
- Пользователь перешёл по UTM-ссылке (зафиксировано в InviteSession)
- Пользователь завершил регистрацию (onboarding completed)
- Система устанавливает
UTMTracking.converted = true
Метрики:
utm_campaigns.clicksCount— агрегированное количество кликовutm_campaigns.conversions— агрегированное количество регистрацийconversionRate = conversions / clicksCount * 100%
Promo Code Integration
UTM-кампания может быть связана с промокодом (promoCodeId). Это позволяет:
- Отслеживать активации промокода от пользователей, пришедших по UTM
- Видеть на графике аналитики две линии: общие активации и активации от UTM
- Сравнивать эффективность разных кампаний по промокоду
Метрики промокода:
totalPromoRedemptions— все активации привязанного промокодаutmPromoRedemptions— активации от пользователей с UTM-визитом за последние 7 дней- На графике: фиолетовая линия (всего) и розовая линия (от UTM)
Активация промокода атрибутируется к UTM-кампании если пользователь посетил Mini App по любой UTM-ссылке в течение 7 дней до активации. Связь устанавливается через source+medium+campaign match.
Normalization
UTM параметры автоматически нормализуются для консистентности:
| Ввод | Результат |
|---|---|
youtube, YOUTUBE, ютуб | YouTube |
tiktok, тикток | TikTok |
vk, вконтакте | VK |
shorts, reels, реели | video_vertical |
Protection
| Действие | Rate Limit | Auth | Validation |
|---|---|---|---|
| Redirect (public) | shortlinks (100/min) | none | — |
| Create campaign | critical (5/min) | admin | UTMParametersSchema |
| List campaigns | admin (10/min) | admin | UTMLinksQuerySchema |
| Toggle/Delete | critical (5/min) | admin | — |
| Analytics | analytics (30/min) | admin | AnalyticsQuerySchema |
| Tracking | tracking (60/min) | telegram | UTMTrackingSchema |
| Emergency | emergency (1/min) | — | При подозрительной активности |
Rate Limit Configs
Определены в backend/src/domains/utm/routes/utm/middleware/rate-limiting.middleware.ts:
| Config | Лимит | Назначение |
|---|---|---|
criticalRateLimitConfig | 5/min | Создание/изменение кампаний |
trackingRateLimitConfig | 60/min | Трекинг активности |
analyticsRateLimitConfig | 30/min | Аналитика |
shortlinksRateLimitConfig | 100/min | Публичные редиректы |
adminRateLimitConfig | 10/min | Админские операции |
emergencyRateLimitConfig | 1/min | Экстренная защита |
См. Security Matrix для полного обзора защит.
Edge Cases
| Ситуация | UI поведение | Код |
|---|---|---|
| ❌ Кампания не найдена | Redirect на /start (fallback) | — |
| ❌ Кампания неактивна | Redirect на /start (fallback) | — |
| ❌ Short link истёк | Redirect на /start (fallback) | — |
| ❌ Дублирующая комбинация UTM | "Кампания с такими параметрами уже существует" | DUPLICATE |
| ❌ Заблокированное значение | "Значение заблокировано" | BLOCKED_VALUE |
| ✅ Успешный редирект | 302 → Telegram | — |
3. ADR (Architectural Decisions)
ADR 1: Clean Redirect Architecture (v4.0.0)
Проблема: Запись кликов в БД при каждом redirect создаёт нагрузку и latency.
Решение: Redirect сервис только редиректит, НЕ пишет в БД. Клики подсчитываются при авторизации в Mini App.
Альтернативы (отклонены):
- Async запись в БД — усложняет архитектуру, возможна потеря данных
- Redis counter — дополнительная инфраструктура
Последствия: Простой, быстрый redirect. Клики подсчитываются точнее (только реальные открытия Mini App, не боты).
ADR 2: Агрегированные счётчики в utm_campaigns
Проблема: Подсчёт кликов через COUNT(*) в utm_tracking дорогой при большом объёме данных.
Решение: Денормализация: clicksCount и conversions хранятся в utm_campaigns и инкрементируются атомарно.
Альтернативы (отклонены):
- Материализованные представления — сложнее поддерживать
- Кэширование — inconsistency при инвалидации
Последствия: O(1) для получения статистики кампании. Trade-off: нужно инкрементировать при каждом событии.
ADR 3: Unique constraint (source, medium, campaign)
Проблема: Две кампании с одинаковыми UTM параметрами создают путаницу в аналитике.
Решение: Unique constraint на комбинацию (source, medium, campaign).
Альтернативы (отклонены):
- Разрешить дубликаты с разными ID — невозможно определить attribution
- Добавить timestamp в constraint — переусложнение
Последствия: Одна комбинация UTM = одна кампания. При необходимости новой кампании нужно изменить один из параметров.
ADR 4: Soft delete для UTM значений
Проблема: Удалённого инфлюенсера/источник можно создать заново, обойдя блокировку.
Решение: Таблица utm_deleted_values хранит заблокированные значения. При создании кампании проверяется отсутствие в этой таблице.
Последствия: Заблокированный инфлюенсер не сможет создать новую кампанию с тем же именем. Restore возможен через админку.
4. Architecture
Services Overview
Key Components
| Компонент | Путь | Описание |
|---|---|---|
| UTMService | backend/src/domains/utm/services/core/utm.service.ts | Facade, делегирует к специализированным сервисам |
| UTMCampaignService | backend/src/domains/utm/services/campaigns/utm-campaign.service.ts | CRUD кампаний, аналитика |
| UTMShortLinksService | backend/src/domains/utm/services/tracking/utm-short-links.service.ts | Управление короткими ссылками |
| UTMValidator | backend/src/domains/utm/services/utils/utm-validator.ts | Валидация параметров |
| UTMNormalizer | backend/src/domains/utm/services/utils/utm-normalizer.ts | Нормализация значений |
| UTMAnalytics | backend/src/domains/utm/services/utils/utm-analytics.ts | Расчёт трендов |
| UTMHashGenerator | backend/src/domains/utm/services/utils/utm-hash-generator.ts | Генерация уникальных shortCode |
| PromoAnalyticsService | backend/src/domains/utm/services/stats/promo-analytics.service.ts | Аналитика промокодов для UTM |
| InviteSessionService | backend/src/domains/activation/services/invite-session.service.ts | Создание UTM/Referral сессий |
| ActivationRewardService | backend/src/domains/activation/services/activation-reward.service.ts | Активация сессий и награды |
| Admin Controllers | backend/src/domains/utm/controllers/ | utm-admin-links, utm-admin-sources, utm-admin-values, utm-analytics, utm-autocomplete |
| Public Routes | backend/src/domains/utm/routes/shortlinks.routes.ts | Redirect endpoint |
| Admin Routes | backend/src/domains/utm/routes/utm/utm-admin.routes.ts | Admin API |
| Rate Limits | backend/src/domains/utm/routes/utm/middleware/rate-limiting.middleware.ts | UTM-специфичные rate limit конфиги |
5. Database Schema
Models
| Модель | Описание | Ключевые поля |
|---|---|---|
| UTMCampaign | Маркетинговая кампания | source, medium, campaign, shortCode, clicksCount, conversions, isActive |
| ShortLink | Короткая ссылка | campaignId, shortCode, destinationUrl, expiresAt |
| UTMTracking | Визит пользователя | source, medium, campaign, userId, converted, conversionDate |
| UTMDeletedValue | Заблокированные значения | field, value, deletedBy, reason |
Relationships
Indexes
| Таблица | Index | Назначение |
|---|---|---|
| UTMCampaign | (source, medium, campaign) | UNIQUE — одна кампания на комбинацию |
| UTMCampaign | shortCode | Быстрый поиск для redirect |
| UTMCampaign | isActive | Фильтрация активных |
| UTMCampaign | influencer | Поиск кампаний инфлюенсера |
| UTMCampaign | clicksCount, conversions | Сортировка по эффективности |
| ShortLink | shortCode | Быстрый redirect |
| ShortLink | expiresAt | Cron для деактивации |
| UTMTracking | source, campaign | Группировка аналитики |
| UTMTracking | userId, converted | Конверсии пользователя |
| UTMDeletedValue | (field, value) | UNIQUE — проверка при создании |
6. API Endpoints
- Public
- Admin: Links
- Admin: Analytics
- Admin: Autocomplete
- Admin: Values
| Метод | Эндпоинт | Описание | Docs |
|---|---|---|---|
| GET | /utm/:influencer/:code | Redirect на Telegram | → |
Response: 302 Redirect → t.me/goloot_bot?start={shortCode}
| Метод | Эндпоинт | Описание | Docs |
|---|---|---|---|
| GET | /admin/utm/links | Список кампаний | → |
| POST | /admin/utm/links | Создать кампанию | → |
| GET | /admin/utm/links/:id | Детали кампании | → |
| PUT | /admin/utm/links/:id | Обновить кампанию | — |
| DELETE | /admin/utm/links/:id | Удалить кампанию | → |
| PATCH | /admin/utm/links/:id/toggle | Вкл/выкл | → |
| PUT | /admin/utm/links/:id/comment | Обновить комментарий | → |
| Метод | Эндпоинт | Описание | Docs |
|---|---|---|---|
| GET | /admin/utm/stats | Сводная статистика | → |
| GET | /admin/utm/detailed-stats | Детальная аналитика (+ promo data) | → |
| GET | /admin/utm/performance-dashboard | Dashboard метрики | → |
| GET | /admin/utm/constants | UTM константы | → |
| GET | /admin/utm/export | Экспорт статистики | → |
| Метод | Эндпоинт | Описание | Docs |
|---|---|---|---|
| GET | /admin/utm/autocomplete/sources | Автодополнение источников | → |
| GET | /admin/utm/autocomplete/mediums | Автодополнение способов | → |
| GET | /admin/utm/autocomplete/campaigns | Автодополнение кампаний | — |
| GET | /admin/utm/autocomplete/ad-types | Автодополнение типов рекламы | → |
| GET | /admin/utm/influencers-autocomplete | Автодополнение инфлюенсеров | → |
7. Related
- Activation — домен InviteSession (создание и активация сессий)
- Promo Codes — промокоды атрибутируются к UTM-кампаниям
- Referrals — реферальная система (также использует activation domain)
- Glossary — термины: UTM, ShortLink, Conversion, InviteSession
- Security Matrix — защиты UTM эндпоинтов
UTM и Referrals используют общие компоненты из activation домена:
InviteSessionService— создание и поиск сессийActivationRewardService— активация и наградыInviteSessionмодель — общая модель в Prisma schema