Campaign Rules

Understand how to build Campaign JSONs

What is a Campaign JSON?

A Campaign JSON is the complete blueprint for how rewards and incentives work in your campaigns. It defines exactly who gets what rewards and when they get them. Think of it as a smart rulebook that automatically handles different customer scenarios and delivers the right rewards at the right time.

Why is Campaign JSON Structure Important?

Campaign JSONs must follow strict rules to work properly. The validation service checks every part of your campaign to ensure:

  • Security: Prevents malicious code or invalid data

  • Performance: Ensures campaigns run fast and efficiently

  • Accuracy: Guarantees customers get the right rewards

  • Reliability: Avoids errors during campaign execution

When you build a campaign JSON incorrectly, the validation service will tell you exactly what's wrong and how to fix it.

Basic Campaign Structure

Every campaign JSON has three main parts:

Section

Purpose

Required

start

Campaign details and who can use it

✅ Yes

switch

How customers are routed between paths

❌ No (auto-generated)

paths

Different reward scenarios

✅ Yes

Simple Campaign Example

{
  "start": {
    "campaign_name": "Summer Sale",
    "campaign_slug": "summer-sale-2024",
    "display_name": "🌞 Summer Sale - 20% Off Everything!",
    "description": "Get 20% off your entire order during our summer sale",
    "applies_to": "everyone"
  },
  "paths": [
    {
      "conditions": {
        "logic": "AND",
        "rules": [
          {
            "field": "cart_value",
            "operator": ">=",
            "value": 50
          }
        ]
      },
      "actions": [
        {
          "action": "discount",
          "discount_type": "percentage",
          "value": 20
        }
      ]
    }
  ]
}

Step 1: Building the Start Configuration

The

start

section contains your campaign's basic information and determines who can participate.

Required Fields

{
  "start": {
    "campaign_name": "Your Campaign Name",      // Internal name for your team
    "campaign_slug": "your-campaign-slug",     // URL-friendly identifier  
    "display_name": "Customer-Facing Title",   // What customers see
    "description": "What this campaign does",  // Explain the campaign
    "applies_to": "everyone"                   // Who can participate
  }
}

Field Requirements

Field

Type

Rules

Example

campaign_name

string

Any descriptive name

"Black Friday 2024"

campaign_slug

string

URL-safe, no spaces

"black-friday-2024"

display_name

string

Customer-facing title

"🛍️ Black Friday - 50% Off!"

description

string

Clear explanation

"Get 50% off everything during Black Friday"

applies_to

string/array

See eligibility section below

"everyone"

Who Can Participate (applies_to)

You have two options for campaign eligibility:

Option 1: Public Campaign

"applies_to": "everyone"
  • Anyone can use this campaign

  • No special codes needed

  • Most common option

Option 2: Specific People Only

"applies_to": ["john_doe", "jane_smith", "vip_customer"]
  • Only listed advocate codes can use it

  • Perfect for exclusive offers

  • Each string is an advocate code

❌ Common Mistakes - applies_to

// ❌ WRONG - Don't use these deprecated terms
"applies_to": "all"        // Use "everyone" instead
"applies_to": "ANY"        // Use "everyone" instead
"applies_to": "All"        // Use "everyone" instead

// ❌ WRONG - Don't use these unclear terms  
"applies_to": "any"        // Use "everyone" instead
"applies_to": "public"     // Use "everyone" instead

// ✅ CORRECT
"applies_to": "everyone"   // For public campaigns
"applies_to": ["user1", "user2"]  // For specific people

Optional Start Fields

{
  "start": {
    // ... required fields above ...
    "start_date": "2024-12-01T00:00:00Z",           // When campaign starts
    "end_date": "2024-12-31T23:59:59Z",             // When campaign ends  
    "image_url": "https://example.com/banner.jpg",   // Campaign banner
    "initial_payout": {                              // Immediate rewards
      "payout_type": "payout",
      "amount": 5,
      "currency": "USD"
    },
    "requires_authentication": true                   // Login required (default: true)
  }
}

Initial Payout (Sign-up Bonuses)

Give immediate rewards when someone joins your campaign:

{
  "initial_payout": {
    "payout_type": "payout",     // Must be "payout"
    "amount": 10,                // Dollar amount
    "currency": "USD"            // Currency code (optional, defaults to USD)
  }
}

You can also give multiple sign-up bonuses:

