Коннектор Optimizely
Подключите Optimizely Feature Experimentation к Brevo через Tajo для синхронизации результатов экспериментов, таргетирования кампаний по сегментам флагов функций и обогащения маркетинговой автоматизации данными A/B-тестов и инсайтами об аудитории.
Обзор
| Свойство | Значение |
|---|---|
| Платформа | Optimizely |
| Категория | Experimentation (Custom) |
| Сложность настройки | Средняя |
| Официальная интеграция | Нет |
| Синхронизируемые данные | Эксперименты, аудитории, события, флаги функций |
| Метод аутентификации | Personal Access Token / OAuth 2.0 |
Возможности
- Синхронизация экспериментов, передача назначений вариантов A/B-тестов в атрибуты контактов Brevo
- Таргетирование по аудитории, использование аудиторий Optimizely для сегментации кампаний Brevo
- Отслеживание конверсий, трекинг событий Optimizely и сопоставление с отслеживанием событий Brevo
- Синхронизация флагов функций, сегментация контактов по включённым флагам функций
- Отчётность о результатах, синхронизация результатов экспериментов для постаналитических маркетинговых кампаний
- Поддержка нескольких проектов, подключение нескольких проектов Optimizely к одному экземпляру Tajo
Предварительные требования
Прежде чем начать, убедитесь, что у вас есть:
- Аккаунт Optimizely Feature Experimentation
- Personal Access Token из настроек приложения Optimizely
- SDK-ключ для вашего окружения Optimizely
- Аккаунт Brevo с доступом к API
- Аккаунт Tajo с правами на управление коннекторами
Аутентификация
Personal Access Token
# Сгенерируйте на https://app.optimizely.com/v2/accountsettings/tokensexport OPTIMIZELY_ACCESS_TOKEN=your_personal_access_tokenexport OPTIMIZELY_SDK_KEY=your_sdk_keyexport TAJO_API_KEY=your_tajo_api_keyexport BREVO_API_KEY=your_brevo_api_key// Все запросы к REST API используют Bearer-аутентификациюconst headers = { 'Authorization': `Bearer ${process.env.OPTIMIZELY_ACCESS_TOKEN}`, 'Content-Type': 'application/json'};SDK-аутентификация
// Для оценки флагов функций используйте SDKconst optimizelySDK = require('@optimizely/optimizely-sdk');
const optimizelyClient = optimizelySDK.createInstance({ sdkKey: process.env.OPTIMIZELY_SDK_KEY, datafileOptions: { autoUpdate: true, updateInterval: 60000 // 1 минута }});
await optimizelyClient.onReady();Конфигурация
Базовая настройка
connectors: optimizely: enabled: true access_token: "${OPTIMIZELY_ACCESS_TOKEN}" sdk_key: "${OPTIMIZELY_SDK_KEY}" project_id: "12345678"
sync: experiments: true audiences: true events: true feature_flags: true schedule: "0 */2 * * *" # Каждые 2 часа
mapping: experiment_variation: EXPERIMENT_VARIATION feature_flags: ENABLED_FEATURES audience_segments: OPT_SEGMENTSСопоставление полей
field_mapping: user_id: email experiment_key: EXPERIMENT_NAME variation_key: VARIATION_NAME feature_key: FEATURE_FLAG enabled: FEATURE_ENABLED audience_name: AUDIENCE_SEGMENT decision_timestamp: EXPERIMENT_DATEЭндпоинты API
| Эндпоинт | Метод | Описание |
|---|---|---|
https://api.optimizely.com/v2/projects | GET | Список проектов |
https://api.optimizely.com/v2/experiments | GET | Список экспериментов |
https://api.optimizely.com/v2/experiments/{id} | GET | Детали эксперимента |
https://api.optimizely.com/v2/experiments/{id}/results | GET | Результаты эксперимента |
https://api.optimizely.com/v2/features | GET | Список флагов функций |
https://api.optimizely.com/v2/features/{id} | GET | Флаг функции |
https://api.optimizely.com/v2/audiences | GET | Список аудиторий |
https://api.optimizely.com/v2/events | GET | Список отслеживаемых событий |
https://logx.optimizely.com/v1/events | POST | Трекинг событий (SDK-эндпоинт) |
Примеры кода
Инициализация коннектора
import { TajoClient } from '@tajo/sdk';
const tajo = new TajoClient({ apiKey: process.env.TAJO_API_KEY, brevoApiKey: process.env.BREVO_API_KEY});
await tajo.connectors.connect('optimizely', { accessToken: process.env.OPTIMIZELY_ACCESS_TOKEN, sdkKey: process.env.OPTIMIZELY_SDK_KEY, projectId: '12345678'});Синхронизация решений эксперимента с Brevo
// Отслеживание решений эксперимента и синхронизация с Brevoconst optimizelyClient = optimizelySDK.createInstance({ sdkKey: process.env.OPTIMIZELY_SDK_KEY});
await optimizelyClient.onReady();
// Регистрация слушателя уведомлений о решенияхoptimizelyClient.notificationCenter.addNotificationListener( optimizelySDK.enums.NOTIFICATION_TYPES.DECISION, async (decisionObject) => { const { type, userId, attributes, decisionInfo } = decisionObject;
if (type === 'feature' || type === 'ab-test') { const email = attributes.email; if (email) { await tajo.contacts.update(email, { attributes: { EXPERIMENT_NAME: decisionInfo.experimentKey || decisionInfo.featureKey, VARIATION_NAME: decisionInfo.variationKey, FEATURE_ENABLED: decisionInfo.featureEnabled || false, EXPERIMENT_DATE: new Date().toISOString() } }); } } });Синхронизация результатов эксперимента
// Получение результатов эксперимента и синхронизация победивших сегментовconst resultsResponse = await fetch( `https://api.optimizely.com/v2/experiments/${experimentId}/results`, { headers: { 'Authorization': `Bearer ${process.env.OPTIMIZELY_ACCESS_TOKEN}` } });
const results = await resultsResponse.json();
// Обработка вариантов и обновление сегментов контактовfor (const variation of results.metrics) { const isWinner = variation.is_improvement && variation.statistical_significance >= 0.95;
if (isWinner) { // Создание сегмента Brevo для пользователей победившего варианта console.log(`Winning variation: ${variation.variation_name}`); }}Сегментация на основе флагов функций
// Оценка флагов функций для сегментации пользователейasync function syncFeatureFlags(userEmail, userId) { const features = ['new_checkout', 'loyalty_program', 'ai_recommendations']; const enabledFeatures = [];
for (const feature of features) { const user = optimizelyClient.createUserContext(userId, { email: userEmail }); const decision = user.decide(feature);
if (decision.enabled) { enabledFeatures.push(feature); } }
await tajo.contacts.update(userEmail, { attributes: { ENABLED_FEATURES: enabledFeatures.join(', '), FEATURE_FLAGS_SYNCED: new Date().toISOString() } });}Ограничения скорости
| Эндпоинт | Лимит | Примечания |
|---|---|---|
| REST API | 50 запросов/мин | На Personal Access Token |
| Results API | 10 запросов/мин | Высокая задержка, тяжёлые запросы |
| Отправка событий через SDK | 10 000 событий/пакет | Через обработчик событий SDK |
| Datafile CDN | Без ограничений | Кешируется с автообновлением |
Задержка Results API
Experiment Results API обрабатывает большие наборы данных и может отвечать более 30 секунд. Используйте асинхронный опрос или кеширование, чтобы не блокировать приложение.
Устранение неполадок
| Проблема | Причина | Решение |
|---|---|---|
| 401 Unauthorized | Токен истёк или недействителен | Перегенерируйте Personal Access Token |
| SDK не готов | Datafile не загружен | Дождитесь разрешения промиса onReady() |
| Решения не логируются | Слушатель не зарегистрирован | Зарегистрируйте слушатель до принятия решений |
| Устаревшие флаги функций | Кеш datafile | Задайте updateInterval для авто-обновления |
| Отсутствующие результаты | Эксперимент не запущен | Убедитесь, что статус эксперимента “running” |
Режим отладки
connectors: optimizely: debug: true log_level: verbose log_decisions: true log_events: trueЛучшие практики
- Используйте SDK для принятия решений, SDK для оценки флагов в реальном времени, REST API для управления
- Реализуйте пакетную обработку событий, группируйте события SDK для снижения сетевой нагрузки
- Кешируйте datafile, включите авто-обновление с подходящими интервалами
- Синхронизируйте победившие варианты, после завершения экспериментов обновляйте сегменты контактов
- Используйте атрибуты для таргетинга, передавайте email и атрибуты пользователя для сопоставления с аудиторией
- Контролируйте статус экспериментов, синхронизируйте данные только из активных или завершённых экспериментов
Безопасность
- Personal Access Tokens, Bearer-аутентификация для REST API
- Изоляция SDK-ключей, отдельные SDK-ключи для каждого окружения (dev, staging, prod)
- Оценка на стороне сервера, оценивайте флаги функций на сервере для предотвращения утечки данных
- Ротация токенов, регулярно ротируйте Personal Access Tokens
- Минимальные права, используйте токены только для чтения, когда запись не требуется
- Зашифрованная передача, TLS 1.2+ для всех API и SDK-коммуникаций