# 📊 Unleash AB Testing → Google Analytics - Подробная документация
## 🎯 Общая схема работы
```
1. Пользователь заходит в воронку
↓
2. UnleashProvider инициализируется (layout.tsx)
↓
3. FunnelUnleashWrapper собирает все флаги из воронки
↓
4. Unleash SDK загружает варианты флагов
↓
5. useUnleash подписывается на события "impression"
↓
6. При активации флага → отправка в Google Analytics
```
---
## 1️⃣ В какой момент отправляется событие
### Цепочка инициализации:
#### Шаг 1: Загрузка воронки
```tsx
// src/app/[funnelId]/layout.tsx
{/* ← Инициализируется один раз */}
{children}
```
#### Шаг 2: Сбор флагов из воронки
```tsx
// src/components/funnel/FunnelUnleashWrapper.tsx
export function FunnelUnleashWrapper({ funnel }) {
// Сканирует все экраны и собирает уникальные флаги
const allFlags = useMemo(() => {
const flags = new Set();
funnel.screens.forEach((screen) => {
// Из вариантов экранов
screen.variants?.forEach(variant => {
variant.conditions.forEach(condition => {
if (condition.conditionType === "unleash") {
flags.add(condition.unleashFlag);
}
});
});
// Из правил навигации
screen.navigation?.rules?.forEach(rule => {
rule.conditions.forEach(condition => {
if (condition.conditionType === "unleash") {
flags.add(condition.unleashFlag);
}
});
});
});
return Array.from(flags);
}, [funnel.screens]);
// Получаем варианты для ВСЕХ флагов сразу
const flagVariants = allFlags.map(flag => {
const variant = useVariant(flag);
return { flag, variant: variant?.name };
});
}
```
#### Шаг 3: Подписка на события
```tsx
// src/lib/funnel/unleash/useUnleash.ts
useEffect(() => {
const handleImpression = (impressionEvent) => {
if (impressionEvent.enabled) {
// ✅ ОТПРАВКА В GA
window.gtag("event", "experiment_impression", {
app_name: "witlab-funnel",
feature: impressionEvent.featureName,
treatment: impressionEvent.variant,
});
}
};
unleashClient.on("impression", handleImpression);
return () => {
unleashClient.off("impression", handleImpression);
};
}, [unleashClient]);
```
### ⏰ Timing событий:
| Момент | Действие | Когда отправляется в GA |
|--------|----------|-------------------------|
| **T+0ms** | Пользователь открывает воронку | - |
| **T+100ms** | UnleashProvider подключается к Unleash | - |
| **T+300ms** | Unleash возвращает варианты флагов | ✅ **Здесь!** |
| **T+300ms** | Unleash SDK эмитит событие "impression" | ✅ **И здесь!** |
| **T+301ms** | useUnleash ловит событие → window.gtag() | ✅ **События отправлены** |
| **T+500ms** | Воронка рендерится с правильными вариантами | - |
### 🔄 Повторная отправка:
**НЕТ повторных отправок** для одного флага в рамках сессии:
- Unleash SDK внутри помнит какие impression уже отправлены
- События эмитятся только **один раз** при первой активации флага
- При переходе между экранами события **НЕ отправляются повторно**
---
## 2️⃣ Какие данные отправляются
### Формат события в Google Analytics:
```javascript
window.gtag("event", "experiment_impression", {
app_name: "witlab-funnel", // Идентификатор приложения
feature: "trial-button-test", // Название флага из Unleash
treatment: "v1" // Вариант который получил пользователь
});
```
### Детали полей:
| Поле | Тип | Значение | Описание |
|------|-----|----------|----------|
| **event** | string | `"experiment_impression"` | Стандартное название для AB тестов в GA |
| **app_name** | string | `"witlab-funnel"` | Фиксированное имя приложения |
| **feature** | string | `impressionEvent.featureName` | Название флага из Unleash |
| **treatment** | string | `impressionEvent.variant` | Вариант: "v0", "v1", "v2", "disabled" и т.д. |
### Пример реальных данных:
```javascript
// AB тест кнопки оплаты
{
event: "experiment_impression",
app_name: "witlab-funnel",
feature: "trial-payment-button",
treatment: "v1"
}
// AB тест навигации
{
event: "experiment_impression",
app_name: "witlab-funnel",
feature: "onboarding-flow-test",
treatment: "short"
}
// Несколько флагов → несколько событий
{
event: "experiment_impression",
app_name: "witlab-funnel",
feature: "special-offer-test",
treatment: "v2"
}
```
### 📊 Как увидеть в Google Analytics:
1. **Realtime → Events**
- Событие: `experiment_impression`
- Параметры: `app_name`, `feature`, `treatment`
2. **Reports → Engagement → Events**
- Найти `experiment_impression`
- Посмотреть breakdown по `feature`
- Посмотреть distribution по `treatment`
3. **Создать кастомный отчет:**
```
Dimensions:
- Event name (experiment_impression)
- Event parameter: feature
- Event parameter: treatment
Metrics:
- Event count
- Users
```
---
## 3️⃣ Совпадает ли логика с aura-webapp
### ✅ Сходства (95% идентичны):
#### 1. Точно такой же механизм отправки:
```typescript
// ✅ WITLAB-FUNNEL
unleashClient.on("impression", (impressionEvent) => {
window.gtag("event", "experiment_impression", {
app_name: "witlab-funnel",
feature: impressionEvent.featureName,
treatment: impressionEvent.variant,
});
});
// ✅ AURA-WEBAPP
unleashClient.on("impression", (impressionEvent: any) => {
window.gtag?.("event", "experiment_impression", {
app_name: impressionEvent.context.appName,
feature: impressionEvent.featureName,
treatment: impressionEvent.variant,
});
});
```
#### 2. Одинаковый формат события:
- Название: `"experiment_impression"`
- Параметры: `app_name`, `feature`, `treatment`
- Условие: только если `impressionEvent.enabled === true`
#### 3. Подписка в useEffect:
- В обоих случаях подписка через `unleashClient.on("impression")`
- В обоих случаях cleanup через `unleashClient.off("impression")`
### ⚠️ Различия (минимальные):
| Аспект | witlab-funnel | aura-webapp | Критично? |
|--------|---------------|-------------|-----------|
| **app_name** | Хардкод `"witlab-funnel"` | Из `context.appName` | ⚠️ Да* |
| **window.gtag** | `window.gtag` | `window.gtag?.` | ✅ Нет |
| **Debug логи** | ✅ Есть в dev | ❌ Нет | ✅ Нет |
| **Типизация** | Явная типизация | `any` | ✅ Нет |
**\* Рекомендация:** Можно улучшить чтобы брать из context:
```typescript
// Улучшенная версия (опционально)
window.gtag("event", "experiment_impression", {
app_name: impressionEvent.context?.appName || "witlab-funnel",
feature: impressionEvent.featureName,
treatment: impressionEvent.variant,
});
```
### 📋 Вывод по совместимости:
✅ **Логика полностью совместима**
- События будут выглядеть одинаково в GA
- Можно создать единые отчеты для обоих приложений
- Единственная разница - в `app_name` (можно использовать для фильтрации)
---
## 4️⃣ Что если Google Analytics не установлена
### Сценарий: GA не настроена
```tsx
// В воронке:
{
"meta": {
"googleAnalyticsId": undefined // ← Не указан
}
}
```
### ✅ Защита от ошибок:
```typescript
// src/lib/funnel/unleash/useUnleash.ts
if (typeof window !== "undefined" && window.gtag) {
// ^^^^^^^^^^^^
// Проверка что gtag существует
window.gtag("event", "experiment_impression", {...});
}
```
### Что произойдет:
1. ✅ **Unleash продолжит работать нормально**
- Флаги загружаются
- Варианты применяются
- AB тесты работают
2. ✅ **Событие "impression" будет эмититься**
- `unleashClient.on("impression")` сработает
- `handleImpression()` будет вызван
3. ⚠️ **Отправка в GA будет пропущена**
- Проверка `window.gtag` вернет `false`
- Блок с `window.gtag()` НЕ выполнится
- **Никакой ошибки не будет**
4. 🐛 **Debug логи все равно работают**
```javascript
// В консоли браузера (в dev):
[Unleash Analytics] {
feature: "trial-button-test",
variant: "v1"
}
```
### Поведение в разных средах:
| Среда | GA установлена? | window.gtag? | Что происходит |
|-------|----------------|--------------|----------------|
| **Production с GA** | ✅ Да | ✅ Да | ✅ События отправляются |
| **Production без GA** | ❌ Нет | ❌ Нет | ✅ AB тесты работают, GA молчит |
| **Development с GA** | ✅ Да | ✅ Да | ✅ События + debug логи |
| **Development без GA** | ❌ Нет | ❌ Нет | ✅ AB тесты + debug логи |
| **Preview/Staging** | Зависит | Зависит | Зависит от настройки |
### Рекомендации:
#### ✅ Текущая реализация безопасна:
```typescript
// Нет ошибок если GA отсутствует
if (typeof window !== "undefined" && window.gtag) {
window.gtag(...); // Выполнится только если GA загружен
}
```
#### ⚠️ Можно добавить предупреждение (опционально):
```typescript
if (process.env.NODE_ENV === "development") {
if (typeof window !== "undefined" && !window.gtag) {
console.warn("[Unleash Analytics] Google Analytics not loaded");
}
}
```
---
## 🔍 Debug и мониторинг
### В development режиме:
```javascript
// Консоль браузера автоматически показывает:
[Unleash Analytics] { feature: "trial-test", variant: "v1" }
[Unleash Analytics] { feature: "button-test", variant: "v2" }
```
### Проверка отправки в GA:
#### 1. Через Network tab:
```
1. Откройте DevTools → Network
2. Фильтр: "collect" или "analytics"
3. Ищите POST запросы к:
- https://www.google-analytics.com/g/collect
- https://www.google-analytics.com/j/collect
4. В payload должны быть:
- en=experiment_impression
- ep.feature=trial-test
- ep.treatment=v1
```
#### 2. Через Google Analytics DebugView:
```bash
# 1. Включите debug mode
localStorage.setItem('ga_debug', '1')
# 2. Перезагрузите страницу
# 3. Откройте GA → Admin → DebugView
# 4. Увидите события в реальном времени
```
#### 3. Через расширение Google Analytics Debugger:
```
1. Установите Chrome extension "Google Analytics Debugger"
2. Включите его
3. В консоли увидите все GA события с деталями
```
---
## 📊 Пример полного flow
### Сценарий: Воронка с 2 AB тестами
```json
{
"meta": {
"googleAnalyticsId": "G-XXXXXXXXXX"
},
"screens": [
{
"id": "payment",
"variants": [
{
"conditions": [
{
"conditionType": "unleash",
"unleashFlag": "trial-button-test",
"unleashVariants": ["v1"]
}
]
}
]
},
{
"id": "gender",
"navigation": {
"rules": [
{
"conditions": [
{
"conditionType": "unleash",
"unleashFlag": "onboarding-flow",
"unleashVariants": ["short"]
}
]
}
]
}
}
]
}
```
### Timeline событий:
```
T+0ms: Пользователь открывает /soulmate/payment
T+50ms: UnleashProvider инициализируется
T+100ms: FunnelUnleashWrapper собирает флаги:
["trial-button-test", "onboarding-flow"]
T+300ms: Unleash возвращает варианты:
trial-button-test → v1
onboarding-flow → short
T+300ms: Unleash эмитит 2 impression события
T+301ms: useUnleash ловит события
T+301ms: ✅ Отправка в GA #1:
{
event: "experiment_impression",
app_name: "witlab-funnel",
feature: "trial-button-test",
treatment: "v1"
}
T+302ms: ✅ Отправка в GA #2:
{
event: "experiment_impression",
app_name: "witlab-funnel",
feature: "onboarding-flow",
treatment: "short"
}
T+500ms: FunnelLoadingScreen исчезает
T+501ms: Экран рендерится с правильными вариантами
```
### В консоли разработчика:
```
[Unleash Analytics] { feature: "trial-button-test", variant: "v1" }
[Unleash Analytics] { feature: "onboarding-flow", variant: "short" }
```
---
## 🎯 Итоговые выводы
### 1. Момент отправки:
✅ **При первой активации флага** (~300ms после загрузки воронки)
✅ **Только один раз** за сессию для каждого флага
✅ **Автоматически** без необходимости явного вызова
### 2. Данные:
✅ Событие: `"experiment_impression"`
✅ Параметры: `app_name`, `feature`, `treatment`
✅ Формат совместим с Google Analytics 4
### 3. Совместимость с aura-webapp:
✅ **95% идентично**
✅ Можно использовать единые GA отчеты
⚠️ Единственная разница: `app_name` (легко фильтровать)
### 4. Без Google Analytics:
✅ **AB тесты работают нормально**
✅ **Никаких ошибок**
✅ Debug логи в dev режиме
⚠️ События просто не отправляются (graceful degradation)
---
## 📚 См. также
- `AB_TESTING_GUIDE.md` - Общее руководство по AB тестам
- `AB_TESTING_UPDATES.md` - Технические детали и оптимизации
- `UNLEASH_SETUP.md` - Настройка Unleash