{
  "initial_payout": [
    {
      "payout_type": "payout",
      "amount": 5,
      "currency": "USD"
    },
    {
      "payout_type": "payout", 
      "amount": 100,
      "currency": "POINTS"
    }
  ]
}

❌ Common Start Configuration Mistakes

// ❌ WRONG - Don't include these fields
{
  "start": {
    "is_active": true,  // This field causes validation errors
    "initial_payout": {
      "is_active": true,  // This field causes validation errors
      "payout_type": "bonus",  // Must be "payout"
      "amount": -5,       // Must be positive
      "amount": "10"      // Must be number, not string
    }
  }
}

// ✅ CORRECT
{
  "start": {
    "campaign_name": "My Campaign",
    "campaign_slug": "my-campaign", 
    "display_name": "My Campaign",
    "description": "A great campaign",
    "applies_to": "everyone",
    "initial_payout": {
      "payout_type": "payout",
      "amount": 10,
      "currency": "USD"
    }
  }
}

Step 2: Building Campaign Paths

Paths are different reward scenarios. Each path has:

  • Conditions: What must be true (like "cart over $50")

  • Actions: What rewards they get (like "20% discount")

Basic Path Structure

{
  "paths": [
    {
      "conditions": {
        "logic": "AND",           // How to combine rules
        "rules": [               // Array of conditions
          {
            "field": "cart_value",
            "operator": ">=", 
            "value": 50
          }
        ]
      },
      "actions": [               // Array of rewards
        {
          "action": "discount",
          "discount_type": "percentage",
          "value": 20
        }
      ]
    }
  ]
}

Multiple Paths Example

{
  "paths": [
    {
      "conditions": {
        "logic": "AND",
        "rules": [
          {
            "field": "cart_value",
            "operator": ">=",
            "value": 100
          }
        ]
      },
      "actions": [
        {
          "action": "discount", 
          "discount_type": "percentage",
          "value": 30
        }
      ]
    },
    {
      "conditions": {
        "logic": "AND",
        "rules": [
          {
            "field": "cart_value",
            "operator": ">=", 
            "value": 50
          }
        ]
      },
      "actions": [
        {
          "action": "discount",
          "discount_type": "percentage", 
          "value": 20
        }
      ]
    }
  ]
}

How Multiple Paths Work:

  • Customers hit the FIRST path they qualify for

  • Order matters! Put highest requirements first

  • In the example above: $100+ gets 30% off, $50+ gets 20% off

Step 3: Building Conditions

Conditions determine when a path activates. You can check cart value, specific products, usage limits, and more.

Condition Structure

Every condition group has:

{
  "logic": "AND",    // or "OR" - how to combine rules
  "rules": [         // Array of individual conditions
    // conditions go here
  ]
}

Available Condition Types

Condition Type

Purpose

Example Use Case

cart_value

Check total cart amount

"Spend $50 for discount"

cart_items

Check number of items

"Buy 3+ items for deal"

products

Check specific products

"Buy these shoes for bonus"

usage_limit

Limit total campaign uses

"First 100 customers only"

user_limit

Limit per-person uses

"Once per customer"

referrer_count

Check referral history

"Referred 5+ people"

time_limit

Check current time

"Weekend special"

webhook

Custom external check

"VIP status verification"

1. Cart Value Conditions

Check if the customer's cart total meets requirements:

{
  "field": "cart_value",
  "operator": ">=",          // >=, <=, ==, >, <
  "value": 50,              // Dollar amount
  "currency": "USD"         // Optional, defaults to USD
}

Examples:

// Spend at least $50
{
  "field": "cart_value",
  "operator": ">=", 
  "value": 50
}

// Spend exactly $100
{
  "field": "cart_value",
  "operator": "==",
  "value": 100
}

// Spend less than $25
{
  "field": "cart_value", 
  "operator": "<",
  "value": 25
}

2. Cart Items Conditions

Check the number of items in the cart:

{
  "field": "cart_items",
  "operator": ">=",          // >=, <=, ==, >, <
  "value": 3                // Number of items
}

Examples:

// Buy 3 or more items
{
  "field": "cart_items",
  "operator": ">=",
  "value": 3
}

// Buy exactly 1 item
{
  "field": "cart_items",
  "operator": "==", 
  "value": 1
}

3. Products Conditions

Check if specific products are in the cart:

{
  "field": "products",
  "operator": "includes",                    // Always "includes"
  "value": [                                // Array of product UUIDs
    "550e8400-e29b-41d4-a716-446655440000",
    "123e4567-e89b-12d3-a456-426614174000"
  ]
}

