16 KiB
📊 Unleash AB Testing → Google Analytics - Подробная документация
🎯 Общая схема работы
1. Пользователь заходит в воронку
↓
2. UnleashProvider инициализируется (layout.tsx)
↓
3. FunnelUnleashWrapper собирает все флаги из воронки
↓
4. Unleash SDK загружает варианты флагов
↓
5. useUnleash подписывается на события "impression"
↓
6. При активации флага → отправка в Google Analytics
1️⃣ В какой момент отправляется событие
Цепочка инициализации:
Шаг 1: Загрузка воронки
// src/app/[funnelId]/layout.tsx
<UnleashProvider> {/* ← Инициализируется один раз */}
<PixelsProvider googleAnalyticsId={funnel.meta.googleAnalyticsId}>
{children}
</PixelsProvider>
</UnleashProvider>
Шаг 2: Сбор флагов из воронки
// src/components/funnel/FunnelUnleashWrapper.tsx
export function FunnelUnleashWrapper({ funnel }) {
// Сканирует все экраны и собирает уникальные флаги
const allFlags = useMemo(() => {
const flags = new Set<string>();
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: Подписка на события
// 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:
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" и т.д. |
Пример реальных данных:
// 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:
-
Realtime → Events
- Событие:
experiment_impression - Параметры:
app_name,feature,treatment
- Событие:
-
Reports → Engagement → Events
- Найти
experiment_impression - Посмотреть breakdown по
feature - Посмотреть distribution по
treatment
- Найти
-
Создать кастомный отчет:
Dimensions: - Event name (experiment_impression) - Event parameter: feature - Event parameter: treatment Metrics: - Event count - Users
3️⃣ Совпадает ли логика с aura-webapp
✅ Сходства (95% идентичны):
1. Точно такой же механизм отправки:
// ✅ 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:
// Улучшенная версия (опционально)
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 не настроена
// В воронке:
{
"meta": {
"googleAnalyticsId": undefined // ← Не указан
}
}
✅ Защита от ошибок:
// src/lib/funnel/unleash/useUnleash.ts
if (typeof window !== "undefined" && window.gtag) {
// ^^^^^^^^^^^^
// Проверка что gtag существует
window.gtag("event", "experiment_impression", {...});
}
Что произойдет:
-
✅ Unleash продолжит работать нормально
- Флаги загружаются
- Варианты применяются
- AB тесты работают
-
✅ Событие "impression" будет эмититься
unleashClient.on("impression")сработаетhandleImpression()будет вызван
-
⚠️ Отправка в GA будет пропущена
- Проверка
window.gtagвернетfalse - Блок с
window.gtag()НЕ выполнится - Никакой ошибки не будет
- Проверка
-
🐛 Debug логи все равно работают
// В консоли браузера (в 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 | Зависит | Зависит | Зависит от настройки |
Рекомендации:
✅ Текущая реализация безопасна:
// Нет ошибок если GA отсутствует
if (typeof window !== "undefined" && window.gtag) {
window.gtag(...); // Выполнится только если GA загружен
}
⚠️ Можно добавить предупреждение (опционально):
if (process.env.NODE_ENV === "development") {
if (typeof window !== "undefined" && !window.gtag) {
console.warn("[Unleash Analytics] Google Analytics not loaded");
}
}
🔍 Debug и мониторинг
В development режиме:
// Консоль браузера автоматически показывает:
[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:
# 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 тестами
{
"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