📖 Campaign Documentation

Page Description
Overview Module overview, workflows, and high-level architecture
Models & Constants Database models, enums, and default templates
Routes API endpoints, request/response formats, and examples
Service Business logic functions and integration points
Schemas Validation schemas and data structures

Overview

The Campaign module empowers merchants to create, manage, and deliver WhatsApp message templates ("campaigns") to their customers and internal merchant–users.
It encapsulates every step of the life-cycle – from authoring a template, submitting it to Twilio for approval, all the way to personalising and sending the message plus recording engagement metrics.

Cosmo supports two broad classes of campaigns:

  • Marketing – one-off or scheduled broadcasts that are subject to WhatsApp marketing rules.
  • Service / Utility – transactional or conversational messages (order updates, support tickets, etc.).

Internally a campaign is a versioned template – each update produces a new Campaign record while the previous version is linked via next_campaign_id.

High-level Responsibilities

  1. Template Authoring & Validation
  2. Validates content against Twilio requirements (see schemas.md).
  3. Extracts & validates variables ({{lead_name}}, {{1}}, …) with find_and_validate_variables().
  4. Storage & Versioning – persists the template plus variable map to the DB (Campaign, CampaignLead, CampaignLeadMessage).
  5. Twilio Content API integration – creates/updates the corresponding Content SID so WhatsApp can render the template.
  6. Lead Management – stores who the template should be sent to and any per-lead custom variables.
  7. Sending – hydrates variables, sends with Twilio, records message IDs & delivery state.
  8. Reporting – calculates reply & conversion rates exposed through CampaignSchema.
  9. Campaign State Management – enables/disables campaigns for message sending and service automation.
  10. Type-based Filtering – supports filtering campaigns by type (marketing vs service) for organized management.

WhatsApp Message Types

WhatsApp enforces strict rules about message categories that determine when and how templates can be sent:

Marketing Campaigns

  • Purpose: Promotional content, announcements, newsletters
  • Restrictions:
  • Can only be sent to users who have opted in within the last 24 hours
  • Subject to WhatsApp's marketing message limits
  • Require explicit user consent
  • Current Behavior: All merchant-created campaigns are automatically categorized as marketing
  • Examples: Product launches, sales announcements, weekly newsletters

Service/Utility Campaigns

  • Purpose: Transactional updates, account notifications, customer service
  • Advantages:
  • Can be sent anytime without the 24-hour opt-in window
  • Higher sending limits
  • No explicit consent required for legitimate business updates
  • Current Behavior:
  • All system-created default templates are service type
  • Merchants can update existing service templates but cannot create new ones
  • Examples: Order confirmations, shipping updates, password resets, support responses

This distinction is enforced by Twilio/WhatsApp and impacts deliverability and compliance.


Campaign State Management

All campaigns have an enabled field that controls their operational state:

Enable/Disable Behavior

Enabled State (enabled = <timestamp>): - Marketing Campaigns: Can send messages via UI and API endpoints - Service Campaigns: Automatic service messages are triggered by events (order confirmations, stock alerts, etc.) - UI Indicators: Shows green circle next to campaign name in frontend

Disabled State (enabled = NULL): - Marketing Campaigns: Cannot send messages; play button disabled in UI - Service Campaigns: Automatic service messages are blocked; events don't trigger sends - UI Indicators: No green circle shown; pause button disabled

State Management Endpoints

Endpoint Purpose Effect
POST /enable Enable campaign Sets enabled = datetime.now()
POST /pause Disable campaign Sets enabled = NULL
POST /send?enable=true Send with auto-enable Enables campaign before sending (marketing only)

Use Cases

Marketing Campaigns: - Merchants manually enable campaigns when ready to send promotional content - Disabled by default to prevent accidental sends - Can be enabled temporarily for specific sends

Service Campaigns: - Merchants can pause service automation without deleting templates - Useful during maintenance, system updates, or when customizing service flows - Enables granular control over which service messages are active