Important Notes:

  • Product values MUST be UUIDs (not product names)

  • Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

  • Use actual product IDs from your database

❌ Common Product Condition Mistakes

// ❌ WRONG - Don't use product names
{
  "field": "products",
  "operator": "includes",
  "value": ["Nike Shoes", "iPhone", "Laptop"]  // Product names don't work
}

// ❌ WRONG - Invalid UUID format
{
  "field": "products", 
  "operator": "includes",
  "value": ["12345", "abc-def", "product_1"]   // Not valid UUIDs
}

// ✅ CORRECT - Use proper UUIDs
{
  "field": "products",
  "operator": "includes", 
  "value": [
    "550e8400-e29b-41d4-a716-446655440000",   // Valid UUID
    "123e4567-e89b-12d3-a456-426614174000"    // Valid UUID
  ]
}

4. Usage Limit Conditions

Limit how many times the campaign can be used total:

{
  "field": "usage_limit",
  "operator": "<",           // <, <=, ==, >=, >, !=
  "value": 100              // Number of total uses
}

Examples:

// First 100 customers only
{
  "field": "usage_limit",
  "operator": "<",
  "value": 100
}

// After 50 people have used it
{
  "field": "usage_limit", 
  "operator": ">=",
  "value": 50
}

5. User Limit Conditions

Limit how many times each person can use the campaign:

{
  "field": "user_limit",
  "operator": "<",           // <, <=, ==, >=, >, !=
  "value": 1                // Number of uses per person
}

Examples:

// Once per customer
{
  "field": "user_limit",
  "operator": "<",
  "value": 1
}

// After someone has used it 3 times
{
  "field": "user_limit",
  "operator": ">=", 
  "value": 3
}

6. Referrer Count Conditions

Check how many people someone has referred:

New Format (Recommended):

{
  "field": "referrer_count",
  "operator": ">=",
  "value": [5, "all_campaigns"]      // [count, scope]
}

Legacy Format (Still Supported):

{
  "field": "referrer_count", 
  "operator": ">=",
  "value": 5,
  "scope": "all_campaigns"           // or "campaign_specific"
}

Scope Options:

  • "all_campaigns": Count referrals across all campaigns

  • "campaign_specific": Count referrals only for this campaign

7. Time Limit Conditions

Make campaigns active only during specific times:

{
  "field": "time_limit",
  "time_start": "2024-12-01T00:00:00Z",    // ISO 8601 timestamp
  "time_end": "2024-12-31T23:59:59Z",      // ISO 8601 timestamp  
  "timezone": "America/New_York"           // Timezone name
}

Important Notes:

  • Timestamps must be in ISO 8601 format

  • Include the "T" and "Z" in timestamps

  • Use proper timezone names (like "America/New_York", "Europe/London")

❌ Common Time Condition Mistakes

// ❌ WRONG - Bad timestamp formats
{
  "field": "time_limit",
  "time_start": "2024-12-01",              // Missing time portion
  "time_end": "Dec 31, 2024",             // Not ISO 8601 format
  "timezone": "EST"                        // Use full timezone name
}

// ✅ CORRECT
{
  "field": "time_limit", 
  "time_start": "2024-12-01T00:00:00Z",    // Proper ISO 8601
  "time_end": "2024-12-31T23:59:59Z",      // Proper ISO 8601
  "timezone": "America/New_York"           // Full timezone name
}

8. Webhook Conditions

Use external services to check custom conditions:

{
  "field": "webhook",
  "url": "https://your-api.com/check-vip-status",
  "method": "POST",
  "headers": {
    "Authorization": "Bearer your-token"
  },
  "payload": {
    "customer_email": "{{customer.email}}"
  },
  "success_condition": "response.is_vip === true",
  "fallback_behavior": "fail"              // "pass", "fail", or "continue"
}

Combining Conditions with Logic

AND Logic - ALL conditions must be true:

{
  "logic": "AND",
  "rules": [
    {
      "field": "cart_value",
      "operator": ">=",
      "value": 50
    },
    {
      "field": "cart_items", 
      "operator": ">=",
      "value": 2
    }
  ]
}

This means: "Cart over $50 AND 2+ items"

OR Logic - ANY condition can be true:

