Campaigns

Creating Campaigns

Campaigns are multi-step cold email sequences that automatically send to your leads based on schedules, conditions, and sender rotation rules. This guide walks you through creating your first campaign.

Prerequisites

Creating a Campaign (Dashboard)

1

Navigate to Campaigns

From the dashboard sidebar, click CampaignsNew Campaign.

2

Configure campaign settings

Set the following:

  • Name — Internal name for your reference
  • Status — Start as "Draft" to configure before launching
  • Check Reply — Stop sequence if lead replies (recommended: ON)
  • Track Opens — Insert invisible pixel for open tracking
  • Track Clicks — Wrap links for click tracking
3

Attach lead lists

Select one or more lead lists to target. Only leads that are not unsubscribed and have valid emails will receive messages.

4

Assign senders

Select the sender accounts (mailboxes) to use. Cleanmails automatically rotates between them using reputation-weighted selection.

5

Build your sequence steps

Add one or more email steps. Each step has:

  • Subjects — One or more subject lines (for A/B testing)
  • Body — HTML email content with personalization tags
  • Wait Days/Hours — Delay before sending this step (after previous step)
  • Trigger Condition — When to send: always, on_open, on_click, not_opened
6

Set schedule (optional)

Configure sending windows to only send during business hours:

Schedule Config Example
{
  "days": [1, 2, 3, 4, 5],
  "start": "09:00",
  "end": "17:00",
  "timezone": "America/New_York"
}

Days are 0-6 (Sunday=0, Monday=1, etc.). Overnight schedules like 22:00 to 06:00 are supported.

7

Launch

Set status to "running" and optionally set a Launch At date for delayed start. The campaign will begin processing leads immediately (or at the scheduled time).

Creating via API

bash
curl -X POST http://YOUR_SERVER/v1/outreach/campaigns \
  -H "Content-Type: application/json" \
  -H "Cookie: auth_token=YOUR_SESSION" \
  -d '{
    "name": "Q2 Outreach",
    "status": "running",
    "check_reply": true,
    "track_opens": true,
    "track_clicks": true,
    "schedule_config": "{\"days\":[1,2,3,4,5],\"start\":\"09:00\",\"end\":\"17:00\",\"timezone\":\"UTC\"}",
    "lists": [{"id": 1}],
    "senders": [{"id": 1}, {"id": 2}],
    "steps": [
      {
        "position": 0,
        "subjects": "[\"Hey {{FIRST_NAME}}, quick question\", \"{{FIRST_NAME}} — saw your work at {{COMPANY}}\"]",
        "body": "<p>Hi {{FIRST_NAME}},</p><p>{I noticed|I saw} your work at {{COMPANY}}...</p>",
        "wait_days": 0,
        "trigger_condition": "always"
      },
      {
        "position": 1,
        "subjects": "[\"Following up\"]",
        "body": "<p>Hey {{FIRST_NAME}}, just bumping this to the top...</p>",
        "wait_days": 3,
        "trigger_condition": "not_opened"
      }
    ]
  }'

Campaign Lifecycle

StatusBehavior
draftNot processing — safe to edit
runningActively sending to leads per schedule
pausedStopped — can be resumed
completedAll leads processed through all steps
Auto-completion

Campaigns automatically move to "completed" when all leads have been processed through the final step and no retries are pending.

Auto-pause on high bounce rate

If hard bounce rate exceeds 5%, the campaign is automatically paused to protect sender reputation. Fix your list quality before resuming.

How Sending Works

The outreach worker runs every 5 seconds and:

  1. Finds all campaigns with status "running" that are within their schedule window
  2. For each campaign, checks which leads need the next step
  3. Assigns senders using reputation-weighted rotation (healthier senders get more sends)
  4. Respects daily limits per sender and per-domain rate limits (e.g., 2/sec for Gmail)
  5. Processes spintax, personalization, and AI tags
  6. Signs with DKIM, wraps tracking links, adds unsubscribe footer
  7. Sends via the sender's SMTP credentials
  8. Logs the delivery and emits events for webhooks/CRM sync