Campaign Type Filtering

The module supports filtering campaigns by type for better organization:

Frontend Filtering

  • Default View: Shows "Marketing Campaigns" by default
  • Dropdown Toggle: Clickable title with chevron to switch between types
  • Separate Lists: Marketing and service campaigns are shown separately
  • Auto-Selection: First campaign is automatically selected when switching types

API Filtering

  • Query Parameter: GET /campaign/?campaign_type=marketing|service
  • Combined Filtering: Works with search, pagination, and other filters
  • Type Validation: Invalid campaign types return 400 error

Benefits

  • Reduced Clutter: Merchants see only relevant campaigns for their current task
  • Clear Separation: Prevents confusion between promotional and transactional messages
  • Workflow Optimization: Different campaign types often have different management workflows

Background Jobs Integration

The Campaign module integrates with SAQ (Simple Async Queue) background jobs for template approval monitoring:

Template Status Monitoring

  • update_message_template_status – Runs every 2 minutes, polls Twilio for status updates on pending/unsubmitted campaigns
  • update_message_template_status_approved – Runs at minutes 5 and 35, specifically monitors already-approved templates for any status changes

Approval Workflow

graph TD
    A[Campaign Created] --> B[Status: unsubmitted]
    B --> C[Background Job Polls Twilio]
    C --> D{Twilio Response}
    D -->|Approved| E[Status: approved<br/>Ready to Send]
    D -->|Rejected| F[Status: rejected<br/>+ rejection_reason]
    D -->|Still Processing| G[Status: pending<br/>Continue Polling]
    G --> C

Critical: Campaigns cannot be sent until status = "approved". The sending functions check this status and will log warnings for non-approved sends (though Twilio will likely reject them anyway).


Campaign Leads as Queue & Historical Record

CampaignLead serves a dual purpose in the system:

1. Target Queue Management

  • Pre-population: Merchants add leads via /add-leads before sending
  • Bulk Operations: send_campaign_messages() processes all active = True leads
  • Soft Deletion: Leads can be deactivated (active = False) without losing historical data
  • Custom Variables: Each lead can have personalized variables that override defaults

2. Historical Sending Record

  • Permanent Audit Trail: Every person who has ever received a campaign version remains in the database
  • Marketing Compliance: Ensures one-time sends for marketing campaigns by checking existing CampaignLeadMessage records
  • Analytics Foundation: Powers reply rates, conversion tracking, and engagement metrics
  • Cross-Campaign Insights: Tracks customer journey across multiple campaign touchpoints

Lead Lifecycle Example

graph LR
    A[Lead Added] --> B[Active: true]
    B --> C[Message Sent]
    C --> D[CampaignLeadMessage Created]
    D --> E[Lead Remains in DB]
    E --> F[Analytics & Compliance]

Even if a lead is later deactivated, their historical engagement data persists for reporting and compliance purposes.


Source Files

File Purpose
models.py Database entities & enums (campaign, lead, message, status, type…).
service.py Business logic: validation, Twilio integration, sending, default templates.
routes.py FastAPI routes that expose the module.
schemas.py Pydantic models used by both API and internal validation.

Typical Workflow

graph TD
    A[POST /campaign/create] --> B(create_message_template)
    B --> C{Twilio OK?}
    C -- yes --> D[Campaign.status = unsubmitted]
    C -- error --> E[Campaign.status = rejected]
    D --> F[Background Job Polls Status]
    F --> G[Campaign.status = approved]
    G --> H[POST /campaign/add-leads]
    H --> I[POST /campaign/send]
    I --> J(send_campaign_messages) --> K[Twilio delivery]

Detailed explanations of each step are provided in Service and Routes.


  • Conversation – owns the actual WhatsApp chat and message history.
  • Merchant / MerchantUser – producers & internal recipients of certain campaigns.
  • Order / Product – supply dynamic variables such as {{order_id}}, {{product_name}}.
  • SAQ – background job system that monitors template approval status.

Further Reading