Konektor Optimizely
Hubungkan Optimizely Feature Experimentation ke Brevo melalui Tajo untuk menyinkronkan hasil eksperimen, menargetkan kampanye berdasarkan segmen feature flag, serta memperkaya otomatisasi pemasaran dengan data A/B test dan wawasan audiens.
Ikhtisar
| Properti | Nilai |
|---|---|
| Platform | Optimizely |
| Kategori | Eksperimen (Custom) |
| Kompleksitas penyiapan | Sedang |
| Integrasi resmi | Tidak |
| Data tersinkron | Eksperimen, audiens, event, feature flag |
| Metode autentikasi | Personal Access Token / OAuth 2.0 |
Fitur
- Sinkronisasi eksperimen - Kirim penetapan variasi A/B test ke atribut kontak Brevo
- Penargetan audiens - Gunakan audiens Optimizely untuk segmentasi kampanye Brevo
- Pelacakan konversi - Lacak event Optimizely dan petakan ke pelacakan event Brevo
- Sinkronisasi feature flag - Segmentasikan kontak berdasarkan feature flag yang aktif
- Pelaporan hasil - Sinkronkan hasil eksperimen untuk kampanye pemasaran pascaanalisis
- Dukungan multi-proyek - Hubungkan beberapa proyek Optimizely ke satu instance Tajo
Prasyarat
Sebelum memulai, pastikan Anda memiliki:
- Akun Optimizely Feature Experimentation
- Personal Access Token dari Optimizely App Settings
- SDK key untuk environment Optimizely Anda
- Akun Brevo dengan akses API
- Akun Tajo dengan izin konektor
Autentikasi
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'};Autentikasi SDK
// 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();Konfigurasi
Penyiapan dasar
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_SEGMENTSPemetaan field
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 | Metode | Deskripsi |
|---|---|---|
https://api.optimizely.com/v2/projects | GET | Menampilkan daftar proyek |
https://api.optimizely.com/v2/experiments | GET | Menampilkan daftar eksperimen |
https://api.optimizely.com/v2/experiments/{id} | GET | Mengambil detail eksperimen |
https://api.optimizely.com/v2/experiments/{id}/results | GET | Mengambil hasil eksperimen |
https://api.optimizely.com/v2/features | GET | Menampilkan daftar feature flag |
https://api.optimizely.com/v2/features/{id} | GET | Mengambil satu feature flag |
https://api.optimizely.com/v2/audiences | GET | Menampilkan daftar audiens |
https://api.optimizely.com/v2/events | GET | Menampilkan daftar event yang dilacak |
https://logx.optimizely.com/v1/events | POST | Melacak event (endpoint SDK) |
Contoh kode
Inisialisasi konektor
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'});Sinkronkan keputusan eksperimen ke 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() } }); } } });Sinkronkan hasil eksperimen
// 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}`); }}Segmentasi berbasis feature flag
// 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() } });}Batas rate
| Endpoint | Batas | Catatan |
|---|---|---|
| REST API | 50 req/menit | Per personal access token |
| Results API | 10 req/menit | Latensi lebih tinggi, kueri lebih berat |
| SDK Event Dispatch | 10.000 event/batch | Melalui event processor SDK |
| Datafile CDN | Tanpa batas | Di-cache dengan pembaruan otomatis |
Latensi Results API
Experiment Results API memproses dataset berukuran besar dan bisa memerlukan lebih dari 30 detik untuk merespons. Gunakan polling asinkron atau caching agar aplikasi Anda tidak terblokir.
Pemecahan masalah
| Masalah | Penyebab | Solusi |
|---|---|---|
| 401 Unauthorized | Token kedaluwarsa atau tidak valid | Buat ulang Personal Access Token |
| SDK tidak siap | Datafile belum dimuat | Tunggu hingga promise onReady() selesai |
| Tidak ada keputusan yang tercatat | Listener notifikasi belum didaftarkan | Daftarkan listener sebelum keputusan dibuat |
| Feature flag usang | Cache datafile | Setel updateInterval untuk penyegaran otomatis |
| Hasil tidak muncul | Eksperimen belum dijalankan | Pastikan status eksperimen adalah “running” |
Mode debug
connectors: optimizely: debug: true log_level: verbose log_decisions: true log_events: truePraktik terbaik
- Gunakan SDK untuk keputusan - Pakai SDK untuk evaluasi flag secara real-time, dan REST API untuk pengelolaan
- Terapkan batching event - Kelompokkan event SDK untuk menekan overhead jaringan
- Cache datafile - Aktifkan pembaruan otomatis dengan interval yang sesuai
- Sinkronkan variasi pemenang - Setelah eksperimen selesai, perbarui segmen kontak
- Gunakan atribut untuk penargetan - Kirim email dan atribut pengguna agar audiens dapat dicocokkan
- Pantau status eksperimen - Sinkronkan data hanya dari eksperimen yang berjalan atau sudah selesai
Keamanan
- Personal Access Token - Autentikasi bearer token untuk REST API
- Isolasi SDK key - Gunakan SDK key terpisah per environment (dev, staging, prod)
- Evaluasi sisi server - Evaluasi feature flag di sisi server agar tidak terekspos
- Rotasi token - Rotasikan Personal Access Token secara berkala
- Izin minimal - Gunakan token baca-saja bila akses tulis tidak diperlukan
- Transport terenkripsi - TLS 1.2+ untuk seluruh komunikasi API dan SDK