{
  "logic": "OR",
  "rules": [
    {
      "field": "cart_value",
      "operator": ">=", 
      "value": 100
    },
    {
      "field": "user_limit",
      "operator": "<",
      "value": 1
    }
  ]
}

This means: "Cart over $100 OR first-time user"

Nested Conditions

You can create complex logic by nesting condition groups:

{
  "logic": "AND",
  "rules": [
    {
      "field": "cart_value",
      "operator": ">=",
      "value": 50
    },
    {
      "logic": "OR",                    // Nested group
      "rules": [
        {
          "field": "cart_items",
          "operator": ">=", 
          "value": 3
        },
        {
          "field": "products",
          "operator": "includes",
          "value": ["550e8400-e29b-41d4-a716-446655440000"]
        }
      ]
    }
  ]
}

This means: "Cart over $50 AND (3+ items OR specific product)"

❌ Common Condition Mistakes

// ❌ WRONG - Invalid field names
{
  "field": "total_amount",      // Use "cart_value"
  "field": "product_ids",       // Use "products"
  "field": "item_count",        // Use "cart_items"
}

// ❌ WRONG - Invalid operators
{
  "field": "cart_value",
  "operator": "greater_than",   // Use ">=" 
  "operator": "equals",         // Use "=="
}

// ❌ WRONG - Invalid logic
{
  "logic": "XOR",              // Use "AND" or "OR" only
  "logic": "NOT"               // Use "AND" or "OR" only
}

// ❌ WRONG - Negative values where not allowed
{
  "field": "cart_value",
  "operator": ">=",
  "value": -10                 // Cart value must be positive
}

{
  "field": "usage_limit", 
  "operator": "<",
  "value": -5                  // Usage limit must be non-negative
}

Step 4: Building Actions

Actions are the rewards customers get when they meet the conditions. Each path can have multiple actions that all execute together.

Action Structure

Actions are always an array (list) and execute with AND logic only:

{
  "actions": [
    {
      "action": "discount",
      "discount_type": "percentage",
      "value": 20
    },
    {
      "action": "commission",
      "commission_type": "fixed",
      "value": 5,
      "payout_type": "direct_payout",
      "currency": "USD"
    }
  ]
}

Available Action Types

Action Type

Purpose

Example Use Case

discount

Give customer discounts

"20% off your order"

commission

Pay rewards to advocates

"Earn $5 commission"

shipping

Shipping discounts

"Free shipping"

bogo

Buy-one-get-one deals

"Buy 2, get 1 free"

webhook

Trigger external actions

"Send to email system"

1. Discount Actions

Give customers money off their orders:

{
  "action": "discount",
  "discount_type": "percentage",     // "percentage" or "fixed"
  "value": 20,                      // Percentage (0-100) or dollar amount
  "currency": "USD",                // Required for fixed discounts
  "max_amount": 50                  // Optional cap for percentage discounts
}

Percentage Discounts:

// 20% off
{
  "action": "discount",
  "discount_type": "percentage",
  "value": 20
}

// 15% off, max $30 discount
{
  "action": "discount", 
  "discount_type": "percentage",
  "value": 15,
  "max_amount": 30
}

Fixed Discounts:

// $10 off
{
  "action": "discount",
  "discount_type": "fixed",
  "value": 10,
  "currency": "USD"                 // Required for fixed discounts
}

❌ Common Discount Mistakes

// ❌ WRONG - Invalid percentage values
{
  "action": "discount",
  "discount_type": "percentage", 
  "value": 150                      // Must be 0-100
}

// ❌ WRONG - Missing currency for fixed discount
{
  "action": "discount",
  "discount_type": "fixed",
  "value": 10                       // Missing "currency" field
}

// ❌ WRONG - Invalid currency codes
{
  "action": "discount",
  "discount_type": "fixed",
  "value": 10,
  "currency": "dollars"             // Use "USD", not "dollars"
}

// ❌ WRONG - Negative values
{
  "action": "discount",
  "discount_type": "percentage",
  "value": -20                      // Must be positive
}

2. Commission Actions

Pay rewards to advocates (people who refer customers):

{
  "action": "commission",
  "commission_type": "percentage",   // "percentage" or "fixed"
  "value": 5,                      // Percentage (0-100) or dollar amount
  "payout_type": "direct_payout",   // "direct_payout" or "redeemable"
  "currency": "USD"                 // Required for fixed commissions
}

Payout Types:

  • "direct_payout": Real money sent to advocate

  • "redeemable": Store credit/points for advocate

Examples:

