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 |
|---|---|---|---|
|
|
string |
Any descriptive name |
"Black Friday 2024" |
|
|
string |
URL-safe, no spaces |
"black-friday-2024" |
|
|
string |
Customer-facing title |
"🛍️ Black Friday - 50% Off!" |
|
|
string |
Clear explanation |
"Get 50% off everything during Black Friday" |
|
|
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 |
|---|---|---|
|
|
Check total cart amount |
"Spend $50 for discount" |
|
|
Check number of items |
"Buy 3+ items for deal" |
|
|
Check specific products |
"Buy these shoes for bonus" |
|
|
Limit total campaign uses |
"First 100 customers only" |
|
|
Limit per-person uses |
"Once per customer" |
|
|
Check referral history |
"Referred 5+ people" |
|
|
Check current time |
"Weekend special" |
|
|
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 |
|---|---|---|
|
|
Give customer discounts |
"20% off your order" |
|
|
Pay rewards to advocates |
"Earn $5 commission" |
|
|
Shipping discounts |
"Free shipping" |
|
|
Buy-one-get-one deals |
"Buy 2, get 1 free" |
|
|
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:
-
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
}
-
Same Products:
{
"type": "same_products" // Get same products they bought
}
-
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 |
|---|---|---|
|
|
No start configuration |
Add required start fields |
|
|
No applies_to specified |
Set applies_to to "everyone" or advocate codes |
|
|
Unknown condition field |
Use valid fields: cart_value, cart_items, products, etc. |
|
|
Unknown action type |
Use valid actions: discount, commission, shipping, bogo, webhook |
|
|
Multiple paths without switch |
Add switch logic for multiple paths |
|
|
Switch with single path |
Remove switch logic for single path |
|
|
Invalid UUID format |
Use proper UUID format for product IDs |
|
|
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
-
Keep paths simple: Fewer conditions = faster evaluation
-
Order paths efficiently: Most likely matches first
-
Limit nesting: Avoid deeply nested condition groups
-
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
-
Use UUIDs for products: Never use product names or user input
-
Validate webhook URLs: Only use trusted external services
-
Limit permissions: Use least privilege for API access
-
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
-
Check validation errors: Run validation first
-
Verify product UUIDs: Ensure they exist in your database
-
Test conditions: Start with simple conditions
-
Check path order: Most specific requirements first
Performance Issues
-
Simplify conditions: Reduce nesting and complexity
-
Optimize path order: Most likely matches first
-
Monitor usage: Check for bottlenecks
-
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
-
Validation Service: Automatic error detection and suggestions
-
Type Definitions: TypeScript types for all campaign structures
-
Example Templates: Working examples for common use cases
-
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.