diff --git a/docs/ENHANCED_LOGGING_GUIDE.md b/docs/ENHANCED_LOGGING_GUIDE.md
new file mode 100644
index 0000000..8f777cd
--- /dev/null
+++ b/docs/ENHANCED_LOGGING_GUIDE.md
@@ -0,0 +1,362 @@
+# 📊 Улучшенное логирование Google Analytics событий
+
+## ✨ Что изменилось
+
+Все события Google Analytics теперь логируются с **детальной информацией** в консоли браузера:
+
+### 1. **Page View события** (просмотры страниц)
+### 2. **AB Test Impression события** (показы AB-тестов)
+
+Все логи используют **console.group** для структурированного отображения и поддерживают цветное форматирование.
+
+---
+
+## 📊 Page View события
+
+### ✅ Успешная отправка
+
+```
+▼ [GA] 📊 Page View Event Sent
+ 🕐 Timestamp: 2025-10-23T19:15:42.123Z
+ 📍 URL: /soulmate/partner-age
+ 🌐 Full Location: http://localhost:3000/soulmate/partner-age
+ 📄 Page Title: Soulmate Portrait - Partner Age
+ 📦 Payload: {
+ page_path: "/soulmate/partner-age",
+ page_location: "http://localhost:3000/soulmate/partner-age",
+ page_title: "Soulmate Portrait - Partner Age"
+ }
+ ✅ Status: Successfully sent to Google Analytics
+```
+
+### ⚠️ Google Analytics не доступен
+
+```
+⚠️ [GA] ⚠️ Page View NOT Sent
+ Reason: Google Analytics not available (window.gtag is undefined)
+```
+
+---
+
+## 🧪 AB Test Impression события
+
+### ✅ Успешная отправка (первый раз)
+
+```
+▼ [GA] 🧪 AB Test Impression Event Sent
+ 🕐 Timestamp: 2025-10-23T19:15:42.456Z
+ 🏷️ Flag: soulmate-onboarding-image
+ 🎯 Variant: v1
+ 📦 Event Name: experiment_impression
+ 📦 Payload: {
+ app_name: "witlab-funnel",
+ feature: "soulmate-onboarding-image",
+ treatment: "v1"
+ }
+ 💾 Storage Key: unleash_impression_soulmate-onboarding-image_v1
+ ✅ Status: Successfully sent to Google Analytics
+ 🔍 Verify in Network tab: Look for /g/collect requests
+```
+
+### ⚠️ Пропущено (уже отправлялось)
+
+```
+▼ [GA] 🧪 AB Test Impression SKIPPED (Already Sent)
+ 🕐 Timestamp: 2025-10-23T19:16:10.789Z
+ 🏷️ Flag: soulmate-onboarding-image
+ 🎯 Variant: v1
+ 💾 Storage Key: unleash_impression_soulmate-onboarding-image_v1
+ ⚠️ Reason: Already sent in this session
+ 📊 Check sessionStorage to verify
+```
+
+### ⚠️ Пропущено (невалидный вариант)
+
+```
+▼ [GA] 🧪 AB Test Impression SKIPPED
+ 🕐 Timestamp: 2025-10-23T19:15:40.123Z
+ 🏷️ Flag: some-test-flag
+ 🎯 Variant: disabled
+ ⚠️ Reason: Invalid variant (disabled or undefined)
+```
+
+### ❌ Ошибка (GA не загружен)
+
+```
+▼ [GA] 🧪 AB Test Impression NOT Sent
+ 🕐 Timestamp: 2025-10-23T19:15:42.456Z
+ 🏷️ Flag: soulmate-trial-grid
+ 🎯 Variant: grid
+ ❌ Error: Google Analytics not available (window.gtag is undefined)
+ 💡 Solution: Check that GoogleAnalytics component is loaded with measurementId
+```
+
+---
+
+## 🧹 Очистка истории AB-тестов
+
+```
+▼ [GA] 🧪 AB Test Impressions Cleared
+ 🕐 Timestamp: 2025-10-23T19:20:15.234Z
+ 🧹 Keys Removed: 2
+ 📋 Removed Keys: [
+ "unleash_impression_soulmate-onboarding-image_v1",
+ "unleash_impression_soulmate-trial-grid_grid"
+ ]
+ ✅ Status: All AB test impression history cleared
+ 💡 New impressions will be sent on next screen view
+```
+
+---
+
+## 📋 Yandex Metrika события
+
+### ✅ Успешная отправка
+
+```
+▼ [YM] 📊 Page View Event Sent
+ 🕐 Timestamp: 2025-10-23T19:15:42.123Z
+ 📍 URL: /soulmate/partner-age
+ 🔢 Counter ID: 104471567
+ ✅ Status: Successfully sent to Yandex Metrika
+```
+
+### ⚠️ Counter ID не найден
+
+```
+⚠️ [YM] ⚠️ Page View NOT Sent
+ Reason: Counter ID not found
+```
+
+---
+
+## 🎨 Цветовая схема
+
+Логи используют цветовое кодирование для быстрой идентификации:
+
+| Тип события | Цвет | Значок |
+|-------------|------|--------|
+| **GA Page View** | 🔵 Синий (`#4285F4`) | 📊 |
+| **YM Page View** | 🔴 Красный (`#FF0000`) | 📊 |
+| **AB Test Sent** | 🔵 Синий (`#4285F4`) | 🧪 |
+| **AB Test Skipped** | ⚪ Серый (`#9E9E9E`) | 🧪 |
+| **AB Test Cleared** | 🟠 Оранжевый (`#FF9800`) | 🧪 |
+| **Warnings** | 🟡 Желтый (`#FFA500`) | ⚠️ |
+| **Errors** | 🔴 Красный (`#FF0000`) | ❌ |
+
+---
+
+## 🔍 Как использовать
+
+### 1. Открыть DevTools Console
+
+```
+Chrome/Edge: F12 → Console tab
+Firefox: F12 → Console tab
+Safari: Cmd+Option+C
+```
+
+### 2. Просмотреть события
+
+Все события логируются **автоматически**:
+
+- При каждом переходе между экранами → **Page View**
+- При попадании на экран с AB-тестом → **AB Test Impression**
+
+### 3. Развернуть группу
+
+Клик на `▼` (или стрелку) чтобы увидеть детали:
+
+```
+▼ [GA] 📊 Page View Event Sent ← Клик здесь
+ 🕐 Timestamp: ...
+ 📍 URL: ...
+ ...
+```
+
+### 4. Проверить Network Tab
+
+После каждого лога проверьте Network tab:
+
+```
+DevTools → Network → Filter: "collect"
+
+Должны появиться POST запросы:
+POST /g/collect?v=2&tid=G-XXX&en=page_view...
+POST /g/collect?v=2&tid=G-XXX&en=experiment_impression...
+```
+
+### 5. Проверить sessionStorage
+
+```javascript
+// В консоли браузера:
+Object.keys(sessionStorage)
+ .filter(key => key.startsWith("unleash_impression_"))
+ .forEach(key => console.log(key, sessionStorage.getItem(key)));
+
+// Вывод:
+// unleash_impression_soulmate-onboarding-image_v1 "true"
+// unleash_impression_soulmate-trial-grid_grid "true"
+```
+
+---
+
+## 🧪 Тестирование AB-тестов
+
+### Очистить историю и переотправить
+
+```javascript
+// В консоли браузера:
+import { clearUnleashImpressions } from "@/lib/funnel/unleash";
+
+// Очистить все impression события
+clearUnleashImpressions();
+
+// Перезагрузить страницу
+window.location.reload();
+
+// События отправятся заново!
+```
+
+### Вручную проверить ключи sessionStorage
+
+```javascript
+// Посмотреть все AB test ключи:
+Object.keys(sessionStorage)
+ .filter(key => key.startsWith("unleash_impression_"));
+
+// Удалить конкретный ключ:
+sessionStorage.removeItem("unleash_impression_soulmate-onboarding-image_v1");
+
+// Удалить все impression ключи:
+Object.keys(sessionStorage)
+ .filter(key => key.startsWith("unleash_impression_"))
+ .forEach(key => sessionStorage.removeItem(key));
+```
+
+---
+
+## 📊 Пример полного flow
+
+### Сценарий: Пользователь проходит воронку Soulmate
+
+```
+1. Открытие /soulmate/onboarding
+ ↓
+ [GA] 📊 Page View Event Sent
+ 🕐 2025-10-23T19:15:40.000Z
+ 📍 /soulmate/onboarding
+
+ [GA] 🧪 AB Test Impression Event Sent
+ 🏷️ soulmate-onboarding-image
+ 🎯 v1
+
+2. Переход на /soulmate/gender
+ ↓
+ [GA] 📊 Page View Event Sent
+ 🕐 2025-10-23T19:16:05.000Z
+ 📍 /soulmate/gender
+
+3. Переход на /soulmate/partner-age
+ ↓
+ [GA] 📊 Page View Event Sent
+ 🕐 2025-10-23T19:16:30.000Z
+ 📍 /soulmate/partner-age
+
+...18 экранов спустя...
+
+4. Переход на /soulmate/email
+ ↓
+ [GA] 📊 Page View Event Sent
+ 🕐 2025-10-23T19:20:15.000Z
+ 📍 /soulmate/email
+
+ [GA] 🧪 AB Test Impression Event Sent
+ 🏷️ soulmate-trial-grid
+ 🎯 grid
+
+5. Возврат назад на /soulmate/onboarding
+ ↓
+ [GA] 📊 Page View Event Sent
+ 🕐 2025-10-23T19:21:00.000Z
+ 📍 /soulmate/onboarding
+
+ [GA] 🧪 AB Test Impression SKIPPED (Already Sent)
+ 🏷️ soulmate-onboarding-image
+ 🎯 v1
+ ⚠️ Already sent in this session
+```
+
+---
+
+## 🎯 Преимущества новых логов
+
+### ✅ Уверенность в отправке
+
+Теперь вы **точно видите**:
+- ✅ Событие отправлено в GA
+- ⏰ Когда именно (timestamp)
+- 📦 Какие данные (payload)
+- 💾 Сохранено в sessionStorage
+
+### ✅ Легкая отладка
+
+При проблемах сразу видно:
+- ❌ GA не загружен
+- ⚠️ Событие уже отправлялось
+- ⚠️ Невалидный вариант AB-теста
+
+### ✅ Удобная навигация
+
+- Логи сгруппированы (не захламляют консоль)
+- Цветное кодирование для быстрой идентификации
+- Эмодзи для визуальных маркеров
+
+### ✅ Полная трассируемость
+
+Каждый лог содержит:
+- 🕐 Timestamp (ISO 8601)
+- 📍 URL / Flag / Variant
+- 📦 Полный payload
+- ✅ Статус отправки
+- 💡 Подсказки при ошибках
+
+---
+
+## 🔗 Связанные документы
+
+- `GA_AB_TEST_ANALYSIS.md` - Техническая документация системы
+- `SOULMATE_AB_TESTS_TIMELINE.md` - Детальный анализ AB-тестов Soulmate
+- `SOULMATE_AB_QUICK_REFERENCE.md` - Быстрая справка по AB-тестам
+
+---
+
+## 📝 Примечания
+
+### Production vs Development
+
+Логи работают **в обоих режимах**:
+- **Development**: Все логи показываются
+- **Production**: Все логи показываются (для проверки в реальном времени)
+
+Если нужно отключить логи в production, можно обернуть в условие:
+
+```typescript
+if (process.env.NODE_ENV === "development") {
+ console.groupCollapsed(...);
+}
+```
+
+### Производительность
+
+**console.groupCollapsed** не влияет на производительность:
+- Группа свернута по умолчанию
+- Содержимое вычисляется только при раскрытии
+- Минимальный overhead
+
+### Browser Support
+
+Логи работают во всех современных браузерах:
+- ✅ Chrome/Edge (полная поддержка)
+- ✅ Firefox (полная поддержка)
+- ✅ Safari (полная поддержка, без цветов в groupCollapsed)
diff --git a/docs/GA_AB_TEST_ANALYSIS.md b/docs/GA_AB_TEST_ANALYSIS.md
new file mode 100644
index 0000000..4e2ede6
--- /dev/null
+++ b/docs/GA_AB_TEST_ANALYSIS.md
@@ -0,0 +1,375 @@
+# 📊 Анализ Google Analytics и AB-тестов в witlab-funnel
+
+## 🎯 Краткий ответ
+
+### Когда отправляется impression событие AB-теста?
+
+**✅ В момент когда пользователь попадает на экран с AB-тестом**
+
+- НЕ при загрузке всей воронки
+- НЕ при инициализации Unleash
+- Именно при рендеринге конкретного экрана в `FunnelRuntime`
+
+### Где происходит отправка?
+
+**Файл:** `src/components/funnel/FunnelRuntime.tsx` (строки 136-150)
+
+```typescript
+useEffect(() => {
+ if (currentScreenFlags.length === 0) return;
+
+ currentScreenFlags.forEach((flag) => {
+ const variant = activeVariants[flag];
+ sendUnleashImpression(flag, variant); // ← ЗДЕСЬ
+ });
+}, [currentScreenFlags, activeVariants]);
+```
+
+### Формат события в GA
+
+```javascript
+window.gtag("event", "experiment_impression", {
+ app_name: "witlab-funnel",
+ feature: "trial-button-test",
+ treatment: "v1"
+});
+```
+
+---
+
+## 🏗️ Архитектура
+
+### Иерархия компонентов
+
+```
+app/[funnelId]/layout.tsx
+├─ UnleashProvider (Unleash SDK)
+│ └─ PixelsProvider
+│ ├─ GoogleAnalytics ← загружает gtag.js
+│ └─ PageViewTracker
+│
+└─ FunnelUnleashWrapper ← собирает все флаги воронки
+ ├─ FlagVariantFetcher[] ← загружает варианты
+ └─ FunnelRuntime ← отправляет impression когда экран виден
+```
+
+---
+
+## ⏱️ Timeline событий
+
+```
+T+0ms Пользователь открывает /funnel/payment
+T+100ms GoogleAnalytics загружает gtag.js
+T+200ms FunnelUnleashWrapper сканирует воронку
+ Находит флаги: ["trial-button-test", "payment-variant"]
+T+300ms Unleash SDK возвращает варианты:
+ • trial-button-test → "v1"
+ • payment-variant → "v2"
+T+400ms FunnelRuntime монтируется
+ currentScreen = "payment"
+ currentScreenFlags = ["trial-button-test"]
+T+420ms useEffect срабатывает
+ ✅ sendUnleashImpression("trial-button-test", "v1")
+ ✅ window.gtag("event", "experiment_impression", {...})
+T+421ms Событие отправлено в Google Analytics
+```
+
+**При переходе на следующий экран:**
+
+```
+T+0ms Клик "Continue" → переход на /funnel/gender
+T+100ms currentScreen = "gender"
+ currentScreenFlags = ["payment-variant"]
+T+120ms ✅ sendUnleashImpression("payment-variant", "v2")
+ ✅ Второе событие отправлено
+```
+
+**При возврате назад:**
+
+```
+T+0ms Клик "Back" → возврат на /funnel/payment
+T+100ms currentScreen = "payment"
+ currentScreenFlags = ["trial-button-test"]
+T+120ms sendUnleashImpression проверяет sessionStorage
+ ❌ Уже отправлялось - пропускаем
+```
+
+---
+
+## 🔧 Ключевые компоненты
+
+### 1. Инициализация Google Analytics
+
+**Файл:** `src/components/analytics/GoogleAnalytics.tsx`
+
+```typescript
+
+
+```
+
+### 2. Сбор флагов из воронки
+
+**Файл:** `src/components/funnel/FunnelUnleashWrapper.tsx`
+
+```typescript
+// Сканирует ВСЕ экраны и собирает уникальные флаги
+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]);
+```
+
+### 3. Определение флагов текущего экрана
+
+**Файл:** `src/components/funnel/FunnelRuntime.tsx`
+
+```typescript
+// Собираем флаги только для ТЕКУЩЕГО экрана
+const currentScreenFlags = useMemo(() => {
+ const flags = new Set();
+
+ currentScreen.variants?.forEach((variant) => {
+ variant.conditions.forEach((condition) => {
+ if (condition.conditionType === "unleash" && condition.unleashFlag) {
+ flags.add(condition.unleashFlag);
+ }
+ });
+ });
+
+ currentScreen.navigation?.rules?.forEach((rule) => {
+ rule.conditions.forEach((condition) => {
+ if (condition.conditionType === "unleash" && condition.unleashFlag) {
+ flags.add(condition.unleashFlag);
+ }
+ });
+ });
+
+ return Array.from(flags);
+}, [currentScreen]);
+```
+
+### 4. Отправка impression
+
+**Файл:** `src/components/funnel/FunnelRuntime.tsx`
+
+```typescript
+// ✅ ЗДЕСЬ ОТПРАВКА
+useEffect(() => {
+ if (currentScreenFlags.length === 0) {
+ return; // Нет AB тестов
+ }
+
+ currentScreenFlags.forEach((flag) => {
+ const variant = activeVariants[flag];
+ sendUnleashImpression(flag, variant);
+ });
+}, [currentScreenFlags, activeVariants]);
+```
+
+### 5. Функция sendUnleashImpression
+
+**Файл:** `src/lib/funnel/unleash/sendImpression.ts`
+
+```typescript
+export function sendUnleashImpression(flag: string, variant: string | undefined) {
+ // 1. Валидация варианта
+ if (!variant || variant === "disabled") return;
+
+ // 2. Проверка браузера
+ if (typeof window === "undefined") return;
+
+ // 3. ✅ ЗАЩИТА ОТ ДУБЛИКАТОВ
+ const storageKey = `unleash_impression_${flag}_${variant}`;
+ if (sessionStorage.getItem(storageKey)) {
+ return; // Уже отправлялось
+ }
+
+ // 4. Проверка GA
+ if (!window.gtag) {
+ console.warn("Google Analytics not available");
+ return;
+ }
+
+ // 5. ✅ ОТПРАВКА
+ window.gtag("event", "experiment_impression", {
+ app_name: "witlab-funnel",
+ feature: flag,
+ treatment: variant,
+ });
+
+ // 6. Пометка
+ sessionStorage.setItem(storageKey, "true");
+}
+```
+
+---
+
+## 🛡️ Защита от дубликатов
+
+### sessionStorage предотвращает повторную отправку
+
+```typescript
+const storageKey = `unleash_impression_${flag}_${variant}`;
+// Пример: "unleash_impression_trial-button-test_v1"
+
+if (sessionStorage.getItem(storageKey)) {
+ return; // Уже отправлялось в этой сессии браузера
+}
+
+// Отправка...
+sessionStorage.setItem(storageKey, "true");
+```
+
+### Когда очищается?
+
+| Действие | Очищается? | Отправится заново? |
+|----------|------------|-------------------|
+| Переход между экранами | ❌ | ❌ |
+| F5 (перезагрузка) | ❌ | ❌ |
+| Закрытие вкладки | ✅ | ✅ |
+| Новая вкладка | ✅ | ✅ |
+
+---
+
+## 🐛 Отладка
+
+### 1. Console logs (dev mode)
+
+```javascript
+[FunnelUnleashWrapper] Active variants: { trial-button-test: "v1" }
+[Unleash Impression] ✅ Sent successfully: { feature: "trial-button-test", variant: "v1" }
+[Unleash Impression] Skipped (already sent): { feature: "trial-button-test", variant: "v1" }
+```
+
+### 2. Network Tab
+
+Фильтр: `collect` или `analytics.google.com`
+
+```
+POST /g/collect?v=2&tid=G-XXX&en=experiment_impression
+ &ep.app_name=witlab-funnel
+ &ep.feature=trial-button-test
+ &ep.treatment=v1
+```
+
+### 3. Google Analytics DebugView
+
+```javascript
+// В консоли:
+localStorage.setItem('google_analytics_debug', '1');
+// Перезагрузить страницу
+// Открыть GA → Admin → DebugView
+```
+
+### 4. Проверка gtag
+
+```javascript
+// В консоли браузера:
+console.log(typeof window.gtag);
+// "function" - ✅ GA загружен
+// "undefined" - ❌ GA не загружен
+
+// Тестовое событие:
+window.gtag("event", "test_event", { test_param: "test" });
+```
+
+### 5. sessionStorage
+
+Chrome DevTools → Application → Session Storage
+
+```
+unleash_impression_trial-button-test_v1 "true"
+unleash_impression_onboarding-flow_short "true"
+```
+
+### 6. Очистка для тестирования
+
+```typescript
+import { clearUnleashImpressions } from "@/lib/funnel/unleash";
+clearUnleashImpressions();
+// Очистит все "unleash_impression_*" ключи
+```
+
+---
+
+## 📚 Ключевые файлы
+
+### Google Analytics
+- `src/components/analytics/GoogleAnalytics.tsx` - загрузка gtag
+- `src/components/providers/PixelsProvider.tsx` - провайдер аналитики
+- `src/components/analytics/PageViewTracker.tsx` - page_view события
+
+### AB тестирование (Unleash)
+- `src/lib/funnel/unleash/sendImpression.ts` ← **Отправка impression**
+- `src/components/funnel/FunnelRuntime.tsx` ← **Момент отправки**
+- `src/components/funnel/FunnelUnleashWrapper.tsx` - сбор флагов
+- `src/lib/funnel/unleash/UnleashProvider.tsx` - инициализация Unleash
+- `src/lib/funnel/unleash/UnleashContext.tsx` - контекст вариантов
+
+### Документация
+- `docs/UNLEASH_ANALYTICS_FLOW.md` - подробный flow
+- `docs/UNLEASH_ANALYTICS_FIX.md` - проблемы и решения
+- `docs/AB_TESTING_GUIDE.md` - руководство по AB тестам
+
+---
+
+## ✅ Итоговая сводка
+
+### Момент отправки impression
+
+**Когда пользователь попадает на экран с AB-тестом:**
+
+1. `FunnelRuntime` рендерится с `currentScreen`
+2. `currentScreenFlags` вычисляются для текущего экрана
+3. `useEffect` срабатывает и вызывает `sendUnleashImpression`
+4. Проверяется `sessionStorage` (не отправлялось ли)
+5. Отправляется `window.gtag("event", "experiment_impression", {...})`
+6. Помечается в `sessionStorage` как отправленное
+
+### Защита от дубликатов
+
+- ✅ sessionStorage хранит отправленные события
+- ✅ При возврате назад события НЕ отправляются повторно
+- ✅ При перезагрузке F5 события НЕ отправляются повторно
+- ✅ При закрытии вкладки история очищается (новая сессия)
+
+### Формат данных
+
+```javascript
+{
+ event: "experiment_impression",
+ app_name: "witlab-funnel",
+ feature: "название-флага",
+ treatment: "вариант"
+}
+```
diff --git a/docs/GA_AB_TEST_EXAMPLES.md b/docs/GA_AB_TEST_EXAMPLES.md
new file mode 100644
index 0000000..78592bf
--- /dev/null
+++ b/docs/GA_AB_TEST_EXAMPLES.md
@@ -0,0 +1,572 @@
+# 📊 Примеры работы AB-тестов и Google Analytics
+
+## 🎬 Сценарий 1: Первый вход пользователя
+
+### Воронка с 2 AB-тестами
+
+```json
+{
+ "meta": {
+ "id": "soulmate",
+ "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"]
+ }]
+ }]
+ }
+ }
+ ]
+}
+```
+
+### Временная последовательность
+
+```
+┌─────────────────────────────────────────────────────────┐
+│ T+0ms: Пользователь открывает /soulmate/payment │
+└─────────────────────────────────────────────────────────┘
+ │
+ ├─ Server-side render
+ ├─ layout.tsx загружается
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+50ms: UnleashProvider инициализируется │
+│ Подключение к Unleash API │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+100ms: PixelsProvider монтируется │
+│ GoogleAnalytics загружает gtag.js │
+│ window.gtag становится доступен │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+200ms: FunnelUnleashWrapper сканирует воронку │
+│ Находит флаги: │
+│ • trial-button-test (из payment.variants) │
+│ • onboarding-flow (из gender.navigation) │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+300ms: FlagVariantFetcher загружает варианты │
+│ Unleash SDK возвращает: │
+│ • trial-button-test → "v1" │
+│ • onboarding-flow → "short" │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+350ms: activeVariants обновляется │
+│ { │
+│ "trial-button-test": "v1", │
+│ "onboarding-flow": "short" │
+│ } │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+400ms: FunnelRuntime монтируется │
+│ currentScreen = payment экран │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+410ms: currentScreenFlags вычисляется │
+│ Анализирует payment экран: │
+│ • payment.variants → trial-button-test │
+│ • payment.navigation → нет флагов │
+│ Результат: ["trial-button-test"] │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+420ms: useEffect срабатывает │
+│ currentScreenFlags = ["trial-button-test"] │
+│ activeVariants["trial-button-test"] = "v1" │
+│ │
+│ sendUnleashImpression("trial-button-test", "v1")│
+└─────────────────────────────────────────────────────────┘
+ │
+ ├─ Проверка: вариант валидный ✅
+ ├─ Проверка: браузер ✅
+ ├─ Проверка sessionStorage: пусто ✅
+ ├─ Проверка window.gtag: есть ✅
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+421ms: ОТПРАВКА В GOOGLE ANALYTICS │
+│ │
+│ window.gtag("event", "experiment_impression", { │
+│ app_name: "witlab-funnel", │
+│ feature: "trial-button-test", │
+│ treatment: "v1" │
+│ }); │
+│ │
+│ sessionStorage.setItem( │
+│ "unleash_impression_trial-button-test_v1", │
+│ "true" │
+│ ); │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+422ms: Network request отправлен │
+│ POST /g/collect?v=2&tid=G-XXX │
+│ &en=experiment_impression │
+│ &ep.feature=trial-button-test │
+│ &ep.treatment=v1 │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ Console (development): │
+│ [Unleash Impression] ✅ Sent successfully: │
+│ { feature: "trial-button-test", variant: "v1" } │
+└─────────────────────────────────────────────────────────┘
+```
+
+---
+
+## 🎬 Сценарий 2: Переход на следующий экран
+
+```
+┌─────────────────────────────────────────────────────────┐
+│ T+0ms: Пользователь нажимает "Continue" │
+│ Router.push("/soulmate/gender") │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+50ms: URL изменился → /soulmate/gender │
+│ FunnelRuntime ре-рендерится │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+100ms: currentScreen обновляется │
+│ currentScreen = gender экран │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+110ms: currentScreenFlags пересчитывается │
+│ Анализирует gender экран: │
+│ • gender.variants → нет флагов │
+│ • gender.navigation → onboarding-flow │
+│ Результат: ["onboarding-flow"] │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+120ms: useEffect срабатывает (deps изменились) │
+│ currentScreenFlags = ["onboarding-flow"] │
+│ activeVariants["onboarding-flow"] = "short" │
+│ │
+│ sendUnleashImpression("onboarding-flow", "short")│
+└─────────────────────────────────────────────────────────┘
+ │
+ ├─ Проверка sessionStorage:
+ │ "unleash_impression_onboarding-flow_short"
+ │ не найдено ✅
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+121ms: ОТПРАВКА ВТОРОГО СОБЫТИЯ │
+│ │
+│ window.gtag("event", "experiment_impression", { │
+│ app_name: "witlab-funnel", │
+│ feature: "onboarding-flow", │
+│ treatment: "short" │
+│ }); │
+│ │
+│ sessionStorage.setItem( │
+│ "unleash_impression_onboarding-flow_short", │
+│ "true" │
+│ ); │
+└─────────────────────────────────────────────────────────┘
+```
+
+### Состояние sessionStorage
+
+```javascript
+// После первого экрана:
+{
+ "unleash_impression_trial-button-test_v1": "true"
+}
+
+// После второго экрана:
+{
+ "unleash_impression_trial-button-test_v1": "true",
+ "unleash_impression_onboarding-flow_short": "true"
+}
+```
+
+---
+
+## 🎬 Сценарий 3: Возврат назад (защита от дубликатов)
+
+```
+┌─────────────────────────────────────────────────────────┐
+│ T+0ms: Пользователь нажимает "Back" │
+│ Router.push("/soulmate/payment") │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+50ms: URL изменился → /soulmate/payment │
+│ FunnelRuntime ре-рендерится │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+100ms: currentScreen = payment (снова) │
+│ currentScreenFlags = ["trial-button-test"] │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+110ms: useEffect срабатывает │
+│ sendUnleashImpression("trial-button-test", "v1")│
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ Проверка sessionStorage: │
+│ │
+│ const key = "unleash_impression_trial-button-test_v1"; │
+│ const alreadySent = sessionStorage.getItem(key); │
+│ // "true" ← Уже отправлялось! │
+│ │
+│ if (alreadySent) { │
+│ return; // ❌ ОТПРАВКА НЕ ПРОИСХОДИТ │
+│ } │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ Console (development): │
+│ [Unleash Impression] Skipped (already sent): │
+│ { feature: "trial-button-test", variant: "v1" } │
+└─────────────────────────────────────────────────────────┘
+```
+
+---
+
+## 🎬 Сценарий 4: Перезагрузка страницы (F5)
+
+```
+┌─────────────────────────────────────────────────────────┐
+│ Пользователь на экране /soulmate/gender │
+│ sessionStorage содержит: │
+│ { │
+│ "unleash_impression_trial-button-test_v1": "true", │
+│ "unleash_impression_onboarding-flow_short": "true" │
+│ } │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+0ms: Пользователь нажимает F5 │
+│ Браузер перезагружает страницу │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ ВАЖНО: sessionStorage НЕ очищается при перезагрузке! │
+│ Данные сохраняются! │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+500ms: Страница загружена заново │
+│ FunnelRuntime монтируется снова │
+│ currentScreen = gender │
+│ currentScreenFlags = ["onboarding-flow"] │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ useEffect срабатывает: │
+│ sendUnleashImpression("onboarding-flow", "short") │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ Проверка sessionStorage: │
+│ "unleash_impression_onboarding-flow_short" = "true" │
+│ │
+│ ❌ УЖЕ ОТПРАВЛЯЛОСЬ - ПРОПУСКАЕМ │
+└─────────────────────────────────────────────────────────┘
+```
+
+**Результат:** Даже после F5 события НЕ отправляются повторно.
+
+---
+
+## 🎬 Сценарий 5: Новая вкладка / Закрытие браузера
+
+```
+┌─────────────────────────────────────────────────────────┐
+│ ВКЛАДКА 1: Пользователь прошел воронку │
+│ sessionStorage: │
+│ { "unleash_impression_trial-button-test_v1": "true" } │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ Пользователь открывает НОВУЮ ВКЛАДКУ │
+│ с тем же URL: /soulmate/payment │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ ВКЛАДКА 2: Новая сессия браузера! │
+│ sessionStorage пустой: │
+│ {} │
+│ │
+│ (sessionStorage изолирован для каждой вкладки) │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ FunnelRuntime загружается: │
+│ sendUnleashImpression("trial-button-test", "v1") │
+│ │
+│ Проверка sessionStorage: ПУСТО │
+│ ✅ СОБЫТИЕ ОТПРАВЛЯЕТСЯ ЗАНОВО │
+└─────────────────────────────────────────────────────────┘
+```
+
+**Важно:** sessionStorage изолирован для каждой вкладки браузера.
+
+---
+
+## 📊 Что видно в Google Analytics
+
+### Events Report
+
+```
+Event name: experiment_impression
+Total events: 2,345
+
+By feature parameter:
+┌────────────────────┬───────────┬────────┐
+│ Feature │ Count │ Users │
+├────────────────────┼───────────┼────────┤
+│ trial-button-test │ 1,234 │ 987 │
+│ onboarding-flow │ 1,111 │ 896 │
+└────────────────────┴───────────┴────────┘
+
+By treatment parameter:
+┌────────────────────┬───────────┬────────┐
+│ Treatment │ Count │ Users │
+├────────────────────┼───────────┼────────┤
+│ v1 │ 634 │ 507 │
+│ v2 │ 600 │ 480 │
+│ control │ 555 │ 445 │
+│ short │ 556 │ 448 │
+└────────────────────┴───────────┴────────┘
+
+Cross-tabulation:
+┌────────────────────┬───────────┬────────┐
+│ Feature + Treatment│ Count │ Users │
+├────────────────────┼───────────┼────────┤
+│ trial-button-test │ │ │
+│ ├─ v1 │ 634 │ 507 │
+│ └─ v2 │ 600 │ 480 │
+│ │ │ │
+│ onboarding-flow │ │ │
+│ ├─ short │ 556 │ 448 │
+│ └─ control │ 555 │ 445 │
+└────────────────────┴───────────┴────────┘
+```
+
+### DebugView (Realtime)
+
+```
+User: 12345abc
+Session ID: sess_xyz789
+
+Events:
+┌─────────┬────────────────────────┬────────────────────┐
+│ Time │ Event │ Parameters │
+├─────────┼────────────────────────┼────────────────────┤
+│ 14:32:10│ page_view │ page: /payment │
+│ 14:32:11│ experiment_impression │ feature: trial-.. │
+│ │ │ treatment: v1 │
+│ 14:32:45│ page_view │ page: /gender │
+│ 14:32:46│ experiment_impression │ feature: onboard.. │
+│ │ │ treatment: short │
+└─────────┴────────────────────────┴────────────────────┘
+```
+
+---
+
+## 🔍 Network Tab Примеры
+
+### Первое impression событие
+
+```http
+POST /g/collect HTTP/1.1
+Host: www.google-analytics.com
+
+Query Parameters:
+v=2
+tid=G-XXXXXXXXXX
+_p=1234567890
+cid=abc-def-ghi-jkl
+en=experiment_impression ← Event Name
+epn.value=1
+ep.app_name=witlab-funnel ← Custom Parameter
+ep.feature=trial-button-test ← Custom Parameter
+ep.treatment=v1 ← Custom Parameter
+_s=1
+```
+
+### Второе impression событие
+
+```http
+POST /g/collect HTTP/1.1
+Host: www.google-analytics.com
+
+Query Parameters:
+v=2
+tid=G-XXXXXXXXXX
+en=experiment_impression
+ep.app_name=witlab-funnel
+ep.feature=onboarding-flow ← Другой флаг
+ep.treatment=short ← Другой вариант
+_s=2
+```
+
+---
+
+## 🧪 Тестирование
+
+### 1. Очистка истории для повторного тестирования
+
+```javascript
+// В консоли браузера:
+import { clearUnleashImpressions } from "@/lib/funnel/unleash";
+
+// Очистит все impression ключи
+clearUnleashImpressions();
+
+// Или вручную:
+Object.keys(sessionStorage)
+ .filter(key => key.startsWith("unleash_impression_"))
+ .forEach(key => sessionStorage.removeItem(key));
+
+// После этого события отправятся заново
+```
+
+### 2. Проверка текущего состояния
+
+```javascript
+// Посмотреть все impression ключи:
+Object.keys(sessionStorage)
+ .filter(key => key.startsWith("unleash_impression_"))
+ .forEach(key => {
+ console.log(key, sessionStorage.getItem(key));
+ });
+
+// Вывод:
+// unleash_impression_trial-button-test_v1 "true"
+// unleash_impression_onboarding-flow_short "true"
+```
+
+### 3. Имитация нового пользователя
+
+```javascript
+// 1. Очистить sessionStorage
+sessionStorage.clear();
+
+// 2. Открыть воронку в новой вкладке Incognito
+// ИЛИ
+// 3. Перезапустить браузер
+
+// События отправятся как для нового пользователя
+```
+
+---
+
+## 📈 Практические примеры AB тестов
+
+### Тест 1: Кнопка оплаты
+
+```json
+{
+ "id": "payment",
+ "variants": [{
+ "conditions": [{
+ "conditionType": "unleash",
+ "unleashFlag": "trial-payment-button",
+ "unleashVariants": ["v1"]
+ }],
+ "override": {
+ "bottomActionButton": {
+ "text": "Start 7-Day Free Trial"
+ }
+ }
+ }]
+}
+```
+
+**Unleash возвращает:**
+- 50% пользователей: `v1` (кнопка "Start 7-Day Free Trial")
+- 50% пользователей: `disabled` (кнопка "Continue to Payment")
+
+**GA события:**
+```javascript
+// Группа A (v1):
+{ feature: "trial-payment-button", treatment: "v1" }
+
+// Группа B (disabled): НЕТ события
+// потому что sendUnleashImpression пропускает variant="disabled"
+```
+
+### Тест 2: Короткая vs длинная воронка
+
+```json
+{
+ "id": "intro",
+ "navigation": {
+ "rules": [{
+ "conditions": [{
+ "conditionType": "unleash",
+ "unleashFlag": "funnel-length-test",
+ "unleashVariants": ["short"]
+ }],
+ "nextScreenId": "payment"
+ }],
+ "default": "details"
+ }
+}
+```
+
+**Unleash возвращает:**
+- 50%: `short` → переход сразу на payment (3 экрана)
+- 50%: `disabled` → переход на details (5 экранов)
+
+**GA события для обеих групп:**
+```javascript
+// Все пользователи видят intro экран:
+{ feature: "funnel-length-test", treatment: "short" }
+{ feature: "funnel-length-test", treatment: "disabled" }
+
+// Но дальше идут разными путями!
+```
+
+---
+
+## ✅ Контрольный список
+
+### Перед запуском AB теста:
+
+- [ ] Google Analytics ID настроен в `funnel.meta.googleAnalyticsId`
+- [ ] Unleash флаг создан и активен
+- [ ] Unleash возвращает правильные варианты
+- [ ] События отправляются (проверить Network tab)
+- [ ] События видны в GA DebugView
+- [ ] sessionStorage работает корректно
+
+### При отладке:
+
+- [ ] `window.gtag` определен (в консоли)
+- [ ] Console логи показывают "Sent successfully"
+- [ ] Network tab показывает POST /g/collect
+- [ ] sessionStorage содержит impression ключи
+- [ ] DebugView показывает события в реальном времени
diff --git a/docs/SOULMATE_AB_QUICK_REFERENCE.md b/docs/SOULMATE_AB_QUICK_REFERENCE.md
new file mode 100644
index 0000000..ddb5c12
--- /dev/null
+++ b/docs/SOULMATE_AB_QUICK_REFERENCE.md
@@ -0,0 +1,178 @@
+# ⚡ Быстрая справка: AB-тесты Soulmate
+
+## 🧪 Два AB-теста
+
+### 1️⃣ `soulmate-onboarding-image`
+
+```
+┌──────────────────────────────────────────┐
+│ Экран: onboarding (1-й экран) │
+│ URL: /soulmate/onboarding │
+│ Когда: Сразу при входе в воронку │
+│ Timing: ~420ms после загрузки │
+│ │
+│ Тестирует: │
+│ • v0 = дефолтное изображение │
+│ • v1 = альтернативное изображение (PNG) │
+│ • v2 = видео (MP4) │
+│ │
+│ JSON: variants блок │
+└──────────────────────────────────────────┘
+ │
+ ▼ GA impression событие
+
+window.gtag("event", "experiment_impression", {
+ feature: "soulmate-onboarding-image",
+ treatment: "v1"
+});
+```
+
+### 2️⃣ `soulmate-trial-grid`
+
+```
+┌──────────────────────────────────────────┐
+│ Экран: email (19-й экран) │
+│ URL: /soulmate/email │
+│ Когда: При достижении email экрана │
+│ Timing: ~120ms после перехода │
+│ │
+│ Тестирует: │
+│ • coupon = переход на экран с купоном │
+│ • grid = переход на выбор тарифов │
+│ │
+│ JSON: navigation.rules блок │
+└──────────────────────────────────────────┘
+ │
+ ▼ GA impression событие
+
+window.gtag("event", "experiment_impression", {
+ feature: "soulmate-trial-grid",
+ treatment: "grid"
+});
+```
+
+---
+
+## 📍 Где в коде
+
+```typescript
+// src/components/funnel/FunnelRuntime.tsx (строки 103-150)
+
+// Определяем флаги текущего экрана
+const currentScreenFlags = useMemo(() => {
+ const flags = new Set();
+
+ // Из variants
+ currentScreen.variants?.forEach((variant) => {
+ if (condition.unleashFlag) flags.add(condition.unleashFlag);
+ });
+
+ // Из navigation.rules
+ currentScreen.navigation?.rules?.forEach((rule) => {
+ if (condition.unleashFlag) flags.add(condition.unleashFlag);
+ });
+
+ return Array.from(flags);
+}, [currentScreen]);
+
+// Отправляем impression когда экран виден
+useEffect(() => {
+ currentScreenFlags.forEach((flag) => {
+ const variant = activeVariants[flag];
+ sendUnleashImpression(flag, variant); // ← ОТПРАВКА
+ });
+}, [currentScreenFlags, activeVariants]);
+```
+
+---
+
+## ⏱️ Timeline полной воронки
+
+```
+┌─────────────────────────────────────────────────────────┐
+│ T+0 Открытие /soulmate/onboarding │
+├─────────────────────────────────────────────────────────┤
+│ T+420ms ✅ IMPRESSION #1 │
+│ feature: soulmate-onboarding-image │
+│ treatment: v1 │
+└─────────────────────────────────────────────────────────┘
+ │
+ │ Пользователь проходит 18 экранов
+ ▼
+┌─────────────────────────────────────────────────────────┐
+│ T+5min Достижение /soulmate/email │
+├─────────────────────────────────────────────────────────┤
+│ T+5m ✅ IMPRESSION #2 │
+│ +120ms feature: soulmate-trial-grid │
+│ treatment: grid │
+└─────────────────────────────────────────────────────────┘
+```
+
+---
+
+## 🔍 Быстрая проверка
+
+### Console (Development mode)
+
+```javascript
+// При загрузке onboarding экрана:
+[Unleash Impression] ✅ Sent successfully:
+{ feature: "soulmate-onboarding-image", variant: "v1" }
+
+// При достижении email экрана:
+[Unleash Impression] ✅ Sent successfully:
+{ feature: "soulmate-trial-grid", variant: "grid" }
+```
+
+### Network Tab
+
+```
+POST /g/collect?...
+ &en=experiment_impression
+ &ep.feature=soulmate-onboarding-image
+ &ep.treatment=v1
+
+POST /g/collect?...
+ &en=experiment_impression
+ &ep.feature=soulmate-trial-grid
+ &ep.treatment=grid
+```
+
+### Session Storage
+
+```javascript
+sessionStorage = {
+ "unleash_impression_soulmate-onboarding-image_v1": "true",
+ "unleash_impression_soulmate-trial-grid_grid": "true"
+}
+```
+
+---
+
+## 📊 Сравнение
+
+| | Test #1 | Test #2 |
+|--|---------|---------|
+| **Флаг** | `soulmate-onboarding-image` | `soulmate-trial-grid` |
+| **Экран** | `onboarding` (1-й) | `email` (19-й) |
+| **URL** | `/soulmate/onboarding` | `/soulmate/email` |
+| **В JSON** | `variants` | `navigation.rules` |
+| **Тестирует** | Медиа-контент | Навигацию |
+| **Когда** | При входе в воронку | Почти в конце воронки |
+
+---
+
+## ✅ Главное
+
+1. **Оба флага загружаются сразу** (preload) для быстрых переходов
+2. **Impression отправляются последовательно** - только когда пользователь видит экран
+3. **Защита от дубликатов** через sessionStorage работает автоматически
+4. **Один и тот же код** отправляет события для обоих тестов
+
+---
+
+## 📚 Детальная документация
+
+- `SOULMATE_AB_TESTS_TIMELINE.md` - полный анализ с диаграммами
+- `GA_AB_TEST_ANALYSIS.md` - техническая документация
+- `GA_AB_TEST_EXAMPLES.md` - примеры и сценарии
diff --git a/docs/SOULMATE_AB_TESTS_TIMELINE.md b/docs/SOULMATE_AB_TESTS_TIMELINE.md
new file mode 100644
index 0000000..90e8672
--- /dev/null
+++ b/docs/SOULMATE_AB_TESTS_TIMELINE.md
@@ -0,0 +1,567 @@
+# 🧪 Конкретный анализ AB-тестов в воронке Soulmate
+
+## 📋 Два AB-теста в воронке
+
+1. **`soulmate-onboarding-image`** - тест картинки/видео на первом экране
+2. **`soulmate-trial-grid`** - тест навигации после email экрана
+
+---
+
+## 🎯 AB-тест #1: `soulmate-onboarding-image`
+
+### 📍 Где находится в JSON
+
+**Файл:** `public/funnels/soulmate.json`
+
+**Экран:** `"onboarding"` (первый экран воронки)
+
+**Строки:** 51-106
+
+```json
+{
+ "id": "onboarding",
+ "template": "soulmate",
+ "variants": [
+ {
+ "conditions": [{
+ "conditionType": "unleash",
+ "unleashFlag": "soulmate-onboarding-image",
+ "unleashVariants": ["v0"]
+ }],
+ "overrides": {}
+ },
+ {
+ "conditions": [{
+ "conditionType": "unleash",
+ "unleashFlag": "soulmate-onboarding-image",
+ "unleashVariants": ["v1"]
+ }],
+ "overrides": {
+ "soulmatePortraitsDelivered": {
+ "mediaUrl": "/images/90b8c77f-c0cd-475d-a4de-bcabb3708c59.png",
+ "mediaType": "image"
+ }
+ }
+ },
+ {
+ "conditions": [{
+ "conditionType": "unleash",
+ "unleashFlag": "soulmate-onboarding-image",
+ "unleashVariants": ["v2"]
+ }],
+ "overrides": {
+ "soulmatePortraitsDelivered": {
+ "mediaUrl": "/images/275472b0-30e0-47d7-a1ab-8090bc9fb236.mp4",
+ "mediaType": "video"
+ }
+ }
+ }
+ ]
+}
+```
+
+### 🎬 Что тестируется
+
+Три варианта картинки/видео на первом экране:
+- **v0** - дефолтное изображение `/soulmate-portrait-delivered-male.jpg`
+- **v1** - альтернативное изображение (PNG)
+- **v2** - видео (MP4)
+
+### ⏱️ КОГДА ОТПРАВЛЯЕТСЯ impression событие
+
+```
+┌─────────────────────────────────────────────────────────┐
+│ T+0ms: Пользователь открывает /soulmate/onboarding │
+│ Это ПЕРВЫЙ экран воронки │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+100ms: GoogleAnalytics загружается (gtag.js) │
+│ window.gtag становится доступен │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+200ms: FunnelUnleashWrapper сканирует ВСЮ воронку │
+│ Находит флаги: │
+│ • soulmate-onboarding-image (из onboarding) │
+│ • soulmate-trial-grid (из email) │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+300ms: Unleash SDK возвращает варианты │
+│ • soulmate-onboarding-image → "v1" (например) │
+│ • soulmate-trial-grid → "grid" (например) │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+400ms: FunnelRuntime монтируется │
+│ currentScreen = onboarding экран │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+410ms: currentScreenFlags вычисляется │
+│ Анализирует onboarding экран: │
+│ • onboarding.variants → soulmate-onboarding-image│
+│ • onboarding.navigation → нет флагов │
+│ Результат: ["soulmate-onboarding-image"] │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+420ms: useEffect срабатывает │
+│ (FunnelRuntime.tsx, строки 136-150) │
+│ │
+│ ✅ sendUnleashImpression( │
+│ "soulmate-onboarding-image", │
+│ "v1" │
+│ ) │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+421ms: ✅ ОТПРАВКА В GOOGLE ANALYTICS │
+│ │
+│ window.gtag("event", "experiment_impression", { │
+│ app_name: "witlab-funnel", │
+│ feature: "soulmate-onboarding-image", │
+│ treatment: "v1" │
+│ }); │
+│ │
+│ sessionStorage.setItem( │
+│ "unleash_impression_soulmate-onboarding-image_v1", │
+│ "true" │
+│ ); │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ Console (development): │
+│ [Unleash Impression] ✅ Sent successfully: │
+│ { │
+│ feature: "soulmate-onboarding-image", │
+│ variant: "v1" │
+│ } │
+└─────────────────────────────────────────────────────────┘
+```
+
+### 📊 Когда КОНКРЕТНО
+
+**✅ Impression отправляется:** Сразу при входе пользователя в воронку на ПЕРВЫЙ экран "onboarding"
+
+**⏰ Timing:** ~420ms после загрузки страницы `/soulmate/onboarding`
+
+**🔧 Код:**
+- **Файл:** `src/components/funnel/FunnelRuntime.tsx` (строки 136-150)
+- **Функция:** `sendUnleashImpression()` из `src/lib/funnel/unleash/sendImpression.ts`
+
+**📍 Условие отправки:**
+```typescript
+// В FunnelRuntime.tsx
+const currentScreenFlags = useMemo(() => {
+ const flags = new Set();
+
+ // Сканирует onboarding.variants
+ currentScreen.variants?.forEach((variant) => {
+ variant.conditions.forEach((condition) => {
+ if (condition.conditionType === "unleash" && condition.unleashFlag) {
+ flags.add(condition.unleashFlag); // ← "soulmate-onboarding-image"
+ }
+ });
+ });
+
+ return Array.from(flags); // ["soulmate-onboarding-image"]
+}, [currentScreen]);
+
+useEffect(() => {
+ if (currentScreenFlags.length === 0) return;
+
+ currentScreenFlags.forEach((flag) => {
+ const variant = activeVariants[flag]; // "v1"
+ sendUnleashImpression(flag, variant); // ← ОТПРАВКА
+ });
+}, [currentScreenFlags, activeVariants]);
+```
+
+### 🔍 Как проверить в браузере
+
+```javascript
+// 1. Открыть /soulmate/onboarding
+// 2. Открыть DevTools → Console
+// 3. Увидеть:
+[Unleash Impression] ✅ Sent successfully: {
+ feature: "soulmate-onboarding-image",
+ variant: "v1" // или "v0", "v2"
+}
+
+// 4. DevTools → Network → Фильтр "collect"
+POST /g/collect?...&en=experiment_impression
+ &ep.feature=soulmate-onboarding-image
+ &ep.treatment=v1
+
+// 5. DevTools → Application → Session Storage
+unleash_impression_soulmate-onboarding-image_v1: "true"
+```
+
+---
+
+## 🎯 AB-тест #2: `soulmate-trial-grid`
+
+### 📍 Где находится в JSON
+
+**Файл:** `public/funnels/soulmate.json`
+
+**Экран:** `"email"` (экран ввода email)
+
+**Строки:** 2277-2309
+
+```json
+{
+ "id": "email",
+ "template": "email",
+ "navigation": {
+ "rules": [
+ {
+ "conditions": [{
+ "conditionType": "unleash",
+ "unleashFlag": "soulmate-trial-grid",
+ "unleashVariants": ["coupon"]
+ }],
+ "nextScreenId": "coupon"
+ },
+ {
+ "conditions": [{
+ "conditionType": "unleash",
+ "unleashFlag": "soulmate-trial-grid",
+ "unleashVariants": ["grid"]
+ }],
+ "nextScreenId": "trial-choice"
+ }
+ ],
+ "defaultNextScreenId": "coupon"
+ }
+}
+```
+
+### 🎬 Что тестируется
+
+Два варианта навигации после email экрана:
+- **coupon** - переход на экран с купоном (`coupon`)
+- **grid** - переход на экран с выбором тарифов (`trial-choice`)
+
+### ⏱️ КОГДА ОТПРАВЛЯЕТСЯ impression событие
+
+```
+┌─────────────────────────────────────────────────────────┐
+│ Пользователь прошел всю воронку: │
+│ onboarding → gender → partner-gender → ... → email │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+0ms: Пользователь попадает на экран /soulmate/email │
+│ Это 19-й экран воронки (почти в конце) │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ ВАЖНО: Unleash уже загружен! │
+│ activeVariants уже содержит: │
+│ { │
+│ "soulmate-onboarding-image": "v1", ← уже отправлено │
+│ "soulmate-trial-grid": "grid" ← еще НЕ отправлено│
+│ } │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+100ms: FunnelRuntime обновляется │
+│ currentScreen = email экран │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+110ms: currentScreenFlags пересчитывается │
+│ Анализирует email экран: │
+│ • email.variants → нет unleash флагов │
+│ • email.navigation.rules → soulmate-trial-grid │
+│ Результат: ["soulmate-trial-grid"] │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+120ms: useEffect срабатывает │
+│ (FunnelRuntime.tsx, строки 136-150) │
+│ │
+│ ✅ sendUnleashImpression( │
+│ "soulmate-trial-grid", │
+│ "grid" │
+│ ) │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+121ms: Проверка sessionStorage: │
+│ "unleash_impression_soulmate-trial-grid_grid" │
+│ НЕ найдено ✅ (первый раз на этом экране) │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ T+122ms: ✅ ОТПРАВКА В GOOGLE ANALYTICS │
+│ │
+│ window.gtag("event", "experiment_impression", { │
+│ app_name: "witlab-funnel", │
+│ feature: "soulmate-trial-grid", │
+│ treatment: "grid" │
+│ }); │
+│ │
+│ sessionStorage.setItem( │
+│ "unleash_impression_soulmate-trial-grid_grid", │
+│ "true" │
+│ ); │
+└─────────────────────────────────────────────────────────┘
+ │
+┌─────────────────────────────────────────────────────────┐
+│ Console (development): │
+│ [Unleash Impression] ✅ Sent successfully: │
+│ { │
+│ feature: "soulmate-trial-grid", │
+│ variant: "grid" │
+│ } │
+└─────────────────────────────────────────────────────────┘
+```
+
+### 📊 Когда КОНКРЕТНО
+
+**✅ Impression отправляется:** Когда пользователь доходит до экрана "email" (19-й экран воронки)
+
+**⏰ Timing:** ~120ms после перехода на `/soulmate/email`
+
+**🔧 Код:**
+- **Файл:** `src/components/funnel/FunnelRuntime.tsx` (строки 136-150)
+- **Функция:** `sendUnleashImpression()` из `src/lib/funnel/unleash/sendImpression.ts`
+
+**📍 Условие отправки:**
+```typescript
+// В FunnelRuntime.tsx
+const currentScreenFlags = useMemo(() => {
+ const flags = new Set();
+
+ // Сканирует email.variants (пусто)
+ // ...
+
+ // Сканирует email.navigation.rules
+ currentScreen.navigation?.rules?.forEach((rule) => {
+ rule.conditions.forEach((condition) => {
+ if (condition.conditionType === "unleash" && condition.unleashFlag) {
+ flags.add(condition.unleashFlag); // ← "soulmate-trial-grid"
+ }
+ });
+ });
+
+ return Array.from(flags); // ["soulmate-trial-grid"]
+}, [currentScreen]);
+
+useEffect(() => {
+ if (currentScreenFlags.length === 0) return;
+
+ currentScreenFlags.forEach((flag) => {
+ const variant = activeVariants[flag]; // "grid"
+ sendUnleashImpression(flag, variant); // ← ОТПРАВКА
+ });
+}, [currentScreenFlags, activeVariants]);
+```
+
+### 🔍 Как проверить в браузере
+
+```javascript
+// 1. Пройти всю воронку до экрана email: /soulmate/email
+// 2. Открыть DevTools → Console
+// 3. Увидеть:
+[Unleash Impression] ✅ Sent successfully: {
+ feature: "soulmate-trial-grid",
+ variant: "grid" // или "coupon"
+}
+
+// 4. DevTools → Network → Фильтр "collect"
+POST /g/collect?...&en=experiment_impression
+ &ep.feature=soulmate-trial-grid
+ &ep.treatment=grid
+
+// 5. DevTools → Application → Session Storage
+// Должно быть 2 ключа:
+unleash_impression_soulmate-onboarding-image_v1: "true"
+unleash_impression_soulmate-trial-grid_grid: "true"
+```
+
+---
+
+## 📊 Сравнительная таблица
+
+| Аспект | soulmate-onboarding-image | soulmate-trial-grid |
+|--------|---------------------------|---------------------|
+| **Экран** | `onboarding` (1-й экран) | `email` (19-й экран) |
+| **Позиция в JSON** | `variants` | `navigation.rules` |
+| **Что тестирует** | Картинка/видео на первом экране | Навигация после email |
+| **Варианты** | v0, v1, v2 | coupon, grid |
+| **Когда отправляется** | Сразу при входе в воронку | При достижении email экрана |
+| **Timing** | T+420ms после загрузки | T+120ms после перехода на email |
+| **URL** | `/soulmate/onboarding` | `/soulmate/email` |
+
+---
+
+## 🎯 Финальная timeline для полной воронки
+
+```
+T+0ms Пользователь открывает /soulmate/onboarding
+ │
+T+420ms ✅ IMPRESSION #1: soulmate-onboarding-image → v1
+ │
+T+5min Пользователь проходит всю воронку
+ │ (gender, partner-gender, analysis-target, partner-age,
+ │ partner-ethnicity, partner-eye-color, partner-hair-length,
+ │ burnout-support, burnout-result, birthdate,
+ │ nature-archetype, love-priority, love-priority-result,
+ │ relationship-block, qualities, qualities-result,
+ │ progress, progress-result)
+ │
+T+5min Пользователь доходит до /soulmate/email
+ │
+T+5min ✅ IMPRESSION #2: soulmate-trial-grid → grid
+ +120ms │
+ │
+T+5min Пользователь вводит email и нажимает Continue
+ +1min │
+ │
+ └─ Переход на trial-choice (если variant = "grid")
+ ИЛИ
+ Переход на coupon (если variant = "coupon")
+```
+
+---
+
+## 📝 Ключевые моменты
+
+### 1. Оба флага загружаются ЗАРАНЕЕ
+
+```
+FunnelUnleashWrapper сканирует ВСЮ воронку при загрузке
+→ Находит оба флага сразу:
+ • soulmate-onboarding-image
+ • soulmate-trial-grid
+→ Unleash SDK загружает варианты для ОБОИХ флагов
+→ Варианты сохраняются в activeVariants
+```
+
+**Результат:** Быстрый переход между экранами (флаги уже загружены).
+
+### 2. Impression отправляются ПОСЛЕДОВАТЕЛЬНО
+
+```
+Экран onboarding → impression для soulmate-onboarding-image
+Экран email → impression для soulmate-trial-grid
+```
+
+**Результат:** Точная аналитика - события отправляются только когда пользователь РЕАЛЬНО видит экран.
+
+### 3. Защита от дубликатов работает
+
+```
+sessionStorage хранит:
+{
+ "unleash_impression_soulmate-onboarding-image_v1": "true",
+ "unleash_impression_soulmate-trial-grid_grid": "true"
+}
+```
+
+**Результат:** Даже если пользователь вернется назад или перезагрузит страницу, события НЕ отправятся повторно.
+
+---
+
+## 🐛 Отладка
+
+### Проверка отправки первого теста
+
+```bash
+# 1. Открыть /soulmate/onboarding
+# 2. В консоли должно появиться:
+[Unleash Impression] ✅ Sent successfully: {
+ feature: "soulmate-onboarding-image",
+ variant: "v1"
+}
+
+# 3. В Network tab:
+POST /g/collect?...
+ &ep.feature=soulmate-onboarding-image
+ &ep.treatment=v1
+```
+
+### Проверка отправки второго теста
+
+```bash
+# 1. Пройти до /soulmate/email
+# 2. В консоли должно появиться:
+[Unleash Impression] ✅ Sent successfully: {
+ feature: "soulmate-trial-grid",
+ variant: "grid"
+}
+
+# 3. В Network tab:
+POST /g/collect?...
+ &ep.feature=soulmate-trial-grid
+ &ep.treatment=grid
+```
+
+### Проверка что оба события отправлены
+
+```javascript
+// В консоли браузера:
+Object.keys(sessionStorage)
+ .filter(key => key.startsWith("unleash_impression_"))
+ .forEach(key => console.log(key, sessionStorage.getItem(key)));
+
+// Вывод (если пользователь дошел до email):
+// unleash_impression_soulmate-onboarding-image_v1 "true"
+// unleash_impression_soulmate-trial-grid_grid "true"
+```
+
+---
+
+## ✅ Итоговый ответ
+
+### Когда отправляется `soulmate-onboarding-image`?
+
+**🎯 Сразу при входе в воронку на первый экран "onboarding"**
+- URL: `/soulmate/onboarding`
+- Timing: ~420ms после загрузки страницы
+- Экран: 1-й из ~20 экранов воронки
+
+### Когда отправляется `soulmate-trial-grid`?
+
+**🎯 Когда пользователь доходит до экрана "email" (почти в конце воронки)**
+- URL: `/soulmate/email`
+- Timing: ~120ms после перехода на экран
+- Экран: 19-й из ~20 экранов воронки
+
+### Код отправки (для обоих)
+
+**Файл:** `src/components/funnel/FunnelRuntime.tsx`
+
+**Строки:** 136-150
+
+```typescript
+useEffect(() => {
+ if (currentScreenFlags.length === 0) return;
+
+ currentScreenFlags.forEach((flag) => {
+ const variant = activeVariants[flag];
+ sendUnleashImpression(flag, variant); // ← ЗДЕСЬ
+ });
+}, [currentScreenFlags, activeVariants]);
+```
+
+**Функция:** `src/lib/funnel/unleash/sendImpression.ts`
+
+```typescript
+export function sendUnleashImpression(flag: string, variant: string | undefined) {
+ // Проверки...
+
+ window.gtag("event", "experiment_impression", {
+ app_name: "witlab-funnel",
+ feature: flag,
+ treatment: variant,
+ });
+
+ sessionStorage.setItem(`unleash_impression_${flag}_${variant}`, "true");
+}
+```
diff --git a/src/components/analytics/PageViewTracker.tsx b/src/components/analytics/PageViewTracker.tsx
index bfad6bf..2ec302c 100644
--- a/src/components/analytics/PageViewTracker.tsx
+++ b/src/components/analytics/PageViewTracker.tsx
@@ -17,15 +17,36 @@ export function PageViewTracker() {
useEffect(() => {
const url = pathname + (searchParams?.toString() ? `?${searchParams.toString()}` : "");
+ const timestamp = new Date().toISOString();
// Track page view in Google Analytics
if (typeof window !== "undefined" && typeof window.gtag === "function") {
- window.gtag("event", "page_view", {
+ const payload = {
page_path: url,
page_location: window.location.href,
page_title: document.title,
- });
- console.log(`[GA] Page view tracked: ${url}`);
+ };
+
+ window.gtag("event", "page_view", payload);
+
+ // Детальное логирование
+ console.groupCollapsed(
+ `%c[GA] 📊 Page View Event Sent`,
+ 'color: #4285F4; font-weight: bold'
+ );
+ console.log('🕐 Timestamp:', timestamp);
+ console.log('📍 URL:', url);
+ console.log('🌐 Full Location:', window.location.href);
+ console.log('📄 Page Title:', document.title);
+ console.log('📦 Payload:', payload);
+ console.log('✅ Status: Successfully sent to Google Analytics');
+ console.groupEnd();
+ } else {
+ console.warn(
+ `%c[GA] ⚠️ Page View NOT Sent`,
+ 'color: #FFA500; font-weight: bold',
+ '\nReason: Google Analytics not available (window.gtag is undefined)'
+ );
}
// Track page view in Yandex Metrika
@@ -33,7 +54,23 @@ export function PageViewTracker() {
const counterId = window.__YM_COUNTER_ID__;
if (counterId) {
window.ym(counterId, "hit", url);
- console.log(`[YM] Page view tracked: ${url}`);
+
+ // Детальное логирование
+ console.groupCollapsed(
+ `%c[YM] 📊 Page View Event Sent`,
+ 'color: #FF0000; font-weight: bold'
+ );
+ console.log('🕐 Timestamp:', timestamp);
+ console.log('📍 URL:', url);
+ console.log('🔢 Counter ID:', counterId);
+ console.log('✅ Status: Successfully sent to Yandex Metrika');
+ console.groupEnd();
+ } else {
+ console.warn(
+ `%c[YM] ⚠️ Page View NOT Sent`,
+ 'color: #FFA500; font-weight: bold',
+ '\nReason: Counter ID not found'
+ );
}
}
}, [pathname, searchParams]);
diff --git a/src/lib/funnel/unleash/sendImpression.ts b/src/lib/funnel/unleash/sendImpression.ts
index c60d02a..c58e85f 100644
--- a/src/lib/funnel/unleash/sendImpression.ts
+++ b/src/lib/funnel/unleash/sendImpression.ts
@@ -10,23 +10,25 @@
* @param variant - вариант который получил пользователь
*/
export function sendUnleashImpression(flag: string, variant: string | undefined) {
- if (process.env.NODE_ENV === "development") {
- console.log("[Unleash Impression] Called with:", { flag, variant });
- }
+ const timestamp = new Date().toISOString();
// Проверяем что вариант валидный
if (!variant || variant === "disabled") {
- if (process.env.NODE_ENV === "development") {
- console.log("[Unleash Impression] Skipped: invalid variant");
- }
+ console.groupCollapsed(
+ `%c[GA] 🧪 AB Test Impression SKIPPED`,
+ 'color: #9E9E9E; font-weight: bold'
+ );
+ console.log('🕐 Timestamp:', timestamp);
+ console.log('🏷️ Flag:', flag);
+ console.log('🎯 Variant:', variant);
+ console.log('⚠️ Reason: Invalid variant (disabled or undefined)');
+ console.groupEnd();
return;
}
// Проверяем что браузерное окружение
if (typeof window === "undefined") {
- if (process.env.NODE_ENV === "development") {
- console.log("[Unleash Impression] Skipped: not browser environment");
- }
+ console.warn('[GA] 🧪 AB Test Impression SKIPPED: Not browser environment');
return;
}
@@ -36,39 +38,62 @@ export function sendUnleashImpression(flag: string, variant: string | undefined)
if (alreadySent) {
// Уже отправляли - пропускаем
- if (process.env.NODE_ENV === "development") {
- console.log("[Unleash Impression] Skipped (already sent):", {
- feature: flag,
- variant: variant,
- });
- }
+ console.groupCollapsed(
+ `%c[GA] 🧪 AB Test Impression SKIPPED (Already Sent)`,
+ 'color: #9E9E9E; font-weight: bold'
+ );
+ console.log('🕐 Timestamp:', timestamp);
+ console.log('🏷️ Flag:', flag);
+ console.log('🎯 Variant:', variant);
+ console.log('💾 Storage Key:', storageKey);
+ console.log('⚠️ Reason: Already sent in this session');
+ console.log('📊 Check sessionStorage to verify');
+ console.groupEnd();
return;
}
// Проверяем наличие gtag
if (!window.gtag) {
- console.warn("[Unleash Impression] ❌ Google Analytics not available (window.gtag is undefined)");
- console.warn("[Unleash Impression] Check that GoogleAnalytics component is loaded with measurementId");
+ console.groupCollapsed(
+ `%c[GA] 🧪 AB Test Impression NOT Sent`,
+ 'color: #FF0000; font-weight: bold'
+ );
+ console.log('🕐 Timestamp:', timestamp);
+ console.log('🏷️ Flag:', flag);
+ console.log('🎯 Variant:', variant);
+ console.log('❌ Error: Google Analytics not available (window.gtag is undefined)');
+ console.log('💡 Solution: Check that GoogleAnalytics component is loaded with measurementId');
+ console.groupEnd();
return;
}
- // Отправляем событие в Google Analytics
- window.gtag("event", "experiment_impression", {
+ // Подготавливаем payload
+ const payload = {
app_name: "witlab-funnel",
feature: flag,
treatment: variant,
- });
+ };
+
+ // Отправляем событие в Google Analytics
+ window.gtag("event", "experiment_impression", payload);
// Помечаем что отправили
sessionStorage.setItem(storageKey, "true");
- // Debug в development
- if (process.env.NODE_ENV === "development") {
- console.log("[Unleash Impression] ✅ Sent successfully:", {
- feature: flag,
- variant: variant,
- });
- }
+ // Детальное логирование успешной отправки
+ console.groupCollapsed(
+ `%c[GA] 🧪 AB Test Impression Event Sent`,
+ 'color: #4285F4; font-weight: bold'
+ );
+ console.log('🕐 Timestamp:', timestamp);
+ console.log('🏷️ Flag:', flag);
+ console.log('🎯 Variant:', variant);
+ console.log('📦 Event Name:', 'experiment_impression');
+ console.log('📦 Payload:', payload);
+ console.log('💾 Storage Key:', storageKey);
+ console.log('✅ Status: Successfully sent to Google Analytics');
+ console.log('🔍 Verify in Network tab: Look for /g/collect requests');
+ console.groupEnd();
}
/**
@@ -80,11 +105,21 @@ export function clearUnleashImpressions() {
return;
}
- Object.keys(sessionStorage)
- .filter(key => key.startsWith("unleash_impression_"))
- .forEach(key => sessionStorage.removeItem(key));
+ const keysToRemove = Object.keys(sessionStorage)
+ .filter(key => key.startsWith("unleash_impression_"));
+
+ const timestamp = new Date().toISOString();
+
+ keysToRemove.forEach(key => sessionStorage.removeItem(key));
- if (process.env.NODE_ENV === "development") {
- console.log("[Unleash Impression] Cleared all impression history");
- }
+ console.groupCollapsed(
+ `%c[GA] 🧪 AB Test Impressions Cleared`,
+ 'color: #FF9800; font-weight: bold'
+ );
+ console.log('🕐 Timestamp:', timestamp);
+ console.log('🧹 Keys Removed:', keysToRemove.length);
+ console.log('📋 Removed Keys:', keysToRemove);
+ console.log('✅ Status: All AB test impression history cleared');
+ console.log('💡 New impressions will be sent on next screen view');
+ console.groupEnd();
}