موصل Optimizely
اربط Optimizely Feature Experimentation بـ Brevo من خلال Tajo لمزامنة نتائج التجارب، واستهداف الحملات حسب شرائح علامات الميزات، وإثراء أتمتة التسويق ببيانات اختبار A/B ورؤى الجمهور.
نظرة عامة
| الخاصية | القيمة |
|---|---|
| المنصة | Optimizely |
| الفئة | التجريب (مخصص) |
| تعقيد الإعداد | متوسط |
| تكامل رسمي | لا |
| البيانات المُزامَنة | تجارب، جماهير، أحداث، علامات ميزات |
| طريقة المصادقة | رمز وصول شخصي / OAuth 2.0 |
الميزات
- مزامنة التجارب - دفع تعيينات تنويعات اختبار A/B إلى سمات جهات اتصال Brevo
- استهداف الجمهور - استخدام جماهير Optimizely لتقسيم حملات Brevo
- تتبع التحويلات - تتبع أحداث Optimizely وربطها بتتبع أحداث Brevo
- مزامنة علامات الميزات - تقسيم جهات الاتصال حسب علامات الميزات المُفعّلة
- تقارير النتائج - مزامنة نتائج التجارب لحملات التسويق ما بعد التحليل
- دعم مشاريع متعددة - ربط مشاريع Optimizely متعددة بمثيل Tajo واحد
المتطلبات الأساسية
قبل البدء، تأكد من توفر ما يلي:
- حساب Optimizely Feature Experimentation
- رمز وصول شخصي من إعدادات تطبيق Optimizely
- مفتاح SDK لبيئة Optimizely الخاصة بك
- حساب Brevo مع وصول إلى API
- حساب Tajo مع صلاحيات الموصلات
المصادقة
رمز الوصول الشخصي
# 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
// لتقييم علامات الميزات، استخدم الـ 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();الإعداد
الإعداد الأساسي
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_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نقاط نهاية واجهة البرمجة
| نقطة النهاية | الطريقة | الوصف |
|---|---|---|
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 طلب/دقيقة | لكل رمز وصول شخصي |
| Results API | 10 طلب/دقيقة | زمن استجابة أعلى، استعلامات أثقل |
| إرسال أحداث SDK | 10,000 حدث/دفعة | عبر معالج أحداث SDK |
| CDN ملف البيانات | غير محدود | مخزّن مؤقتًا مع تحديثات تلقائية |
زمن استجابة Results API
تعالج واجهة نتائج التجربة مجموعات بيانات كبيرة وقد تستغرق 30 ثانية أو أكثر للاستجابة. استخدم الاستطلاع غير المتزامن أو التخزين المؤقت لتجنب حجب تطبيقك.
استكشاف الأخطاء وإصلاحها
| المشكلة | السبب | الحل |
|---|---|---|
| 401 Unauthorized | الرمز منتهي/غير صالح | أعد توليد رمز الوصول الشخصي |
| SDK ليس جاهزًا | ملف البيانات لم يُحمَّل | انتظر حلّ وعد onReady() |
| لا توجد قرارات مسجلة | الإشعار غير مُسجَّل | سجّل المستمع قبل اتخاذ القرارات |
| علامات ميزات قديمة | ذاكرة تخزين ملف البيانات | اضبط updateInterval للتحديث التلقائي |
| نتائج مفقودة | لم تبدأ التجربة | تحقق من أن حالة التجربة “running” |
وضع التصحيح
connectors: optimizely: debug: true log_level: verbose log_decisions: true log_events: trueأفضل الممارسات
- استخدم الـ SDK للقرارات - استخدم الـ SDK لتقييم العلامات في الوقت الفعلي، وREST API للإدارة
- طبّق تجميع الأحداث - جمّع أحداث SDK لتقليل عبء الشبكة
- خزّن ملف البيانات مؤقتًا - فعّل التحديث التلقائي بفترات مناسبة
- مزامنة التنويعات الفائزة - بعد انتهاء التجارب، حدّث شرائح جهات الاتصال
- استخدم السمات للاستهداف - مرّر البريد الإلكتروني وسمات المستخدم لمطابقة الجمهور
- راقب حالة التجارب - زامن فقط بيانات من تجارب قيد التشغيل أو المنتهية
الأمان
- رموز الوصول الشخصية - مصادقة Bearer token لـ REST API
- عزل مفتاح SDK - مفاتيح SDK منفصلة لكل بيئة (dev، staging، prod)
- التقييم من جانب الخادم - قيّم علامات الميزات من جانب الخادم لمنع الكشف
- تدوير الرموز - دوّر رموز الوصول الشخصية دوريًا
- الحد الأدنى من الصلاحيات - استخدم رموز قراءة فقط عندما لا يكون الوصول للكتابة ضروريًا
- النقل المُشفَّر - TLS 1.2+ لجميع اتصالات API وSDK