# 📊 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