Connettore Optimizely
Collega Optimizely Feature Experimentation a Brevo tramite Tajo per sincronizzare i risultati degli esperimenti, targettizzare le campagne per segmenti di feature flag e arricchire le automazioni marketing con dati di A/B test e insight di audience.
Panoramica
| Proprietà | Valore |
|---|---|
| Piattaforma | Optimizely |
| Categoria | Experimentation (Custom) |
| Complessità di setup | Media |
| Integrazione ufficiale | No |
| Dati sincronizzati | Esperimenti, Audience, Eventi, Feature Flag |
| Metodo di autenticazione | Personal Access Token / OAuth 2.0 |
Funzionalità
- Sync esperimenti - Invia le assegnazioni di variante dei test A/B agli attributi dei contatti Brevo
- Targeting audience - Usa le audience Optimizely per la segmentazione delle campagne Brevo
- Tracciamento conversioni - Traccia gli eventi Optimizely e mappali al tracking eventi Brevo
- Sync feature flag - Segmenta i contatti per feature flag abilitati
- Reporting risultati - Sincronizza i risultati degli esperimenti per campagne marketing di post-analisi
- Supporto multi-progetto - Collega più progetti Optimizely a una singola istanza Tajo
Prerequisiti
Prima di iniziare, assicurati di avere:
- Un account Optimizely Feature Experimentation
- Un Personal Access Token da Optimizely App Settings
- Una SDK key per il tuo ambiente Optimizely
- Un account Brevo con accesso API
- Un account Tajo con permessi sui connettori
Autenticazione
Personal Access Token
# Genera su 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// Tutte le richieste REST API usano autenticazione Bearer tokenconst headers = { 'Authorization': `Bearer ${process.env.OPTIMIZELY_ACCESS_TOKEN}`, 'Content-Type': 'application/json'};Autenticazione SDK
// Per la valutazione dei feature flag, usa l'SDKconst optimizelySDK = require('@optimizely/optimizely-sdk');
const optimizelyClient = optimizelySDK.createInstance({ sdkKey: process.env.OPTIMIZELY_SDK_KEY, datafileOptions: { autoUpdate: true, updateInterval: 60000 // 1 minuto }});
await optimizelyClient.onReady();Configurazione
Setup di base
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 * * *" # Ogni 2 ore
mapping: experiment_variation: EXPERIMENT_VARIATION feature_flags: ENABLED_FEATURES audience_segments: OPT_SEGMENTSMapping dei campi
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_DATEEndpoint API
| Endpoint | Metodo | Descrizione |
|---|---|---|
https://api.optimizely.com/v2/projects | GET | Elenca i progetti |
https://api.optimizely.com/v2/experiments | GET | Elenca gli esperimenti |
https://api.optimizely.com/v2/experiments/{id} | GET | Ottieni dettagli esperimento |
https://api.optimizely.com/v2/experiments/{id}/results | GET | Ottieni risultati esperimento |
https://api.optimizely.com/v2/features | GET | Elenca i feature flag |
https://api.optimizely.com/v2/features/{id} | GET | Ottieni un feature flag |
https://api.optimizely.com/v2/audiences | GET | Elenca le audience |
https://api.optimizely.com/v2/events | GET | Elenca gli eventi tracciati |
https://logx.optimizely.com/v1/events | POST | Traccia eventi (endpoint SDK) |
Esempi di codice
Inizializzare il connettore
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'});Sincronizzare le decisioni degli esperimenti su Brevo
// Traccia le decisioni degli esperimenti e sincronizzale su Brevoconst optimizelyClient = optimizelySDK.createInstance({ sdkKey: process.env.OPTIMIZELY_SDK_KEY});
await optimizelyClient.onReady();
// Registra un notification listener per le decisionioptimizelyClient.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() } }); } } });Sincronizzare i risultati degli esperimenti
// Recupera i risultati degli esperimenti e sincronizza i segmenti vincenticonst resultsResponse = await fetch( `https://api.optimizely.com/v2/experiments/${experimentId}/results`, { headers: { 'Authorization': `Bearer ${process.env.OPTIMIZELY_ACCESS_TOKEN}` } });
const results = await resultsResponse.json();
// Elabora le varianti e aggiorna i segmenti contattofor (const variation of results.metrics) { const isWinner = variation.is_improvement && variation.statistical_significance >= 0.95;
if (isWinner) { // Crea un segmento Brevo per gli utenti nella variante vincente console.log(`Variante vincente: ${variation.variation_name}`); }}Segmentazione basata su feature flag
// Valuta i feature flag per la segmentazione utentiasync 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() } });}Limiti di rate
| Endpoint | Limite | Note |
|---|---|---|
| REST API | 50 req/min | Per personal access token |
| Results API | 10 req/min | Latenza più alta, query più pesanti |
| SDK Event Dispatch | 10.000 eventi/batch | Tramite event processor SDK |
| Datafile CDN | Illimitato | Cachato con auto-aggiornamenti |
Latenza Results API
L’Experiment Results API elabora grandi dataset e può impiegare 30+ secondi per rispondere. Usa polling asincrono o caching per evitare di bloccare la tua applicazione.
Risoluzione dei problemi
| Problema | Causa | Soluzione |
|---|---|---|
| 401 Unauthorized | Token scaduto/non valido | Rigenera il Personal Access Token |
| SDK non pronto | Datafile non caricato | Attendi la risoluzione della promise onReady() |
| Nessuna decisione loggata | Notification non registrata | Registra il listener prima di prendere decisioni |
| Feature flag stantii | Cache del datafile | Imposta updateInterval per l’auto-refresh |
| Risultati mancanti | Esperimento non avviato | Verifica che lo stato dell’esperimento sia “running” |
Modalità debug
connectors: optimizely: debug: true log_level: verbose log_decisions: true log_events: trueBest practice
- Usa l’SDK per le decisioni - Usa l’SDK per la valutazione flag in real-time, la REST API per la gestione
- Implementa batching degli eventi - Raggruppa gli eventi SDK per ridurre l’overhead di rete
- Metti in cache il datafile - Abilita l’auto-update con intervalli appropriati
- Sincronizza le varianti vincenti - Dopo la conclusione degli esperimenti, aggiorna i segmenti contatti
- Usa gli attributi per il targeting - Passa email e attributi utente per il matching delle audience
- Monitora lo stato degli esperimenti - Sincronizza solo i dati di esperimenti in corso o conclusi
Sicurezza
- Personal Access Token - Autenticazione Bearer token per la REST API
- Isolamento SDK key - SDK key separate per ambiente (dev, staging, prod)
- Valutazione server-side - Valuta i feature flag lato server per evitare esposizioni
- Rotazione token - Ruota periodicamente i Personal Access Token
- Permessi minimi - Usa token read-only quando l’accesso in scrittura non è necessario
- Trasporto cifrato - TLS 1.2+ per tutte le comunicazioni API e SDK