w-funnel/docs/UNLEASH_ANALYTICS_FLOW.md
2025-10-22 22:42:01 +02:00

16 KiB
Raw Permalink Blame History

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

  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. Точно такой же механизм отправки:

// ✅ 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", {...});
}

Что произойдет:

  1. Unleash продолжит работать нормально

    • Флаги загружаются
    • Варианты применяются
    • AB тесты работают
  2. Событие "impression" будет эмититься

    • unleashClient.on("impression") сработает
    • handleImpression() будет вызван
  3. ⚠️ Отправка в GA будет пропущена

    • Проверка window.gtag вернет false
    • Блок с window.gtag() НЕ выполнится
    • Никакой ошибки не будет
  4. 🐛 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