// 5% commission as real money
{
  "action": "commission",
  "commission_type": "percentage",
  "value": 5,
  "payout_type": "direct_payout"
}

// $3 fixed commission as store credit
{
  "action": "commission",
  "commission_type": "fixed", 
  "value": 3,
  "payout_type": "redeemable",
  "currency": "USD"
}

3. Shipping Actions

Give shipping discounts or free shipping:

{
  "action": "shipping",
  "discount_type": "free",          // "free", "percentage", or "fixed"  
  "value": 0,                      // 0 for free, percentage, or dollar amount
  "currency": "USD"                 // Required for fixed discounts
}

Shipping Types:

// Free shipping
{
  "action": "shipping",
  "discount_type": "free",
  "value": 0                        // or 100
}

// 50% off shipping
{
  "action": "shipping",
  "discount_type": "percentage", 
  "value": 50
}

// $5 off shipping
{
  "action": "shipping",
  "discount_type": "fixed",
  "value": 5,
  "currency": "USD"
}

4. BOGO Actions (Buy-One-Get-One)

Complex deals where customers buy certain items and get others free or discounted:

{
  "action": "bogo",
  "buy_config": {
    "buy_quantity": 2,               // How many to buy
    "eligible_products": {
      "type": "any_products"         // What products count
    }
  },
  "get_config": {
    "get_quantity": 1,               // How many they get
    "eligible_products": {
      "type": "same_products"        // What they get
    },
    "discount_config": {
      "discount_type": "percentage",
      "discount_value": 100          // 100% = free
    }
  }
}

Product Selection Types:

  1. Any Products:

{
  "type": "any_products",
  "exclude_product_ids": ["uuid1", "uuid2"],    // Optional exclusions
  "include_categories": ["shoes", "clothing"],   // Optional category filter
  "min_price": 25,                              // Optional minimum price
  "max_price": 100                              // Optional maximum price
}
  1. Same Products:

{
  "type": "same_products"          // Get same products they bought
}
  1. Specific Products:

{
  "type": "specific_products",
  "product_ids": [                 // Exact product UUIDs
    "550e8400-e29b-41d4-a716-446655440000",
    "123e4567-e89b-12d3-a456-426614174000"
  ],
  "allow_variants": false          // Include product variants
}

BOGO Examples:

// Buy 2, get 1 free (same products)
{
  "action": "bogo",
  "buy_config": {
    "buy_quantity": 2,
    "eligible_products": {
      "type": "any_products"
    }
  },
  "get_config": {
    "get_quantity": 1,
    "eligible_products": {
      "type": "same_products"
    },
    "discount_config": {
      "discount_type": "percentage",
      "discount_value": 100
    }
  }
}

// Buy shoes, get 50% off socks
{
  "action": "bogo",
  "buy_config": {
    "buy_quantity": 1,
    "eligible_products": {
      "type": "specific_products",
      "product_ids": ["shoe-uuid-here"]
    }
  },
  "get_config": {
    "get_quantity": 1,
    "eligible_products": {
      "type": "specific_products", 
      "product_ids": ["sock-uuid-here"]
    },
    "discount_config": {
      "discount_type": "percentage",
      "discount_value": 50,
      "currency": "USD"
    }
  }
}

5. Webhook Actions

Trigger external systems when actions execute:

{
  "action": "webhook",
  "url": "https://your-system.com/reward-notification",
  "method": "POST",
  "headers": {
    "Authorization": "Bearer your-token",
    "Content-Type": "application/json"
  },
  "payload": {
    "customer_email": "{{customer.email}}",
    "reward_amount": "{{action.value}}",
    "campaign_name": "{{campaign.name}}"
  },
  "success_condition": "response.status === 'success'",
  "fallback_behavior": "continue"        // "continue" or "stop"
}

Available Variables:

  • {{customer.email}} - Customer's email

  • {{advocate.handle}} - Advocate's username

  • {{campaign.name}} - Campaign name

  • {{action.value}} - Action value

❌ Common Action Mistakes

// ❌ WRONG - Using OR logic for actions
{
  "actions": {
    "logic": "OR",                  // Actions don't support OR logic
    "rules": [
      {"action": "discount", ...},
      {"action": "commission", ...}
    ]
  }
}

// ❌ WRONG - Nesting actions like conditions
{
  "actions": [
    {
      "rules": [                    // Actions don't have rules
        {"action": "discount", ...}
      ]
    }
  ]
}

