386 lines
11 KiB
Markdown
386 lines
11 KiB
Markdown
# 🧪 AB Testing с Unleash в Воронках
|
||
|
||
Полное руководство по интеграции AB тестов через Unleash feature flags в систему воронок.
|
||
|
||
## 📋 Содержание
|
||
|
||
- [Настройка](#настройка)
|
||
- [Примеры использования](#примеры-использования)
|
||
- [API Reference](#api-reference)
|
||
- [Архитектура](#архитектура)
|
||
|
||
## 🔧 Настройка
|
||
|
||
### 1. Environment Variables
|
||
|
||
Добавьте в `.env.local`:
|
||
|
||
```bash
|
||
NEXT_PUBLIC_UNLEASH_URL=https://your-unleash-instance.com/api/frontend
|
||
NEXT_PUBLIC_UNLEASH_CLIENT_KEY=your-client-key
|
||
```
|
||
|
||
**Важно:** Если переменные не установлены, AB тесты будут отключены автоматически.
|
||
|
||
### 2. Настройка Unleash Dashboard
|
||
|
||
1. Создайте feature flag в Unleash (например, `trial-button-test`)
|
||
2. Добавьте варианты (v0, v1, v2, etc.)
|
||
3. Настройте stickiness на `sessionId` для консистентности
|
||
4. Добавьте gradual rollout strategy
|
||
|
||
## 💡 Примеры использования
|
||
|
||
### Пример 1: AB тест текста кнопки
|
||
|
||
**Сценарий:** Тестируем разные тексты кнопки оплаты
|
||
|
||
```json
|
||
{
|
||
"id": "payment-screen",
|
||
"template": "trialPayment",
|
||
"bottomActionButton": {
|
||
"text": "Continue"
|
||
},
|
||
"variants": [
|
||
{
|
||
"conditions": [
|
||
{
|
||
"screenId": "payment-screen",
|
||
"conditionType": "unleash",
|
||
"unleashFlag": "trial-button-test",
|
||
"unleashVariants": ["v1"],
|
||
"operator": "includesAny"
|
||
}
|
||
],
|
||
"overrides": {
|
||
"bottomActionButton": {
|
||
"text": "Start 3-Day Trial"
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"conditions": [
|
||
{
|
||
"screenId": "payment-screen",
|
||
"conditionType": "unleash",
|
||
"unleashFlag": "trial-button-test",
|
||
"unleashVariants": ["v2"],
|
||
"operator": "includesAny"
|
||
}
|
||
],
|
||
"overrides": {
|
||
"bottomActionButton": {
|
||
"text": "Get My Reading Now"
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**Результат:**
|
||
- v0 (контроль): "Continue"
|
||
- v1: "Start 3-Day Trial"
|
||
- v2: "Get My Reading Now"
|
||
|
||
### Пример 2: AB тест навигации
|
||
|
||
**Сценарий:** Тестируем короткий vs длинный onboarding
|
||
|
||
```json
|
||
{
|
||
"id": "gender-select",
|
||
"template": "list",
|
||
"navigation": {
|
||
"defaultNextScreenId": "birthdate",
|
||
"rules": [
|
||
{
|
||
"conditions": [
|
||
{
|
||
"screenId": "gender-select",
|
||
"conditionType": "unleash",
|
||
"unleashFlag": "onboarding-flow-test",
|
||
"unleashVariants": ["short"],
|
||
"operator": "equals"
|
||
}
|
||
],
|
||
"nextScreenId": "payment"
|
||
},
|
||
{
|
||
"conditions": [
|
||
{
|
||
"screenId": "gender-select",
|
||
"conditionType": "unleash",
|
||
"unleashFlag": "onboarding-flow-test",
|
||
"unleashVariants": ["long"],
|
||
"operator": "equals"
|
||
}
|
||
],
|
||
"nextScreenId": "relationship-status"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
**Результат:**
|
||
- v0/default: gender → birthdate
|
||
- short: gender → payment (пропускаем шаги)
|
||
- long: gender → relationship-status → ... → payment
|
||
|
||
### Пример 3: Комбинированные условия
|
||
|
||
**Сценарий:** AB тест только для женской аудитории
|
||
|
||
```json
|
||
{
|
||
"variants": [
|
||
{
|
||
"conditions": [
|
||
{
|
||
"screenId": "gender",
|
||
"conditionType": "options",
|
||
"optionIds": ["female"],
|
||
"operator": "includesAny"
|
||
},
|
||
{
|
||
"screenId": "payment",
|
||
"conditionType": "unleash",
|
||
"unleashFlag": "female-specific-test",
|
||
"unleashVariants": ["v1"],
|
||
"operator": "equals"
|
||
}
|
||
],
|
||
"overrides": {
|
||
"title": {
|
||
"text": "Special offer for you! ✨"
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
## 📚 API Reference
|
||
|
||
### NavigationConditionDefinition
|
||
|
||
```typescript
|
||
interface NavigationConditionDefinition {
|
||
screenId: string;
|
||
conditionType?: "options" | "values" | "unleash";
|
||
operator?: "includesAny" | "includesAll" | "includesExactly" | "equals";
|
||
|
||
// Для Unleash AB тестов
|
||
unleashFlag?: string;
|
||
unleashVariants?: string[];
|
||
|
||
// Для других типов
|
||
optionIds?: string[];
|
||
values?: string[];
|
||
}
|
||
```
|
||
|
||
### Операторы
|
||
|
||
| Оператор | Описание | Пример |
|
||
|----------|----------|--------|
|
||
| `includesAny` | Хотя бы один вариант совпадает | `["v1", "v2"]` → true если v1 ИЛИ v2 |
|
||
| `includesAll` | Все варианты совпадают | `["v1"]` → true если v1 (для одного = includesAny) |
|
||
| `includesExactly` | Только указанные варианты | Редко используется |
|
||
| `equals` | Точное совпадение | `["v1"]` → true только если v1 |
|
||
|
||
### Типы условий
|
||
|
||
| Тип | Использование | Пример |
|
||
|-----|---------------|--------|
|
||
| `options` | List экраны | `{ conditionType: "options", optionIds: ["male"] }` |
|
||
| `values` | Зодиак, возраст | `{ conditionType: "values", values: ["aries", "leo"] }` |
|
||
| `unleash` | AB тесты | `{ conditionType: "unleash", unleashFlag: "test-1" }` |
|
||
|
||
## 🏗 Архитектура
|
||
|
||
### Компоненты
|
||
|
||
```
|
||
UnleashProvider (от @unleash/proxy-client-react)
|
||
└── FunnelUnleashWrapper (собирает все флаги из воронки)
|
||
└── UnleashContextProvider (предоставляет активные варианты)
|
||
└── FunnelRuntime (использует варианты для navigation/variants)
|
||
```
|
||
|
||
### Поток данных
|
||
|
||
1. **FunnelUnleashWrapper** сканирует все экраны воронки
|
||
2. Находит все `unleashFlag` в conditions
|
||
3. Получает варианты для всех флагов через `useVariant`
|
||
4. Передает `{ flagName: variant }` в **UnleashContextProvider**
|
||
5. **FunnelRuntime** использует `unleashChecker` для проверки условий
|
||
6. **navigation.ts** и **variants.ts** вызывают `unleashChecker` при проверке
|
||
|
||
### Файловая структура
|
||
|
||
```
|
||
src/
|
||
├── lib/funnel/
|
||
│ ├── unleash/
|
||
│ │ ├── UnleashProvider.tsx # Wrapper для Unleash SDK
|
||
│ │ ├── UnleashContext.tsx # Context с активными вариантами
|
||
│ │ ├── useUnleash.ts # Hook для получения вариантов
|
||
│ │ └── index.ts
|
||
│ ├── navigation.ts # Поддержка unleash в условиях
|
||
│ ├── variants.ts # Поддержка unleash в вариантах
|
||
│ └── types.ts # Расширенные типы
|
||
├── components/
|
||
│ ├── funnel/
|
||
│ │ ├── FunnelUnleashWrapper.tsx # Сборщик флагов
|
||
│ │ └── FunnelRuntime.tsx # Интеграция unleashChecker
|
||
│ └── admin/builder/forms/
|
||
│ ├── UnleashConditionEditor.tsx # UI для настройки
|
||
│ ├── ConditionTypeSelector.tsx # Выбор типа
|
||
│ └── variants/
|
||
│ └── VariantConditionEditor.tsx # Интеграция в существующий UI
|
||
```
|
||
|
||
## 🎯 Best Practices
|
||
|
||
### 1. Naming Convention
|
||
|
||
```bash
|
||
# Формат: [page]-[element]-[description]
|
||
trial-button-text
|
||
onboarding-flow-length
|
||
payment-copy-variant
|
||
```
|
||
|
||
### 2. Variants Naming
|
||
|
||
```bash
|
||
# Всегда используйте v0 как контроль
|
||
v0 - контрольная группа (baseline)
|
||
v1 - вариант 1
|
||
v2 - вариант 2
|
||
```
|
||
|
||
### 3. Stickiness
|
||
|
||
**Всегда используйте `sessionId` для stickiness** в Unleash:
|
||
- Обеспечивает консистентность для анонимных пользователей
|
||
- Пользователь видит одинаковый вариант на всех экранах
|
||
- Не требует авторизации
|
||
|
||
### 4. Rollout Strategy
|
||
|
||
```bash
|
||
# Начните с малого
|
||
Week 1: 10% traffic → v1
|
||
Week 2: 50% traffic → v1
|
||
Week 3: 100% traffic → v1 (если winner)
|
||
```
|
||
|
||
## 🔍 Debugging
|
||
|
||
### Development Mode
|
||
|
||
В development режиме в консоли будут логи:
|
||
|
||
```bash
|
||
[Unleash] Flag "trial-button-test" = v1
|
||
[Unleash] Active variants: { "trial-button-test": "v1", "onboarding-flow": "short" }
|
||
```
|
||
|
||
### Query Parameters (только dev)
|
||
|
||
```bash
|
||
# Переопределить вариант флага
|
||
?trial-button-test=v2
|
||
|
||
# Комбинировать несколько
|
||
?trial-button-test=v1&onboarding-flow=short
|
||
```
|
||
|
||
### Admin Preview
|
||
|
||
В админке конструктора:
|
||
1. Экраны с AB тестами помечены значком 🧪
|
||
2. В превью можно переключать варианты
|
||
3. Validation показывает некорректные флаги
|
||
|
||
## ⚠️ Troubleshooting
|
||
|
||
### Флаг не работает
|
||
|
||
**Проверьте:**
|
||
1. ✅ Environment variables установлены
|
||
2. ✅ Флаг создан в Unleash Dashboard
|
||
3. ✅ Флаг включен (enabled)
|
||
4. ✅ Правильно указано `unleashFlag` в JSON
|
||
5. ✅ Варианты существуют в Unleash
|
||
|
||
### Всегда показывается контроль
|
||
|
||
**Причины:**
|
||
- Rollout = 0% (увеличьте в Unleash)
|
||
- Неправильный stickiness (используйте sessionId)
|
||
- Constraints блокируют пользователя
|
||
|
||
### Ошибка в консоли
|
||
|
||
```bash
|
||
Cannot find module '@/lib/funnel/unleash'
|
||
```
|
||
|
||
**Решение:** Проект не собран. Выполните `npm run dev`
|
||
|
||
## 📊 Analytics Integration
|
||
|
||
Unleash автоматически отправляет impression events:
|
||
|
||
```typescript
|
||
window.gtag?.("event", "experiment_impression", {
|
||
app_name: "witlab-funnel",
|
||
feature: "trial-button-test",
|
||
treatment: "v1"
|
||
});
|
||
```
|
||
|
||
Интегрируется с:
|
||
- ✅ Google Analytics
|
||
- ✅ Google Tag Manager
|
||
- ✅ Yandex Metrika (через funnel meta)
|
||
|
||
## 🚀 Deployment
|
||
|
||
### Перед выкаткой
|
||
|
||
```bash
|
||
# 1. Проверьте сборку
|
||
npm run build
|
||
|
||
# 2. Проверьте все флаги в Unleash
|
||
# 3. Убедитесь что rollout = 0% для новых тестов
|
||
# 4. Deploy
|
||
```
|
||
|
||
### После выкатки
|
||
|
||
```bash
|
||
# 1. Проверьте метрики через 1 час
|
||
# 2. Постепенно увеличивайте rollout
|
||
# 3. Анализируйте результаты через 1-2 недели
|
||
# 4. Выберите winner и удалите проигравшие варианты
|
||
```
|
||
|
||
## 📞 Support
|
||
|
||
**Вопросы?** Проверьте:
|
||
1. Эту документацию
|
||
2. Примеры в `/public/funnels/`
|
||
3. Код в `/src/lib/funnel/unleash/`
|
||
|
||
**Нашли баг?** Создайте issue с:
|
||
- Название флага
|
||
- JSON конфигурация
|
||
- Ожидаемое vs фактическое поведение
|