Optimizely Connector
Forbind Optimizely Feature Experimentation med Brevo via Tajo for at synkronisere eksperimentresultater, målrette kampagner efter feature flag-segmenter og berige marketingautomatiseringer med A/B-testdata og målgruppeindsigter.
Oversigt
| Egenskab | Værdi |
|---|---|
| Platform | Optimizely |
| Kategori | Eksperimentering (brugerdefineret) |
| Opsætningskompleksitet | Mellem |
| Officiel integration | Nej |
| Synkroniserede data | Eksperimenter, målgrupper, hændelser, feature flags |
| Autentifikationsmetode | Personal Access Token / OAuth 2.0 |
Funktioner
- Eksperimentsynkronisering - Push A/B-testvariationstildelinger til Brevo-kontaktattributter
- Målgruppemålretning - Brug Optimizely-målgrupper til segmentering af Brevo-kampagner
- Konverteringsssporing - Spor Optimizely-hændelser, og kortlæg dem til Brevo-hændelsessporing
- Feature flag-synkronisering - Segmentér kontakter efter aktiverede feature flags
- Resultatrapportering - Synkronisér eksperimentresultater til marketingkampagner efter analyse
- Multi-projekt-understøttelse - Forbind flere Optimizely-projekter til én Tajo-instans
Forudsætninger
Før du begynder, skal du sikre dig, at du har:
- En Optimizely Feature Experimentation-konto
- Et Personal Access Token fra Optimizely App Settings
- En SDK-nøgle til dit Optimizely-miljø
- En Brevo-konto med API-adgang
- En Tajo-konto med connector-tilladelser
Autentifikation
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-autentifikation
// 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
Grundlæggende opsætning
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_SEGMENTSFeltmapping
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 | Metode | Beskrivelse |
|---|---|---|
https://api.optimizely.com/v2/projects | GET | Vis projekter |
https://api.optimizely.com/v2/experiments | GET | Vis eksperimenter |
https://api.optimizely.com/v2/experiments/{id} | GET | Hent eksperimentdetaljer |
https://api.optimizely.com/v2/experiments/{id}/results | GET | Hent eksperimentresultater |
https://api.optimizely.com/v2/features | GET | Vis feature flags |
https://api.optimizely.com/v2/features/{id} | GET | Hent feature flag |
https://api.optimizely.com/v2/audiences | GET | Vis målgrupper |
https://api.optimizely.com/v2/events | GET | Vis sporede hændelser |
https://logx.optimizely.com/v1/events | POST | Spor hændelser (SDK-endpoint) |
Kodeeksempler
Initialisér connector
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'});Synkronisér eksperimentbeslutninger til Brevo
// 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() } }); } } });Synkronisér eksperimentresultater
// 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-baseret segmentering
// 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 | Grænse | Noter |
|---|---|---|
| REST API | 50 req/min. | Pr. personal access token |
| Results API | 10 req/min. | Højere latens, tungere forespørgsler |
| SDK Event Dispatch | 10.000 hændelser/batch | Via SDK event processor |
| Datafile CDN | Ubegrænset | Cachet med auto-opdateringer |
Latens for Results API
Experiment Results API behandler store datasæt og kan tage 30+ sekunder at svare. Brug asynkron polling eller caching for at undgå at blokere din applikation.
Fejlfinding
| Problem | Årsag | Løsning |
|---|---|---|
| 401 Unauthorized | Token udløbet/ugyldigt | Regenerér Personal Access Token |
| SDK ikke klar | Datafile ikke indlæst | Vent på, at onReady()-promise bliver resolved |
| Ingen beslutninger logget | Notifikation ikke registreret | Registrér listener, før du træffer beslutninger |
| Forældede feature flags | Datafile-cache | Indstil updateInterval for auto-opdatering |
| Manglende resultater | Eksperiment ikke startet | Verificér, at eksperimentstatus er “running” |
Debug-tilstand
connectors: optimizely: debug: true log_level: verbose log_decisions: true log_events: trueBedste praksis
- Brug SDK’et til beslutninger - Brug SDK’et til realtidsflagevaluering, REST API til administration
- Implementér event-batching - Batch SDK-hændelser for at reducere netværksoverhead
- Cache datafilen - Aktivér auto-opdatering med passende intervaller
- Synkronisér vindende variationer - Når eksperimenter slutter, opdatér kontaktsegmenter
- Brug attributter til målretning - Pass e-mail og brugerattributter til målgruppematch
- Overvåg eksperimentstatus - Synkronisér kun data fra kørende eller afsluttede eksperimenter
Sikkerhed
- Personal Access Tokens - Bearer-token-autentifikation til REST API
- SDK-nøgleisolation - Separate SDK-nøgler pr. miljø (dev, staging, prod)
- Server-side-evaluering - Evaluér feature flags server-side for at undgå eksponering
- Tokenrotation - Rotér Personal Access Tokens regelmæssigt
- Minimale tilladelser - Brug read-only-tokens, når skriveadgang ikke er nødvendig
- Krypteret transport - TLS 1.2+ til al API- og SDK-kommunikation