// ❌ WRONG - Duplicate action types in same path
{
  "actions": [
    {"action": "discount", "discount_type": "percentage", "value": 10},
    {"action": "discount", "discount_type": "fixed", "value": 5}  // Can't have 2 discounts
  ]
}

// ✅ CORRECT - Actions as simple array
{
  "actions": [
    {
      "action": "discount",
      "discount_type": "percentage", 
      "value": 20
    },
    {
      "action": "commission",
      "commission_type": "fixed",
      "value": 5,
      "payout_type": "direct_payout",
      "currency": "USD"  
    }
  ]
}

Step 5: Switch Logic (Optional)

Switch logic determines how customers are routed between multiple paths. Most campaigns don't need custom switch logic.

Default Behavior (Recommended)

If you don't specify switch logic, the system uses priority order:

  • Customers hit the FIRST path they qualify for

  • Order your paths from most specific to least specific

  • Put highest requirements first

Manual Switch Configuration

Only add this if you need custom routing:

{
  "switch": {
    "type": "priority_order"        // Only option currently supported
  }
}

When Multiple Paths Are Required

The validation service automatically requires switch logic when you have multiple paths:

{
  "start": { ... },
  "switch": {                       // Required with multiple paths
    "type": "priority_order"
  },
  "paths": [
    { ... },                        // Path 1: Most specific requirements
    { ... },                        // Path 2: Less specific requirements  
    { ... }                         // Path 3: Least specific requirements
  ]
}

❌ Common Switch Logic Mistakes

// ❌ WRONG - Multiple paths without switch logic
{
  "start": { ... },
  "paths": [                        // Multiple paths require switch logic
    { ... },
    { ... }
  ]
  // Missing "switch" field
}

// ❌ WRONG - Switch logic with single path
{
  "start": { ... },
  "switch": {                       // Not needed with single path
    "type": "priority_order"
  },
  "paths": [
    { ... }                         // Only one path
  ]
}

// ✅ CORRECT - Single path (no switch needed)
{
  "start": { ... },
  "paths": [
    { ... }
  ]
}

// ✅ CORRECT - Multiple paths (switch required)
{
  "start": { ... },
  "switch": {
    "type": "priority_order"
  },
  "paths": [
    { ... },
    { ... }
  ]
}

Step 6: Testing Your Campaign JSON

Using the Validation Service

The validation service checks your campaign JSON and tells you exactly what's wrong:

import { validateCampaign } from '@/features/campaign-management/services/validation';

const result = validateCampaign(yourCampaignJSON);

if (!result.isValid) {
  console.log('Errors found:');
  result.errors.forEach(error => {
    console.log(`- ${error.message}`);
  });
} else {
  console.log('Campaign is valid!');
}

Validation Result Structure

{
  isValid: true/false,              // Overall validation result
  errors: [                        // Critical issues that prevent execution
    {
      code: 'MISSING_START',
      message: 'Campaign must have a start configuration',
      severity: 'error'
    }
  ],
  warnings: [                      // Non-critical issues
    {
      code: 'DEEP_CONDITION_NESTING',
      message: 'Condition nesting is 4 levels deep. Consider simplifying for better performance.',
      severity: 'warning'
    }
  ],
  summary: {                       // Campaign statistics
    totalPaths: 2,
    totalConditions: 5,
    totalActions: 3,
    duplicateConditions: [],
    switchUsage: true,
    structureValid: true
  }
}

Common Validation Errors

Error Code

Problem

Solution

MISSING_START

No start configuration

Add required start fields

MISSING_APPLIES_TO

No applies_to specified

Set applies_to to "everyone" or advocate codes

INVALID_CONDITION_FIELD

Unknown condition field

Use valid fields: cart_value, cart_items, products, etc.

INVALID_ACTION_TYPE

Unknown action type

Use valid actions: discount, commission, shipping, bogo, webhook

MISSING_REQUIRED_SWITCH

Multiple paths without switch

Add switch logic for multiple paths

UNNECESSARY_SWITCH

Switch with single path

Remove switch logic for single path

INVALID_PRODUCT_ID

Invalid UUID format

Use proper UUID format for product IDs

INVALID_PERCENTAGE_DISCOUNT

Percentage not 0-100

Keep percentages between 0 and 100

Complete Working Examples

Example 1: Simple Discount Campaign

