UNPKG

@simonecoelhosfo/optimizely-mcp-server

Version:

Optimizely MCP Server for AI assistants with integrated CLI tools

583 lines 21.9 kB
/** * Entity Creation Templates * @description Comprehensive templates for creating Optimizely entities with placeholder-based approach. * AI agents fill in {FILL: description} placeholders instead of guessing API structures. * * Template Philosophy: * - {FILL: description} = Required field that AI agent must fill * - {OPTIONAL: description} = Optional field that can be omitted * - Platform-specific templates based on is_flags_enabled project property * * @author Optimizely MCP Server * @version 1.0.0 */ /** * Comprehensive Entity Creation Templates * Organized by complexity and platform availability */ export const ENTITY_TEMPLATES = { // ============================================================================= // FEATURE EXPERIMENTATION TEMPLATES (is_flags_enabled: true) // ============================================================================= /** * Flag Creation Template - MINIMAL * Creates flag without variables or A/B test * For complex flags with variables/AB test, use advanced templates */ flag: { metadata: { platform: 'feature', complexity: 'minimal', description: 'Create a basic feature flag', requiredFields: ['key', 'name'], optionalFields: [], apiCalls: 1, dependencies: [] }, template: { key: '{FILL: unique_flag_key_no_spaces}', name: '{FILL: display_name}' } }, /** * Flag with Variables Template * Creates flag with variable definitions */ flag_with_variables: { metadata: { platform: 'feature', complexity: 'medium', description: 'Create a feature flag with variables', requiredFields: ['flag.key', 'flag.name'], optionalFields: ['variables'], apiCalls: 2, // flag + variables dependencies: [] }, template: { flag: { key: '{FILL: unique_flag_key_no_spaces}', name: '{FILL: display_name}' }, variables: [ { key: '{FILL: variable_key}', type: '{FILL_ENUM: string|boolean|integer|double|json}', default_value: '{FILL: default_value_matching_type}' } ] } }, /** * ❌ REMOVED: flag_with_ab_test template - INVALID PATTERN * * This template was teaching agents to use the incorrect 'ab_test' structure * on Feature Experimentation flags, which doesn't exist in the API. * * ✅ CORRECT APPROACH for A/B tests in Feature Experimentation: * * 1. Create the flag with variables (use flag_with_variables template) * 2. Create variations separately (entity_type='variation') * 3. Update the ruleset to add A/B test rules (entity_type='ruleset') * 4. Create experiment for tracking (entity_type='experiment') * * This multi-step approach is the ONLY way to create A/B tests in Feature Experimentation. * The 'ab_test' field does not exist on flags and was causing validation errors. * * For working examples, see: * - docs/agent-education/update-flag-ab-test-example.md (corrected approach) * - Use separate templates for each step instead of this combined approach */ /** * Event Creation Template - Feature Experimentation * Creates metrics for A/B test measurement * NOTE: All fields are optional in the API */ event: { metadata: { platform: 'feature', complexity: 'simple', description: 'Create an event/metric for measuring A/B test results', requiredFields: [], // No required fields per API spec optionalFields: ['key', 'name', 'event_type', 'event_properties'], apiCalls: 1 }, template: { key: '{FILL: unique_event_key}', name: '{FILL: display_name}', event_type: '{FILL_ENUM: custom|click|pageview|conversion}' } }, /** * Event with Properties Template - Feature Experimentation * Creates an event with event properties for advanced filtering */ event_with_properties: { metadata: { platform: 'feature', complexity: 'simple', description: 'Create an event with properties for metrics filtering', requiredFields: [], // No required fields per API spec optionalFields: ['key', 'name', 'event_type', 'event_properties'], apiCalls: 1 }, template: { _template_type: 'event_with_properties', key: '{FILL: unique_event_key}', name: '{FILL: display_name}', event_type: '{FILL_ENUM: custom|click|pageview|conversion}', event_properties: [ { name: '{FILL: property_name}', data_type: '{FILL_ENUM: string|number|boolean}', description: '{OPTIONAL: property_description}' } ] } }, // ============================================================================= // WEB EXPERIMENTATION TEMPLATES (is_flags_enabled: false) // ============================================================================= /** * Page Creation Template - Web Experimentation * Creates pages for experiment targeting */ page: { metadata: { platform: 'web', complexity: 'minimal', description: 'Create a page for web experimentation targeting', requiredFields: ['name', 'edit_url'], // project_id added automatically optionalFields: [], apiCalls: 1 }, template: { name: '{FILL: page_name}', edit_url: '{FILL: target_url}' } }, /** * Page with Conditions Template * Creates page with activation and targeting conditions */ page_with_conditions: { metadata: { platform: 'web', complexity: 'medium', description: 'Create a page with targeting conditions', requiredFields: ['name', 'edit_url'], optionalFields: ['activation_type', 'conditions'], apiCalls: 1 }, template: { name: '{FILL: page_name}', edit_url: '{FILL: target_url}', activation_type: '{FILL_ENUM: immediate|manual|polling|callback|dom_changed|url_changed}', conditions: '["and", {"type": "url", "match_type": "{FILL_ENUM: exact|simple|substring|regex}", "value": "{FILL: url_pattern}"}]' }, examples: [ { name: 'Homepage', edit_url: 'https://example.com/', activation_type: 'immediate', conditions: '["and", {"type": "url", "match_type": "exact", "value": "https://example.com/"}]' }, { name: 'Product Pages', edit_url: 'https://example.com/products/', activation_type: 'dom_changed', conditions: '["and", {"type": "url", "match_type": "substring", "value": "/products/"}]' } ] }, /** * Web Experiment Creation Template - MINIMAL * Creates experiment container only * WARNING: Must add variations separately or use experiment_with_variations */ experiment: { metadata: { platform: 'web', complexity: 'minimal', description: 'Create a web experiment container', requiredFields: [], // Only project_id required (added automatically) optionalFields: ['name', 'page_ids'], apiCalls: 1, dependencies: ['page'] }, template: { name: '{FILL: experiment_name}', page_ids: ['{FILL: page_id_from_page_creation}'] } }, /** * Web Experiment with Variations Template * Creates complete experiment with variations * CRITICAL: All variations MUST have actions with changes */ experiment_with_variations: { metadata: { platform: 'web', complexity: 'medium', description: 'Create a complete web experiment with variations', requiredFields: ['variations[].weight'], // Variations must have weight optionalFields: ['name', 'page_ids'], apiCalls: 2, // experiment + variations dependencies: ['page'] }, template: { name: '{FILL: experiment_name}', page_ids: ['{FILL: page_id_from_page_creation}'], variations: [ { name: '{FILL: Control}', weight: '{FILL: basis_points_10000=100%}', // Must sum to 10000 across all variations // For 3 variations: use 3333, 3333, 3334 // For 4+ variations: divide 10000 evenly, give remainder to last variations actions: [] // Changes will be added later in the Optimizely UI }, { name: '{FILL: Treatment}', weight: '{FILL: basis_points_10000=100%}', actions: [] // Changes will be added later in the Optimizely UI } ], metrics: [ { event_id: '{FILL: integer_event_id}', // ⚠️ CRITICAL: Must be integer ID of existing event aggregator: '{REQUIRED_ENUM: "unique" | "count" | "sum" | "bounce" | "exit" | "ratio"}', // ⚠️ CRITICAL: Must use EXACT value from this list scope: '{REQUIRED_ENUM: "session" | "visitor" | "event"}', // ⚠️ CRITICAL: Must use EXACT value from this list winning_direction: '{OPTIONAL_ENUM: "increasing" | "decreasing"}' // Optional, defaults to "increasing" } ] }, examples: [ { name: 'Homepage Hero Test', description: 'Test different hero section copy', page_ids: ['12345'], variations: [ { name: 'Control', weight: 5000, actions: [] // No changes for Control - defined later in UI }, { name: 'New Hero Copy', weight: 5000, actions: [ { page_id: 12345, changes: [ { type: 'insert_html', selector: '.hero-title', value: '<h1>Revolutionary New Product</h1>' } ] } ] } ] }, { name: 'Three-Way Button Test Example', description: 'Testing three different button colors', page_ids: ['12345'], variations: [ { name: 'Blue Button', weight: 3333, actions: [ { page_id: 12345, changes: [ { type: 'replace_html', selector: '.cta-button', value: '<button class="blue">Get Started</button>' } ] } ] }, { name: 'Green Button', weight: 3333, actions: [ { page_id: 12345, changes: [ { type: 'replace_html', selector: '.cta-button', value: '<button class="green">Get Started</button>' } ] } ] }, { name: 'Red Button', weight: 3334, // Gets the extra basis point actions: [ { page_id: 12345, changes: [ { type: 'replace_html', selector: '.cta-button', value: '<button class="red">Get Started</button>' } ] } ] } ] } ] }, /** * Campaign Creation Template - Web Experimentation * Creates campaigns for grouping experiments */ campaign: { metadata: { platform: 'web', complexity: 'minimal', description: 'Create a campaign for organizing experiments', requiredFields: [], // Only project_id required (added automatically) optionalFields: ['name'], apiCalls: 1 }, template: { name: '{FILL: campaign_name}' }, examples: [ { name: 'Q4 Homepage Optimization', description: 'Testing different homepage elements for Q4', page_ids: ['12345'], holdback: '1000' }, { // Example with entity reference (Phase 3) name: 'Multi-Page Campaign', description: 'Campaign across multiple existing pages', page_ids: [ '{EXISTING: page:homepage}', '{EXISTING: page:product_list}', '{FIND_OR_CREATE: page:checkout}' ], holdback: '500' } ] }, // ============================================================================= // SHARED TEMPLATES (Both platforms) // ============================================================================= /** * Audience Creation Template - Both Platforms * Creates audience segments for targeting */ audience: { metadata: { platform: 'both', complexity: 'minimal', description: 'Create a basic audience', requiredFields: [], // Only project_id required (added automatically) optionalFields: ['name'], apiCalls: 1 }, template: { name: '{FILL: audience_name}' } }, /** * Audience with Conditions Template * Creates audience with targeting conditions */ audience_with_conditions: { metadata: { platform: 'both', complexity: 'medium', description: 'Create an audience with targeting conditions', requiredFields: [], optionalFields: ['name', 'conditions'], apiCalls: 1 }, template: { name: '{FILL: audience_name}', conditions: [ 'and', { type: '{FILL_ENUM: browser|location|custom_attribute|device}', name: '{FILL: condition_parameter}', value: '{FILL: condition_value}' } ] }, examples: [ { name: 'US Mobile Users', description: 'Users on mobile devices in the United States', conditions: [ 'and', { type: 'location', name: 'country', value: 'US' }, { type: 'device', name: 'mobile', value: 'true' } ] } ] }, /** * Attribute Creation Template - Both Platforms * Creates custom attributes for audience targeting */ attribute: { metadata: { platform: 'both', complexity: 'minimal', description: 'Create a custom attribute', requiredFields: ['key'], // project_id added automatically optionalFields: ['name'], apiCalls: 1 }, template: { key: '{FILL: attribute_key_no_spaces}', name: '{FILL: display_name}' }, examples: [ { key: 'user_tier', name: 'User Tier', description: 'Customer tier level (bronze, silver, gold)', condition_type: 'single_option' } ] }, /** * Webhook Creation Template - Both Platforms * Creates webhooks for event notifications */ webhook: { metadata: { platform: 'both', complexity: 'minimal', description: 'Create a webhook for notifications', requiredFields: ['name', 'url'], // project_id added automatically optionalFields: ['event_types'], apiCalls: 1 }, template: { name: '{FILL: webhook_name}', url: '{FILL: https_endpoint_url}', event_types: ['{FILL_ENUM: experiment.created|experiment.modified|decision.notification}'] }, examples: [ { name: 'Slack Notifications', url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK', event_types: ['experiment.created', 'experiment.modified'], headers: { 'Content-Type': 'application/json' } } ] }, /** * Extension Creation Template - Web Experimentation * Creates custom JavaScript extensions */ extension: { metadata: { platform: 'web', complexity: 'minimal', description: 'Create a JavaScript extension', requiredFields: ['name', 'edit_url', 'implementation'], // per API spec optionalFields: [], apiCalls: 1 }, template: { name: '{FILL: extension_name}', edit_url: '{FILL: editor_url}', implementation: '{FILL: javascript_code_string}' }, examples: [ { name: 'Google Analytics Integration', description: 'Send experiment data to Google Analytics', extension_type: 'analytics_integration', implementation: ` window.optimizely = window.optimizely || []; window.optimizely.push({ type: "analytics", provider: "google", measurementId: "GA_MEASUREMENT_ID" }); ` } ] } }; /** * Get templates available for a specific platform * @param isFeatureExperimentation - Whether project has Feature Experimentation enabled * @returns Available entity templates for the platform */ export function getAvailableTemplates(isFeatureExperimentation) { const availableTemplates = {}; for (const [entityType, template] of Object.entries(ENTITY_TEMPLATES)) { const { platform } = template.metadata; if (platform === 'both') { availableTemplates[entityType] = template; } else if (platform === 'feature' && isFeatureExperimentation) { availableTemplates[entityType] = template; } else if (platform === 'web' && !isFeatureExperimentation) { availableTemplates[entityType] = template; } } return availableTemplates; } /** * Get template placeholders that need to be filled * @param template - Template object to analyze * @returns Array of placeholder descriptions */ export function getTemplatePlaceholders(template) { const placeholders = []; function extractPlaceholders(obj, path = '') { if (typeof obj === 'string') { const fillMatch = obj.match(/\{FILL:\s*([^}]+)\}/); const optionalMatch = obj.match(/\{OPTIONAL:\s*([^}]+)\}/); if (fillMatch) { placeholders.push(`${path}: ${fillMatch[1]} (REQUIRED)`); } else if (optionalMatch) { placeholders.push(`${path}: ${optionalMatch[1]} (OPTIONAL)`); } } else if (Array.isArray(obj)) { obj.forEach((item, index) => { extractPlaceholders(item, `${path}[${index}]`); }); } else if (obj && typeof obj === 'object') { Object.entries(obj).forEach(([key, value]) => { const newPath = path ? `${path}.${key}` : key; extractPlaceholders(value, newPath); }); } } extractPlaceholders(template); return placeholders; } //# sourceMappingURL=EntityTemplates.js.map