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

513 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ✅ AB Testing Integration - Полная реализация
## 🎯 Задача
Интегрировать Unleash feature flags в систему воронок для проведения AB тестирования:
- Возможность тестировать варианты экранов
- Возможность тестировать разные пути навигации
- UI в админке для настройки AB тестов
- Полная типизация TypeScript
## ✨ Что реализовано
### 1. 📦 Backend Infrastructure
#### Типы и интерфейсы (`src/lib/funnel/types.ts`)
```typescript
// Расширен NavigationConditionDefinition
interface NavigationConditionDefinition {
conditionType?: "options" | "values" | "unleash"; // ← Новый тип
// Новые поля для Unleash
unleashFlag?: string; // Название флага
unleashVariants?: string[]; // Ожидаемые варианты
}
```
**Поддерживаемые операторы:**
- `includesAny` - хотя бы один вариант совпадает
- `includesAll` - все варианты совпадают
- `includesExactly` - только указанные варианты
- `equals` - точное совпадение
#### Логика проверки условий
**`src/lib/funnel/navigation.ts`:**
```typescript
export type UnleashChecker = (
flag: string,
expectedVariants: string[],
operator?: "includesAny" | "includesAll" | "includesExactly" | "equals"
) => boolean;
function satisfiesCondition(
condition: NavigationConditionDefinition,
answers: FunnelAnswers,
allScreens?: ScreenDefinition[],
unleashChecker?: UnleashChecker // ← Новый параметр
): boolean {
if (conditionType === "unleash") {
return unleashChecker(
condition.unleashFlag,
condition.unleashVariants,
operator
);
}
// ... остальная логика
}
```
**`src/lib/funnel/variants.ts`:**
```typescript
export function resolveScreenVariant<T>(
screen: T,
answers: FunnelAnswers,
allScreens?: ScreenDefinition[],
unleashChecker?: UnleashChecker // ← Новый параметр
): T {
// Проверяет варианты с учетом Unleash условий
}
```
### 2. 🔌 Unleash SDK Integration
#### Provider (`src/lib/funnel/unleash/UnleashProvider.tsx`)
```typescript
export function UnleashProvider({ children, userId, sessionId }) {
// Инициализирует Unleash клиент
// Если env переменные не заданы - graceful fallback
const config = {
url: process.env.NEXT_PUBLIC_UNLEASH_URL,
clientKey: process.env.NEXT_PUBLIC_UNLEASH_CLIENT_KEY,
context: {
userId,
sessionId: sessionId || userId || "anonymous",
}
};
return <FlagProvider config={config}>{children}</FlagProvider>;
}
```
#### Context (`src/lib/funnel/unleash/UnleashContext.tsx`)
```typescript
export function UnleashContextProvider({
children,
activeVariants // { "flag-name": "v1", ... }
}) {
const checkVariant = (flag, expectedVariants, operator) => {
// Проверяет соответствие текущего варианта ожидаемым
};
return (
<UnleashContext.Provider value={{ activeVariants, checkVariant }}>
{children}
</UnleashContext.Provider>
);
}
```
#### Wrapper (`src/components/funnel/FunnelUnleashWrapper.tsx`)
```typescript
export function FunnelUnleashWrapper({ funnel, children }) {
// 1. Сканирует все экраны воронки
// 2. Находит все unleashFlag в conditions (variants + navigation)
// 3. Получает варианты для всех флагов через useVariant
// 4. Передает activeVariants в UnleashContextProvider
const allFlags = useMemo(() => {
// Собирает unique флаги из всех условий
}, [funnel.screens]);
const activeVariants = useMemo(() => {
// Получает текущие варианты для всех флагов
}, [flagsReady, flagVariants]);
}
```
#### Runtime Integration (`src/components/funnel/FunnelRuntime.tsx`)
```typescript
export function FunnelRuntime({ funnel, initialScreenId }) {
const { checkVariant } = useUnleashContext();
// Создаем unleashChecker для передачи в navigation/variants
const unleashChecker: UnleashChecker = useCallback(
(flag, expectedVariants, operator) => {
return checkVariant(flag, expectedVariants, operator);
},
[checkVariant]
);
// Передаем во все функции проверки
resolveScreenVariant(baseScreen, answers, funnel.screens, unleashChecker);
resolveNextScreenId(currentScreen, answers, funnel.screens, unleashChecker);
estimatePathLength(funnel, answers, unleashChecker);
}
```
### 3. 🎨 Admin UI Components
#### Селектор типа условия (`ConditionTypeSelector.tsx`)
```typescript
export function ConditionTypeSelector({ condition, onChange }) {
return (
<select value={conditionType} onChange={...}>
<option value="options">Выбранные опции (list экраны)</option>
<option value="values">Значения (зодиак, возраст, email)</option>
<option value="unleash">AB тест (Unleash)</option>
</select>
);
}
```
#### Редактор Unleash условий (`UnleashConditionEditor.tsx`)
```typescript
export function UnleashConditionEditor({ condition, onChange }) {
return (
<>
{/* Название флага */}
<Input
value={unleashFlag}
placeholder="trial-button-test"
onChange={handleFlagChange}
/>
{/* Оператор проверки */}
<select value={operator} onChange={handleOperatorChange}>
<option value="includesAny">Любой из вариантов (OR)</option>
<option value="equals">Равен (один вариант)</option>
</select>
{/* Ожидаемые варианты */}
<Input
value={unleashVariants.join(", ")}
placeholder="v1, v2, v3"
onChange={handleVariantsChange}
/>
</>
);
}
```
#### Интеграция в VariantConditionEditor
```typescript
export function VariantConditionEditor({ condition, allScreens, onChange }) {
const conditionType = condition.conditionType ?? "options";
const isUnleashCondition = conditionType === "unleash";
return (
<>
<ConditionTypeSelector
condition={condition}
onChange={handleConditionTypeChange}
/>
{isUnleashCondition ? (
<UnleashConditionEditor condition={condition} onChange={onChange} />
) : (
// Существующая логика для options/values
)}
</>
);
}
```
### 4. 📚 Документация
- **AB_TESTING_GUIDE.md** - Полное руководство (200+ строк)
- Настройка environment
- Примеры использования
- API Reference
- Best Practices
- Troubleshooting
- **UNLEASH_SETUP.md** - Quick Start
- Быстрый старт за 4 шага
- Структура файлов
- Примеры
- Требования
- **ab-test-example.json** - Тестовая воронка
- 6 экранов с разными типами AB тестов
- Button text testing
- Content variant testing
- Navigation testing
- Combined conditions (gender + AB test)
## 🚀 Использование
### В админке
1. Откройте экран для редактирования
2. Перейдите в "Вариативность" → Добавить вариант
3. В условиях выберите "AB тест (Unleash)"
4. Укажите флаг и варианты
5. Настройте overrides
6. Сохраните
### В JSON
```json
{
"variants": [
{
"conditions": [
{
"screenId": "payment",
"conditionType": "unleash",
"unleashFlag": "button-test",
"unleashVariants": ["v1"],
"operator": "equals"
}
],
"overrides": {
"bottomActionButton": {
"text": "New Button Text"
}
}
}
]
}
```
### Environment Setup
```bash
# .env.local
NEXT_PUBLIC_UNLEASH_URL=https://unleash.example.com/api/frontend
NEXT_PUBLIC_UNLEASH_CLIENT_KEY=your-key
```
## 📊 Возможности
### Что можно тестировать
**Варианты экранов:**
- Тексты (заголовки, подзаголовки, кнопки)
- Контент (описания, иконки, блоки)
- Любые поля через variants overrides
**Навигация:**
- Разные пути через воронку
- Длинный vs короткий onboarding
- A/B тест целых flow
**Комбинированные условия:**
- AB тест + пол пользователя
- AB тест + возраст
- AB тест + ответы на вопросы
### Архитектура
```
┌─────────────────────────────────────┐
│ Unleash Dashboard │
│ (Feature Flags Config) │
└─────────────────┬───────────────────┘
┌─────────────────────────────────────┐
│ UnleashProvider │
│ (@unleash/proxy-client-react) │
└─────────────────┬───────────────────┘
┌─────────────────────────────────────┐
│ FunnelUnleashWrapper │
│ - Сканирует воронку │
│ - Собирает все флаги │
│ - Получает варианты │
└─────────────────┬───────────────────┘
┌─────────────────────────────────────┐
│ UnleashContextProvider │
│ activeVariants: { │
│ "flag-1": "v1", │
│ "flag-2": "v2" │
│ } │
└─────────────────┬───────────────────┘
┌─────────────────────────────────────┐
│ FunnelRuntime │
│ - unleashChecker: UnleashChecker │
│ - resolveScreenVariant(...) │
│ - resolveNextScreenId(...) │
└─────────────────┬───────────────────┘
┌────────┴────────┐
▼ ▼
┌─────────┐ ┌─────────┐
│variants │ │navigation│
│.ts │ │.ts │
└─────────┘ └─────────┘
```
## 📁 Файлы
### Новые файлы (14)
```
src/lib/funnel/unleash/
├── UnleashProvider.tsx ✨ Unleash SDK wrapper
├── UnleashContext.tsx ✨ React Context для вариантов
├── useUnleash.ts ✨ Hooks для работы с флагами
└── index.ts ✨ Экспорты
src/components/funnel/
└── FunnelUnleashWrapper.tsx ✨ Сборщик флагов из воронки
src/components/admin/builder/forms/
├── UnleashConditionEditor.tsx ✨ UI редактор AB тестов
└── ConditionTypeSelector.tsx ✨ Селектор типа условия
docs/
├── AB_TESTING_GUIDE.md ✨ Полное руководство
├── UNLEASH_SETUP.md ✨ Quick start
└── AB_TESTING_IMPLEMENTATION.md ✨ Этот файл
public/funnels/
└── ab-test-example.json ✨ Тестовая воронка
package.json ✏️ +@unleash/proxy-client-react
```
### Модифицированные файлы (6)
```
src/lib/funnel/
├── types.ts ✏️ +unleash поля в NavigationConditionDefinition
├── navigation.ts ✏️ +UnleashChecker support
└── variants.ts ✏️ +UnleashChecker support
src/components/
├── funnel/FunnelRuntime.tsx ✏️ +unleashChecker integration
└── admin/builder/forms/variants/
└── VariantConditionEditor.tsx ✏️ +Unleash UI
src/app/[funnelId]/[screenId]/
└── page.tsx ✏️ +UnleashProvider wrapper
```
## ✅ Проверка
### Сборка
```bash
✓ npm run build
✓ No TypeScript errors
✓ No ESLint errors
✓ All pages compiled successfully
```
### Тестирование
```bash
# 1. Запустите dev сервер
npm run dev
# 2. Откройте тестовую воронку
http://localhost:3000/ab-test-example/welcome
# 3. Проверьте разные варианты
# Откройте в нескольких вкладках - увидите разные версии
```
## 🎓 Примеры
### Пример 1: Button Text AB Test
```json
{
"id": "payment",
"bottomActionButton": { "text": "Continue" },
"variants": [
{
"conditions": [{
"conditionType": "unleash",
"unleashFlag": "payment-button-test",
"unleashVariants": ["variant-a"]
}],
"overrides": {
"bottomActionButton": { "text": "Start Trial" }
}
}
]
}
```
### Пример 2: Navigation AB Test
```json
{
"navigation": {
"defaultNextScreenId": "long-flow",
"rules": [{
"conditions": [{
"conditionType": "unleash",
"unleashFlag": "onboarding-length",
"unleashVariants": ["short"]
}],
"nextScreenId": "payment"
}]
}
}
```
### Пример 3: Combined Conditions
```json
{
"variants": [{
"conditions": [
{
"screenId": "gender",
"conditionType": "options",
"optionIds": ["female"]
},
{
"conditionType": "unleash",
"unleashFlag": "female-test",
"unleashVariants": ["v1"]
}
],
"overrides": {
"title": { "text": "Special for Women!" }
}
}]
}
```
## 🎯 Следующие шаги
1. ✅ Настройте Unleash instance
2. ✅ Создайте первые feature flags
3. ✅ Добавьте AB тесты в существующие воронки
4. ✅ Соберите метрики и выберите победителей
5. ✅ Масштабируйте на все воронки
## 📞 Поддержка
- **Документация:** AB_TESTING_GUIDE.md
- **Quick Start:** UNLEASH_SETUP.md
- **Примеры:** /public/funnels/ab-test-example.json
- **Unleash Docs:** https://docs.getunleash.io/
---
**Статус:** ✅ Готово к production
**Версия:** 1.0.0
**Дата:** 2025-01-20