Optimizely Connector
Verbinde Optimizely Feature Experimentation über Tajo mit Brevo, um Experimentergebnisse zu synchronisieren, Kampagnen nach Feature-Flag-Segmenten auszurichten und Marketing-Automationen mit A/B-Test-Daten und Audience-Insights anzureichern.
Überblick
| Eigenschaft | Wert |
|---|---|
| Plattform | Optimizely |
| Kategorie | Experimentation (Custom) |
| Einrichtungsaufwand | Mittel |
| Offizielle Integration | Nein |
| Synchronisierte Daten | Experimente, Audiences, Events, Feature Flags |
| Authentifizierung | Personal Access Token / OAuth 2.0 |
Funktionen
- Experiment-Synchronisation - Übertrage A/B-Test-Variationszuweisungen an Brevo-Kontaktattribute
- Audience-Targeting - Nutze Optimizely-Audiences für die Brevo-Kampagnensegmentierung
- Conversion-Tracking - Tracke Optimizely-Events und mappe sie auf das Brevo-Event-Tracking
- Feature-Flag-Synchronisation - Segmentiere Kontakte nach aktivierten Feature Flags
- Ergebnis-Reporting - Synchronisiere Experimentergebnisse für nachgelagerte Analyse-Marketing-Kampagnen
- Multi-Projekt-Support - Verbinde mehrere Optimizely-Projekte mit einer einzigen Tajo-Instanz
Voraussetzungen
Bevor du beginnst, stelle sicher, dass du Folgendes hast:
- Ein Optimizely-Feature-Experimentation-Konto
- Einen Personal Access Token aus den Optimizely App Settings
- Einen SDK-Schlüssel für deine Optimizely-Umgebung
- Ein Brevo-Konto mit API-Zugriff
- Ein Tajo-Konto mit Connector-Berechtigungen
Authentifizierung
Personal Access Token
# Generate at 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// All REST API requests use Bearer token authconst headers = { 'Authorization': `Bearer ${process.env.OPTIMIZELY_ACCESS_TOKEN}`, 'Content-Type': 'application/json'};SDK-Authentifizierung
// For feature flag evaluation, use the SDKconst optimizelySDK = require('@optimizely/optimizely-sdk');
const optimizelyClient = optimizelySDK.createInstance({ sdkKey: process.env.OPTIMIZELY_SDK_KEY, datafileOptions: { autoUpdate: true, updateInterval: 60000 // 1 minute }});
await optimizelyClient.onReady();Konfiguration
Grundeinrichtung
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 * * *" # Every 2 hours
mapping: experiment_variation: EXPERIMENT_VARIATION feature_flags: ENABLED_FEATURES audience_segments: OPT_SEGMENTSFeld-Mapping
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_DATEAPI-Endpoints
| Endpoint | Methode | Beschreibung |
|---|---|---|
https://api.optimizely.com/v2/projects | GET | Projekte auflisten |
https://api.optimizely.com/v2/experiments | GET | Experimente auflisten |
https://api.optimizely.com/v2/experiments/{id} | GET | Experimentdetails abrufen |
https://api.optimizely.com/v2/experiments/{id}/results | GET | Experimentergebnisse abrufen |
https://api.optimizely.com/v2/features | GET | Feature Flags auflisten |
https://api.optimizely.com/v2/features/{id} | GET | Feature Flag abrufen |
https://api.optimizely.com/v2/audiences | GET | Audiences auflisten |
https://api.optimizely.com/v2/events | GET | Getrackte Events auflisten |
https://logx.optimizely.com/v1/events | POST | Events tracken (SDK-Endpoint) |
Code-Beispiele
Connector initialisieren
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'});Experiment-Entscheidungen mit Brevo synchronisieren
// Track experiment decisions and sync to Brevoconst optimizelyClient = optimizelySDK.createInstance({ sdkKey: process.env.OPTIMIZELY_SDK_KEY});
await optimizelyClient.onReady();
// Register a decision notification listeneroptimizelyClient.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() } }); } } });Experimentergebnisse synchronisieren
// Fetch experiment results and sync winning segmentsconst resultsResponse = await fetch( `https://api.optimizely.com/v2/experiments/${experimentId}/results`, { headers: { 'Authorization': `Bearer ${process.env.OPTIMIZELY_ACCESS_TOKEN}` } });
const results = await resultsResponse.json();
// Process variations and update contact segmentsfor (const variation of results.metrics) { const isWinner = variation.is_improvement && variation.statistical_significance >= 0.95;
if (isWinner) { // Create a Brevo segment for users in the winning variation console.log(`Winning variation: ${variation.variation_name}`); }}Feature-Flag-basierte Segmentierung
// Evaluate feature flags for user segmentationasync 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() } });}Rate Limits
| Endpoint | Limit | Hinweise |
|---|---|---|
| REST API | 50 Anfr./Min | Pro Personal Access Token |
| Results API | 10 Anfr./Min | Höhere Latenz, aufwendigere Queries |
| SDK Event Dispatch | 10.000 Events/Batch | Über den SDK-Event-Prozessor |
| Datafile CDN | Unbegrenzt | Gecacht mit Auto-Updates |
Latenz der Results API
Die Experiment Results API verarbeitet große Datensätze und kann über 30 Sekunden für eine Antwort benötigen. Nutze asynchrones Polling oder Caching, um dein Programm nicht zu blockieren.
Fehlerbehebung
| Problem | Ursache | Lösung |
|---|---|---|
| 401 Unauthorized | Token abgelaufen/ungültig | Personal Access Token neu generieren |
| SDK nicht bereit | Datafile nicht geladen | Auf onReady()-Promise warten |
| Keine Decisions geloggt | Notification nicht registriert | Listener vor Decisions registrieren |
| Veraltete Feature Flags | Datafile-Cache | updateInterval für Auto-Refresh setzen |
| Fehlende Ergebnisse | Experiment nicht gestartet | Status des Experiments auf “running” prüfen |
Debug-Modus
connectors: optimizely: debug: true log_level: verbose log_decisions: true log_events: trueBest Practices
- SDK für Decisions nutzen - Nutze das SDK für Echtzeit-Flag-Evaluation, die REST-API fürs Management
- Event-Batching implementieren - Bündle SDK-Events, um Netzwerk-Overhead zu reduzieren
- Datafile cachen - Aktiviere Auto-Update mit passenden Intervallen
- Gewinner-Variationen synchronisieren - Aktualisiere Kontaktsegmente nach Experiment-Abschluss
- Attribute fürs Targeting nutzen - Übergib E-Mail und User-Attribute für das Audience-Matching
- Experimentstatus überwachen - Synchronisiere nur Daten aus laufenden oder abgeschlossenen Experimenten
Sicherheit
- Personal Access Tokens - Bearer-Token-Authentifizierung für die REST-API
- SDK-Schlüssel-Isolation - Separate SDK-Schlüssel pro Umgebung (Dev, Staging, Prod)
- Serverseitige Evaluation - Evaluiere Feature Flags serverseitig, um Offenlegung zu vermeiden
- Token-Rotation - Rotiere Personal Access Tokens regelmäßig
- Minimale Berechtigungen - Nutze Read-only-Tokens, wenn kein Schreibzugriff nötig ist
- Verschlüsselter Transport - TLS 1.2+ für alle API- und SDK-Kommunikationen