{
  "start": {
    "campaign_name": "Welcome Discount", 
    "campaign_slug": "welcome-discount",
    "display_name": "🎉 Welcome! Get 15% Off",
    "description": "New customers get 15% off orders over $30",
    "applies_to": "everyone"
  },
  "paths": [
    {
      "conditions": {
        "logic": "AND",
        "rules": [
          {
            "field": "cart_value",
            "operator": ">=",
            "value": 30
          },
          {
            "field": "user_limit", 
            "operator": "<",
            "value": 1
          }
        ]
      },
      "actions": [
        {
          "action": "discount",
          "discount_type": "percentage",
          "value": 15
        }
      ]
    }
  ]
}

Example 2: Tiered Discount Campaign

{
  "start": {
    "campaign_name": "VIP Tiered Discounts",
    "campaign_slug": "vip-tiered-discounts", 
    "display_name": "🌟 VIP Discounts - Spend More, Save More!",
    "description": "Get bigger discounts with larger orders",
    "applies_to": ["azim", "lucas"],
    "initial_payout": {
      "payout_type": "payout",
      "amount": 5,
      "currency": "USD"
    }
  },
  "switch": {
    "type": "priority_order"
  },
  "paths": [
    {
      "conditions": {
        "logic": "AND",
        "rules": [
          {
            "field": "cart_value",
            "operator": ">=", 
            "value": 200
          }
        ]
      },
      "actions": [
        {
          "action": "discount",
          "discount_type": "percentage",
          "value": 25
        },
        {
          "action": "commission",
          "commission_type": "fixed",
          "value": 10,
          "payout_type": "direct_payout",
          "currency": "USD"
        }
      ]
    },
    {
      "conditions": {
        "logic": "AND",
        "rules": [
          {
            "field": "cart_value",
            "operator": ">=",
            "value": 100
          }
        ]
      },
      "actions": [
        {
          "action": "discount", 
          "discount_type": "percentage",
          "value": 20
        },
        {
          "action": "commission",
          "commission_type": "fixed",
          "value": 5,
          "payout_type": "direct_payout", 
          "currency": "USD"
        }
      ]
    },
    {
      "conditions": {
        "logic": "AND",
        "rules": [
          {
            "field": "cart_value",
            "operator": ">=",
            "value": 50
          }
        ]
      },
      "actions": [
        {
          "action": "discount",
          "discount_type": "percentage", 
          "value": 15
        }
      ]
    }
  ]
}

Example 3: Product-Specific BOGO Campaign

{
  "start": {
    "campaign_name": "Shoe Sale BOGO",
    "campaign_slug": "shoe-sale-bogo",
    "display_name": "👟 Buy 2 Shoes, Get 1 Free!",
    "description": "Buy any 2 shoes and get the cheapest one free",
    "applies_to": "everyone",
    "start_date": "2024-12-01T00:00:00Z",
    "end_date": "2024-12-31T23:59:59Z"
  },
  "paths": [
    {
      "conditions": {
        "logic": "AND",
        "rules": [
          {
            "field": "products",
            "operator": "includes",
            "value": [
              "550e8400-e29b-41d4-a716-446655440000",
              "123e4567-e89b-12d3-a456-426614174000",
              "987fcdeb-51d3-11d4-a716-446655440000"
            ]
          },
          {
            "field": "cart_items",
            "operator": ">=",
            "value": 2
          }
        ]
      },
      "actions": [
        {
          "action": "bogo",
          "buy_config": {
            "buy_quantity": 2,
            "eligible_products": {
              "type": "specific_products",
              "product_ids": [
                "550e8400-e29b-41d4-a716-446655440000",
                "123e4567-e89b-12d3-a456-426614174000", 
                "987fcdeb-51d3-11d4-a716-446655440000"
              ]
            }
          },
          "get_config": {
            "get_quantity": 1,
            "eligible_products": {
              "type": "same_products"
            },
            "discount_config": {
              "discount_type": "percentage",
              "discount_value": 100
            }
          }
        }
      ]
    }
  ]
}

Example 4: Time-Limited Referral Campaign

