# Tracking plan — <продукт>

> Владелец: <кто>. Этот файл — источник истины для инструментирования.
> Версионируйте вместе с кодом; ломающие правки — через changelog, а не тихой правкой.
>
> Шаблон Goodlabs — https://goodlabs.kz · dilshat@goodlabs.kz
> Копируйте и адаптируйте свободно. Атрибуция приятна, но не обязательна.

Заполните это **до** того, как кто-то откроет контейнер GTM. Большинство
сломанных аналитик — не проблема тегирования, а проблема несогласованности:
три человека отправили каждый то событие, которое имел в виду.

---

## Конвенции именования

- **События:** `snake_case`, `объект_действие` — `payment_completed`, а не
  `completedPayment` или `Payment Success`
- **Свойства:** `snake_case`
- **Значения:** lowercase, нормализованные. Одно каноническое имя на канал:
  выберите `google` или `google_ads`, но не оба, иначе квартал уйдёт на
  разбор `google,google` в отчёте по каналам
- **Запрещено:** PII в event properties, сырые URL как значения, свободный ввод пользователя

Запишите конвенцию здесь один раз. Конвенция, на которую нельзя показать
пальцем, — это предпочтение, а предпочтения дрейфуют.

---

## Модель идентичности

Самое дорогое, что придётся переделывать задним числом. Решите сейчас.

| | Определение |
|---|---|
| **Anonymous id** | напр. GA4 `client_id` / Amplitude `device_id`, first-party cookie, TTL 400 дней |
| **User id** | напр. внутренний `user_id`, хешированный. **Присваивается:** при логине, регистрации или первом идентифицированном действии — укажите, при каком |
| **Сшивка device → phone → user** | Какой ключ соединяет, где выполняется джойн (клиент, сервер, DWH), что происходит с событиями до логина |
| **Группы (аккаунт / компания)** | Только B2B: id аккаунта и агрегируются ли метрики до него |

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

---

## События

Одна строка — одно событие. Если строку нельзя заполнить, событие не готово
к разработке.

| Событие | Триггер | Ключевые свойства | Назначения | Дедуп-ключ | Владелец |
|---|---|---|---|---|---|
| `sign_up` | Регистрация подтверждена на сервере (не по сабмиту формы) | `method`, `plan` | GA4, Amplitude | `event_id` | |
| `checkout_started` | Отрисован экран оформления, корзина непустая | `value`, `currency`, `items[]` | GA4, Meta CAPI | `event_id` | |
| `payment_completed` | Вебхук платёжного провайдера вернул успех | `value`, `currency`, `payment_method`, `order_id` | GA4, Meta CAPI, TikTok, Amplitude | `order_id` | |
| `refund_issued` | Возврат проведён в реестре | `value`, `currency`, `order_id`, `reason` | GA4, DWH | `refund_id` | |
| | | | | | |

**Триггер** — то, что команды пропускают, и именно он решает, правдива ли
цифра. «На странице спасибо» и «когда вебхук подтвердил оплату» дают разную
выручку, и переживёт возврат только один из них.

---

## Словарь свойств

| Свойство | Тип | Пример | Событие(я) | Заметка |
|---|---|---|---|---|
| `value` | number | `24990` | `checkout_started`, `payment_completed` | Копейки или рубли — выберите одно и укажите здесь |
| `currency` | string | `KZT` | любое денежное событие | ISO 4217, uppercase |
| `order_id` | string | `ord_10482` | `payment_completed`, `refund_issued` | Он же дедуп-ключ |
| `payment_method` | string | `card`, `apple_pay`, `installment` | `payment_completed` | Закрытый список — перечислите его здесь |
| `method` | string | `email`, `phone`, `apple` | `sign_up` | Закрытый список |
| | | | | |

Перечисляйте закрытые списки прямо в этом файле. Открытое строковое свойство
за два квартала превращается в 40 написаний одного и того же значения.

---

## Назначения (destinations)

| Назначение | Что заполнить |
|---|---|
| **GA4** | Measurement ID, web или server-side контейнер, какие события помечены как key events |
| **Meta CAPI** | Dataset ID, какие EMQ-поля отправляете (email, телефон, `fbp`, `fbc`, IP, UA), `event_id` для дедупа browser↔server |
| **Google Ads** | Enhanced conversions: какой идентификатор, где хешируется |
| **TikTok Events API** | Pixel code, дедуп по `event_id` |
| **Amplitude / product analytics** | Проект, `insert_id` для дедупа, события идут с клиента или из DWH |
| **DWH** | Таблица, частота загрузки, является ли источником истины по выручке |

Отмечайте для каждого события, кто авторитетен — браузер или сервер. Когда
срабатывают оба, дедуп-ключ — единственное, что отделяет вас от задвоенной
выручки.

---

## QA-чеклист

Прогоняйте перед релизом, на staging, с реальным назначением в debug-режиме.

- [ ] Событие срабатывает ровно один раз — нет дублей при `router.replace()`, ре-рендере, навигации назад
- [ ] Свойства заполнены: нет `undefined`, нет строк `null`, нет PII
- [ ] Дедуп работает: browser- и server-события с одинаковым `event_id` / `insert_id` схлопываются в одно
- [ ] Match quality (EMQ) проверено в интерфейсе самого назначения, а не «на глаз»
- [ ] Consent Mode / gating учтён — события подавляются при отказе, состояние consent доходит до серверного контейнера
- [ ] Валюта и value сверены с реальным заказом в реестре, а не с тестовым
- [ ] Возвраты и отмены проходят по пайплайну — план, который знает только happy path, завышает выручку
- [ ] Проверено на staging, не на проде

---

## Changelog

| Дата | Изменение | Ломающее? | Кто |
|---|---|---|---|
| | | | |

---

## Когда это перестаёт быть проблемой документации

Tracking plan лечит несогласованность. Он не лечит webview, который теряет
сессию, CAPI-фид с match quality 3/10 и офлайн-выручку, которая не
возвращается из CRM.

Разборы этих случаев: https://goodlabs.kz/ru/wiki
Двухнедельный аудит с фиксированным скоупом: https://goodlabs.kz/ru/#contact
