@simonecoelhosfo/optimizely-mcp-server
Version:
Optimizely MCP Server for AI assistants with integrated CLI tools
832 lines (756 loc) • 34.8 kB
JavaScript
/**
* Plugin Pattern Examples
* Common patterns for using custom functions in orchestration
*/
export const pluginPatterns = {
// Campaign Configuration Patterns
campaign_configuration: {
external_segment_integration: {
id: 'pattern_external_segments',
name: 'External Customer Segment Integration',
description: 'Fetch customer segments from CDP to configure audience targeting',
template: {
type: 'plugin',
plugin: {
code: `
const cdpEndpoint = parameters.cdp_api_endpoint;
const apiKey = parameters.cdp_api_key;
const campaignType = parameters.campaign_type;
try {
console.log('Fetching customer segments from CDP...');
const response = await api.fetch(cdpEndpoint + '/segments', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + apiKey,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error('CDP API returned ' + response.status);
}
const segments = JSON.parse(response.data);
// Filter segments relevant to this campaign type
const relevantSegments = segments.filter(segment => {
if (campaignType === 'premium_features') {
return segment.tier === 'premium' || segment.tier === 'enterprise';
} else if (campaignType === 'onboarding') {
return segment.lifecycle_stage === 'new' || segment.lifecycle_stage === 'trial';
}
return true;
});
// Generate audience conditions for each segment
const audienceConditions = relevantSegments.map(segment => ({
segment_id: segment.id,
segment_name: segment.name,
condition: {
type: 'custom_attribute',
name: 'customer_segment_id',
match_type: 'exact',
value: segment.id
},
description: 'Targets ' + segment.name + ' (' + segment.size + ' users)'
}));
return {
available_segments: relevantSegments,
audience_conditions: audienceConditions,
total_addressable_users: relevantSegments.reduce((sum, s) => sum + s.size, 0)
};
} catch (error) {
console.error('Failed to fetch segments:', error.message);
return {
available_segments: [],
audience_conditions: [],
error: 'Could not connect to CDP: ' + error.message
};
}
`,
inputs: {
cdp_api_endpoint: '${external_apis.cdp_base_url}',
cdp_api_key: '${external_apis.cdp_token}',
campaign_type: '${campaign_configuration.type}'
},
outputs: ['available_segments', 'audience_conditions', 'total_addressable_users', 'error'],
permissions: {
external_requests: true
},
timeout_ms: 15000
}
},
usage: 'Configure audience targeting using external customer segments from CDP'
},
pricing_tier_experience_generator: {
id: 'pattern_pricing_tiers',
name: 'Pricing Tier Experience Generator',
description: 'Generate experiment variations based on current pricing tiers from external system',
template: {
type: 'plugin',
plugin: {
code: `
const pricingEndpoint = parameters.pricing_api_endpoint;
const productId = parameters.product_id;
const experimentType = parameters.experiment_type;
try {
// Fetch current pricing tiers from external system
const response = await api.fetch(pricingEndpoint + '/tiers/' + productId, {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + parameters.pricing_api_key,
'Content-Type': 'application/json'
}
});
const pricingData = JSON.parse(response.data);
// Generate JavaScript code that will run for ALL users in each variation
const generatePricingExperience = (tier) => {
return \`
// This code runs for ALL users assigned to this variation
(function() {
const tierConfig = \${JSON.stringify(tier)};
// Update pricing display for everyone in this variation
const priceElements = document.querySelectorAll('.product-price');
priceElements.forEach(function(element) {
element.innerHTML = '<span class="price">$' + tierConfig.price + '</span>';
if (tierConfig.discount > 0) {
element.innerHTML += '<span class="discount">' + tierConfig.discount + '% off</span>';
}
});
// Add tier-specific styling
document.body.className += ' pricing-tier-' + tierConfig.name.toLowerCase();
// Track which tier this variation represents
window.optimizely = window.optimizely || [];
window.optimizely.push(['trackEvent', 'pricing_tier_shown', {
tier: tierConfig.name,
price: tierConfig.price
}]);
})();
\`;
};
// Create variation configs for the experiment
const variations = pricingData.tiers.map((tier, index) => ({
name: tier.name + ' Pricing (' + tier.price + ')',
weight: tier.allocation_percentage * 100, // Convert to basis points
javascript_code: generatePricingExperience(tier),
metadata: {
tier_id: tier.id,
price: tier.price,
discount: tier.discount
}
}));
return {
experiment_name: 'Pricing Tier Test - ' + pricingData.product_name,
variations: variations,
total_tiers: pricingData.tiers.length,
expected_traffic_split: pricingData.tiers.map(t => t.name + ': ' + t.allocation_percentage + '%').join(', ')
};
} catch (error) {
console.error('Pricing API error:', error.message);
return {
error: 'Could not generate pricing experiment: ' + error.message,
variations: []
};
}
`,
inputs: {
pricing_api_endpoint: '${external_apis.pricing_service_url}',
pricing_api_key: '${external_apis.pricing_token}',
product_id: '${experiment_config.target_product}',
experiment_type: 'pricing_test'
},
outputs: ['experiment_name', 'variations', 'total_tiers', 'expected_traffic_split', 'error'],
permissions: {
external_requests: true
}
}
},
usage: 'Generate pricing experiment variations based on external pricing tier configuration'
},
score_calculation: {
id: 'pattern_score_calculation',
name: 'Engagement Score Calculator',
description: 'Calculate user engagement scores',
template: {
type: 'plugin',
plugin: {
code: `
const activities = parameters.user_activities;
let score = 0;
// Weight different activities
const weights = {
page_view: 1,
click: 2,
form_submit: 5,
purchase: 20,
share: 10
};
for (const activity of activities) {
score += (weights[activity.type] || 0) * activity.count;
}
// Normalize to 0-100
const normalizedScore = Math.min(100, Math.round(score / 10));
return {
raw_score: score,
normalized_score: normalizedScore,
engagement_level: normalizedScore > 70 ? 'high' : normalizedScore > 30 ? 'medium' : 'low'
};
`,
inputs: {
user_activities: '${activity_data}'
},
outputs: ['raw_score', 'normalized_score', 'engagement_level']
}
},
usage: 'Calculate engagement scores from user activity data'
}
},
// Content Generation Patterns
content_generation: {
extension_template_generator: {
id: 'pattern_extension_generator',
name: 'Extension Template Generator',
description: 'Generate Optimizely extension code based on external content/configuration',
template: {
type: 'plugin',
plugin: {
code: `
const contentEndpoint = parameters.content_api_endpoint;
const brandingEndpoint = parameters.branding_api_endpoint;
const extensionType = parameters.extension_type;
try {
// Fetch current branding/content from external CMS
const [contentResponse, brandingResponse] = await Promise.all([
api.fetch(contentEndpoint + '/campaign-content', {
method: 'GET',
headers: { 'Authorization': 'Bearer ' + parameters.cms_api_key }
}),
api.fetch(brandingEndpoint + '/current-theme', {
method: 'GET',
headers: { 'Authorization': 'Bearer ' + parameters.cms_api_key }
})
]);
const content = JSON.parse(contentResponse.data);
const branding = JSON.parse(brandingResponse.data);
// Generate extension JavaScript that will run for ALL experiment visitors
let extensionCode = '';
if (extensionType === 'banner_overlay') {
extensionCode = \`
// Banner overlay extension - runs for all visitors in this experiment
(function() {
var banner = document.createElement('div');
banner.id = 'experiment-banner';
banner.style.cssText = \`
position: fixed;
top: 0;
left: 0;
width: 100%;
background: \${branding.primary_color};
color: \${branding.text_color};
padding: 12px;
text-align: center;
z-index: 10000;
font-family: \${branding.font_family};
\`;
banner.innerHTML = '\${content.banner_message}';
// Add close button
var closeBtn = document.createElement('button');
closeBtn.innerHTML = '×';
closeBtn.style.cssText = 'float: right; background: none; border: none; color: inherit; font-size: 18px; cursor: pointer;';
closeBtn.onclick = function() { banner.remove(); };
banner.appendChild(closeBtn);
document.body.insertBefore(banner, document.body.firstChild);
// Track that banner was shown
window.optimizely = window.optimizely || [];
window.optimizely.push(['trackEvent', 'banner_shown', {
campaign_id: '\${content.campaign_id}',
message: '\${content.banner_message}'
}]);
})();
\`;
} else if (extensionType === 'checkout_enhancement') {
extensionCode = \`
// Checkout enhancement - runs for all visitors on checkout pages
(function() {
// Wait for checkout form to load
var checkInterval = setInterval(function() {
var checkoutForm = document.querySelector('\${content.checkout_form_selector}');
if (checkoutForm) {
clearInterval(checkInterval);
// Add trust signals
var trustDiv = document.createElement('div');
trustDiv.className = 'experiment-trust-signals';
trustDiv.innerHTML = \`
<div style="background: \${branding.secondary_color}; padding: 15px; margin: 10px 0; border-radius: 5px;">
<h4 style="margin: 0 0 10px 0; color: \${branding.primary_color};">\${content.trust_heading}</h4>
<ul style="margin: 0; padding-left: 20px; color: \${branding.text_color};">
\${content.trust_points.map(point => '<li>' + point + '</li>').join('')}
</ul>
</div>
\`;
checkoutForm.insertBefore(trustDiv, checkoutForm.firstChild);
// Track enhancement shown
window.optimizely.push(['trackEvent', 'checkout_enhancement_shown']);
}
}, 500);
})();
\`;
}
return {
extension_name: content.campaign_name + ' - ' + extensionType,
extension_code: extensionCode,
content_updated_at: content.last_modified,
branding_theme: branding.theme_name,
estimated_load_impact: 'Low - ~2KB additional'
};
} catch (error) {
console.error('Content generation failed:', error.message);
return {
extension_code: '// Error: Could not generate extension - ' + error.message,
error: error.message
};
}
`,
inputs: {
content_api_endpoint: '${external_apis.cms_base_url}',
branding_api_endpoint: '${external_apis.branding_service_url}',
cms_api_key: '${external_apis.cms_token}',
extension_type: '${experiment_config.extension_type}'
},
outputs: ['extension_name', 'extension_code', 'content_updated_at', 'branding_theme', 'error'],
permissions: {
external_requests: true
}
}
},
usage: 'Generate extension code with current content/branding for all experiment visitors'
},
data_quality_check: {
id: 'pattern_data_quality',
name: 'Data Quality Checker',
description: 'Check data quality before processing',
template: {
type: 'plugin',
plugin: {
code: `
const data = parameters.input_data;
const issues = [];
// Check for required fields
const requiredFields = parameters.required_fields || [];
for (const item of data) {
for (const field of requiredFields) {
if (!item[field]) {
issues.push({
item_id: item.id || 'unknown',
issue: \`Missing required field: \${field}\`
});
}
}
}
// Check data types
const typeChecks = parameters.type_checks || {};
for (const item of data) {
for (const [field, expectedType] of Object.entries(typeChecks)) {
if (item[field] && typeof item[field] !== expectedType) {
issues.push({
item_id: item.id || 'unknown',
issue: \`Invalid type for \${field}: expected \${expectedType}\`
});
}
}
}
return {
total_items: data.length,
issue_count: issues.length,
quality_score: Math.round((1 - issues.length / data.length) * 100),
issues: issues.slice(0, 10), // First 10 issues
passed: issues.length === 0
};
`,
inputs: {
input_data: '${data_to_validate}',
required_fields: ['id', 'name', 'value'],
type_checks: { value: 'number', active: 'boolean' }
},
outputs: ['total_items', 'issue_count', 'quality_score', 'issues', 'passed']
}
},
usage: 'Validate data quality before import or processing'
}
},
// Page Targeting Patterns
page_targeting: {
dynamic_product_targeting: {
id: 'pattern_dynamic_product_targeting',
name: 'Dynamic Product Page Targeting',
description: 'Generate page targeting conditions based on current product catalog from external system',
template: {
type: 'plugin',
plugin: {
code: `
const catalogEndpoint = parameters.catalog_api_endpoint;
const campaignType = parameters.campaign_type;
const targetCategory = parameters.target_category;
try {
// Fetch current product catalog from external system
const response = await api.fetch(catalogEndpoint + '/products', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + parameters.catalog_api_key,
'Content-Type': 'application/json'
},
query: {
category: targetCategory,
active: true,
campaign_eligible: true
}
});
const products = JSON.parse(response.data);
// Generate page targeting conditions based on product URLs
const pageConditions = [];
if (campaignType === 'product_upsell') {
// Target product detail pages
const productUrls = products.map(p => p.url_path);
pageConditions.push({
match_type: 'regex',
value: '(' + productUrls.join('|') + ')',
description: 'Targets ' + products.length + ' product pages in ' + targetCategory + ' category'
});
// Also target category listing pages
pageConditions.push({
match_type: 'substring',
value: '/category/' + targetCategory.toLowerCase(),
description: 'Targets category listing page'
});
} else if (campaignType === 'cart_abandonment') {
// Target pages where these products might be added to cart
pageConditions.push({
match_type: 'simple',
value: '/cart',
description: 'Targets cart page'
});
pageConditions.push({
match_type: 'simple',
value: '/checkout',
description: 'Targets checkout page'
});
}
// Generate JavaScript targeting conditions for complex scenarios
const jsCondition = \`
// Advanced targeting condition - checks if current page has eligible products
(function() {
var eligibleProductIds = \${JSON.stringify(products.map(p => p.id))};
var currentProductId = window.productData ? window.productData.id : null;
// Check if current page is for an eligible product
if (currentProductId && eligibleProductIds.indexOf(currentProductId) !== -1) {
return true;
}
// Check if page has eligible products in listing
var productCards = document.querySelectorAll('[data-product-id]');
for (var i = 0; i < productCards.length; i++) {
var productId = productCards[i].getAttribute('data-product-id');
if (eligibleProductIds.indexOf(productId) !== -1) {
return true;
}
}
return false;
})();
\`;
return {
page_conditions: pageConditions,
javascript_condition: jsCondition,
targeted_products: products.map(p => ({ id: p.id, name: p.name, url: p.url_path })),
total_products: products.length,
category_targeted: targetCategory
};
} catch (error) {
console.error('Catalog API error:', error.message);
return {
page_conditions: [{
match_type: 'simple',
value: '/' + targetCategory.toLowerCase(),
description: 'Fallback: Target category pages only'
}],
error: 'Could not fetch product catalog: ' + error.message
};
}
`,
inputs: {
catalog_api_endpoint: '${external_apis.catalog_service_url}',
catalog_api_key: '${external_apis.catalog_token}',
campaign_type: '${experiment_config.campaign_type}',
target_category: '${experiment_config.product_category}'
},
outputs: ['page_conditions', 'javascript_condition', 'targeted_products', 'total_products', 'error'],
permissions: {
external_requests: true
}
}
},
usage: 'Configure page targeting based on current product catalog for campaign experiments'
},
audience_converter: {
id: 'pattern_audience_converter',
name: 'Audience Format Converter',
description: 'Convert between different audience condition formats',
template: {
type: 'plugin',
plugin: {
code: `
const sourceAudiences = parameters.source_audiences;
const targetFormat = parameters.target_format;
const converted = [];
for (const audience of sourceAudiences) {
let conditions;
if (targetFormat === 'optimizely') {
// Convert to Optimizely format
conditions = [];
for (const rule of audience.rules || []) {
if (rule.attribute) {
conditions.push({
type: 'custom_attribute',
name: rule.attribute,
match_type: rule.operator === '==' ? 'exact' : rule.operator,
value: rule.value
});
} else if (rule.event) {
conditions.push({
type: 'behavior',
event_name: rule.event,
match_type: 'exists'
});
}
}
converted.push({
key: audience.id.toLowerCase().replace(/\\W+/g, '_'),
name: audience.name,
conditions: conditions.length > 1 ? { and: conditions } : conditions[0]
});
}
}
return {
converted_audiences: converted,
conversion_count: converted.length
};
`,
inputs: {
source_audiences: '${audiences_to_convert}',
target_format: 'optimizely'
},
outputs: ['converted_audiences', 'conversion_count']
}
},
usage: 'Convert audience definitions between different formats'
}
},
// Experiment Configuration Patterns
experiment_configuration: {
experiment_setup_validator: {
id: 'pattern_experiment_validator',
name: 'Experiment Configuration Validator',
description: 'Validate experiment setup meets business requirements before launch',
template: {
type: 'plugin',
plugin: {
code: `
const endpoint = parameters.api_endpoint;
const apiKey = parameters.api_key;
const method = parameters.method || 'GET';
try {
console.log(\`Calling \${method} \${endpoint}\`);
const response = await api.fetch(endpoint, {
method: method,
headers: {
'Authorization': \`Bearer \${apiKey}\`,
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: method !== 'GET' ? JSON.stringify(parameters.request_body) : undefined
});
if (!response.ok) {
throw new Error(\`API returned \${response.status}: \${response.statusText}\`);
}
const data = JSON.parse(response.data);
return {
success: true,
data: data,
status: response.status
};
} catch (error) {
console.error('API call failed:', error.message);
return {
success: false,
error: error.message,
data: null
};
}
`,
inputs: {
api_endpoint: '${external_api_url}',
api_key: '${api_credentials.key}',
method: 'GET',
request_body: {}
},
outputs: ['success', 'data', 'error', 'status'],
permissions: {
external_requests: true
},
timeout_ms: 30000
}
},
usage: 'Fetch data from external REST APIs'
},
webhook_notifier: {
id: 'pattern_webhook_notify',
name: 'Webhook Notification Sender',
description: 'Send notifications via webhook',
template: {
type: 'plugin',
plugin: {
code: `
const webhookUrl = parameters.webhook_url;
const eventType = parameters.event_type;
const eventData = parameters.event_data;
const payload = {
event: eventType,
timestamp: new Date().toISOString(),
data: eventData,
source: 'optimizely_orchestration'
};
try {
const response = await api.fetch(webhookUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Event-Type': eventType
},
body: JSON.stringify(payload)
});
console.log(\`Webhook notification sent: \${eventType}\`);
return {
sent: true,
status: response.status,
event_id: \`evt_\${Date.now()}\`
};
} catch (error) {
console.error('Failed to send webhook:', error.message);
return {
sent: false,
error: error.message
};
}
`,
inputs: {
webhook_url: '${notification_webhook}',
event_type: '${event_name}',
event_data: '${event_payload}'
},
outputs: ['sent', 'status', 'event_id', 'error'],
permissions: {
external_requests: true
}
}
},
usage: 'Send webhook notifications for orchestration events'
}
},
// Orchestration Tracking Patterns
orchestration_tracking: {
campaign_setup_tracker: {
id: 'pattern_campaign_tracker',
name: 'Campaign Setup Progress Tracker',
description: 'Track orchestration progress and log setup milestones',
template: {
type: 'plugin',
plugin: {
code: `
const counterKey = parameters.counter_name;
const increment = parameters.increment || 1;
// Get current count
const currentCount = await api.getState(counterKey) || 0;
const newCount = currentCount + increment;
// Update count
await api.setState(counterKey, newCount);
console.log(\`Counter \${counterKey}: \${currentCount} -> \${newCount}\`);
return {
counter_name: counterKey,
previous_count: currentCount,
new_count: newCount,
increment: increment
};
`,
inputs: {
counter_name: 'execution_count',
increment: 1
},
outputs: ['counter_name', 'previous_count', 'new_count', 'increment'],
permissions: {
write_state: true
}
}
},
usage: 'Track how many times a workflow or step has executed'
},
cache_manager: {
id: 'pattern_cache',
name: 'Temporary Cache Manager',
description: 'Cache data between steps',
template: {
type: 'plugin',
plugin: {
code: `
const operation = parameters.operation;
const cacheKey = parameters.cache_key;
const ttl = parameters.ttl_seconds || 3600;
if (operation === 'set') {
const cacheData = {
data: parameters.data,
expires_at: Date.now() + (ttl * 1000),
created_at: Date.now()
};
await api.setState(cacheKey, cacheData);
return {
operation: 'set',
success: true,
expires_in_seconds: ttl
};
} else if (operation === 'get') {
const cached = await api.getState(cacheKey);
if (!cached) {
return {
operation: 'get',
found: false,
data: null
};
}
if (cached.expires_at < Date.now()) {
// Expired - clear it
await api.setState(cacheKey, null);
return {
operation: 'get',
found: false,
expired: true,
data: null
};
}
return {
operation: 'get',
found: true,
data: cached.data,
age_seconds: Math.round((Date.now() - cached.created_at) / 1000)
};
}
`,
inputs: {
operation: 'get',
cache_key: 'temp_data',
data: null,
ttl_seconds: 3600
},
outputs: ['operation', 'success', 'found', 'data', 'expired', 'age_seconds'],
permissions: {
write_state: true
}
}
},
usage: 'Cache temporary data with expiration'
}
}
};
//# sourceMappingURL=PluginPatterns.js.map