{
  "start": {
    "campaign_name": "Weekend Referral Bonus",
    "campaign_slug": "weekend-referral-bonus",
    "display_name": "🎯 Weekend Special - Refer Friends & Earn!",
    "description": "This weekend only: Refer friends and earn extra rewards",
    "applies_to": "everyone"
  },
  "paths": [
    {
      "conditions": {
        "logic": "AND",
        "rules": [
          {
            "field": "time_limit",
            "time_start": "2024-12-14T00:00:00Z",
            "time_end": "2024-12-15T23:59:59Z", 
            "timezone": "America/New_York"
          },
          {
            "field": "referrer_count",
            "operator": ">=",
            "value": [3, "all_campaigns"]
          },
          {
            "field": "cart_value",
            "operator": ">=",
            "value": 75
          }
        ]
      },
      "actions": [
        {
          "action": "discount",
          "discount_type": "percentage",
          "value": 30
        },
        {
          "action": "commission",
          "commission_type": "percentage",
          "value": 10,
          "payout_type": "direct_payout"
        },
        {
          "action": "shipping",
          "discount_type": "free",
          "value": 0
        }
      ]
    }
  ]
}

Performance Best Practices

Optimize for Speed

  1. Keep paths simple: Fewer conditions = faster evaluation

  2. Order paths efficiently: Most likely matches first

  3. Limit nesting: Avoid deeply nested condition groups

  4. Use specific conditions: More specific = faster elimination

Avoid Performance Issues

// ❌ SLOW - Too many nested conditions
{
  "logic": "AND",
  "rules": [
    {
      "logic": "OR",
      "rules": [
        {
          "logic": "AND", 
          "rules": [
            // 4+ levels deep is slow
          ]
        }
      ]
    }
  ]
}

// ✅ FAST - Simple, flat structure
{
  "logic": "AND",
  "rules": [
    {
      "field": "cart_value",
      "operator": ">=",
      "value": 50
    },
    {
      "field": "user_limit",
      "operator": "<", 
      "value": 1
    }
  ]
}

Limit Campaign Complexity

  • Maximum paths: 10 paths per campaign

  • Maximum nesting: 3 levels deep

  • Maximum conditions per path: 10 conditions

  • Maximum actions per path: 5 actions

Security Considerations

Data Validation

The validation service automatically protects against:

  • SQL injection: All inputs are sanitized

  • XSS attacks: HTML content is escaped

  • Invalid data: Type checking prevents errors

  • Malicious payloads: Webhook validation

Safe Practices

  1. Use UUIDs for products: Never use product names or user input

  2. Validate webhook URLs: Only use trusted external services

  3. Limit permissions: Use least privilege for API access

  4. Monitor usage: Track campaign performance and usage

❌ Security Mistakes to Avoid

// ❌ DANGEROUS - Don't use user input directly
{
  "field": "products",
  "operator": "includes", 
  "value": ["<script>alert('xss')</script>"]  // Malicious input
}

// ❌ DANGEROUS - Don't use untrusted webhooks
{
  "action": "webhook",
  "url": "http://malicious-site.com/steal-data"  // Untrusted URL
}

// ✅ SAFE - Use validated UUIDs and trusted URLs
{
  "field": "products",
  "operator": "includes",
  "value": ["550e8400-e29b-41d4-a716-446655440000"]  // Valid UUID
}

{
  "action": "webhook", 
  "url": "https://your-trusted-api.com/endpoint"  // Your trusted system
}

Troubleshooting Common Issues

Campaign Not Working

  1. Check validation errors: Run validation first

  2. Verify product UUIDs: Ensure they exist in your database

  3. Test conditions: Start with simple conditions

  4. Check path order: Most specific requirements first

Performance Issues

  1. Simplify conditions: Reduce nesting and complexity

  2. Optimize path order: Most likely matches first

  3. Monitor usage: Check for bottlenecks

  4. Limit scope: Target specific user groups

Debugging Tips

// Enable detailed logging
const result = validateCampaign(campaign, {
  includeWarnings: true,
  strictMode: true
});

console.log('Validation Summary:', result.summary);
console.log('Performance Estimate:', result.performanceEstimate);

Help

Validation Service Functions

// Quick validation
const isValid = isCampaignValid(campaign);

// Get only errors
const errors = getCampaignValidationErrors(campaign);

// Get detailed analysis
const analysis = generateCampaignAnalysis(campaign);

// Batch validation
const batchResults = validateCampaignBatch([campaign1, campaign2]);

Support Resources

  1. Validation Service: Automatic error detection and suggestions

  2. Type Definitions: TypeScript types for all campaign structures

  3. Example Templates: Working examples for common use cases

  4. Performance Monitoring: Built-in optimization recommendations

Remember: The validation service is your friend! It will catch mistakes and guide you to working campaign JSONs. Always run validation before deploying campaigns.