phase 3 · act
Campaigns
Go deeper
A campaign is one run of one playbook, with its sequence, on one segment, inside a window. It has an offer, a stop rule, arms and a holdout. This page defines the campaign as an object, lists 14 presets a solo founder can run, and sets out what every finished campaign leaves behind in the log.
lead · who to reach → playbook · the strategy → sequence · the steps → campaign · one run of them → funnel · what it produced
One playbook per campaign — Two playbooks on the same people at once means you can't tell which one worked.
Window and stop rule set first — Decide when it ends and what failure looks like before the first message goes out.
A holdout whenever you can — A slice of the segment that gets nothing is the only way to know what the campaign caused.
in industry terms
A campaign is an instance. The playbook and the sequence are the templates.
Sales and marketing tools use the same split. The playbook is the strategy you reuse; the sequence (sales tools also call it a cadence) is the ordered list of steps; the campaign is the dated run of both against real people, which is where results come from.
template
Playbook
When this trigger fires, use this channel and this offer, and stop at this result.
- reused
- across products and months
- example
- Community answers
template
Sequence
The steps in order: wait, channel, action, message template, who sends it, exit rule.
- reused
- across playbooks
- example
- reply → follow-up → DM on request
instance
Campaign
One playbook and one sequence, on one segment, from a start date to a stop rule, split into arms.
- reused
- never; presets are reused
- example
- Reddit pain-reply sprint, Oct 20 to Nov 3
| Question | Playbook | Sequence | Campaign |
|---|---|---|---|
| What it answers | what to do when this trigger fires | which steps, in what order | who, when, with which offer, and did it work |
| Has a date | no | no | yes: a start, a window and a readout date |
| Has people in it | no | no | yes: a segment, split into arms |
| Produces results | only through campaigns | only through campaigns | yes: counts per step, per arm |
| Versioned | yes | yes | pins the playbook and sequence versions it ran |
the campaign object
Every campaign is one record with the same fields.
Fill every field before launch. A campaign with no stop rule or no readout date runs until you forget it, and you learn nothing from it.
| Field | Type | What it holds |
|---|---|---|
campaign_id | string | Stable and readable: camp.<preset>.<yyyy-mm-dd>. Every touch, signup and payment it causes carries it. |
preset | preset id | Which entry in the library below it was started from, if any. |
playbook | id + version | The one playbook it runs, pinned to the version at launch. |
sequence | id + version | The steps it runs, pinned the same way. A change mid-run starts a new campaign. |
segment | rule | Who is eligible: tiers, triggers, sources, freshness, and the ICP's "not if" lines. |
offer | text | What the person gets for saying yes: a brief, a trial, a price, early access. |
goal_metric | metric id | The one number that decides it, defined once: waitlist joins per offer, trials per touch. |
guardrails | metric ids | What must not get worse: stop requests, spam reports, founder minutes. |
window | start, end | When it runs. Short windows (one to three weeks) give faster readouts. |
stop_rule | rule | When to end early, written as a count: "40 offers made and 0 joins". |
arms | list of {name, share} | The variants and their shares of the segment: offer A, offer B, holdout. |
holdout_share | 0 to 1 | The share of eligible people who get nothing. 0 only when withholding is wrong (money owed) or the audience is public. |
assignment | per lead | Each lead's arm and the probability it had of landing there, logged at assignment. |
budget | minutes, tool spend | Founder time and tool spend it may spend. Cost is half of every readout. |
status | draft | live | stopped | read | Where it is. "Read" means the readout is written down. |
readout_date | date | When the result is judged, set at launch. |
win_rule | rule | What counts as a win, set at launch: "joins per offer above 10%, and above the holdout". |
one campaign, as data
{
"campaign_id": "camp.lead-to-waitlist.2026-10-20",
"preset": "lead-to-waitlist",
"playbook": {
"id": "lead-to-waitlist",
"version": 1
},
"sequence": {
"id": "seq.reply-touch-dm-nudge",
"version": 1
},
"segment": {
"tiers": [
"Hot",
"Warm"
],
"contacted": false,
"sources": [
"reddit",
"x"
],
"exclude": [
"icp.not_if",
"lead_rules.never",
"in_other_campaign"
]
},
"offer": "a free brief of their own product, with a waitlist sign-up on it",
"goal_metric": "waitlist_joins_per_offer",
"guardrails": [
"stop_requests",
"founder_minutes"
],
"window": {
"start": "2026-10-20",
"end": "2026-12-31"
},
"stop_rule": "offers_made >= 40 and joins == 0",
"arms": [
{
"name": "treatment",
"share": 0.9
},
{
"name": "holdout",
"share": 0.1
}
],
"holdout_share": 0.1,
"assignment": {
"unit": "lead",
"method": "random",
"log": "lead_assigned(campaign_id, lead_id, arm, probability)"
},
"budget": {
"founder_minutes_per_week": 150,
"tool_spend_usd": 40
},
"status": "draft",
"readout_date": "2026-11-17",
"win_rule": "joins per offer >= 0.10 and above holdout"
}the library
Fourteen presets a solo founder can run.
Each preset fills the campaign object with sensible defaults. Placeholders in braces come from the brief and the ICP: {who} is the buyer, {category} is what they call the product, {competitor} comes from the competitive analysis.
camp.lead-to-waitlist — Waitlist
Lead to waitlist
Listen and reply
- segment
- Hot and Warm leads never contacted, most found on Reddit in the last month
- offer
- a free brief of their own product, with a waitlist sign-up on it
- playbook
- Lead to waitlist
listen-and-reply, signal-based-outbound - sequence
- a helpful public reply
- a light touch
- one private message with their brief and the waitlist
- one nudge
- stop
- 40 offers made and 0 joins: change the offer, not the queue
- metric
- waitlist joins per offer
camp.reddit-pain-sprint — First customers
Reddit pain-reply sprint
Listen and reply
- segment
- posts in 5 target subreddits asking for {category} help, under 48 hours old
- offer
- a useful answer; the product named only if they ask
- playbook
- Community answers
listen-and-reply - sequence
- answer in the thread
- follow-up reply if they respond
- private message only on request
- window
- 14 days
- stop
- 20 answers and under 2 profile visits: wrong subreddits
- metric
- replies that ask about the product
- holdout
- half the matching threads get no answer; compare visits from each half
camp.competitor-switch — First customers
Competitor-unhappy switch offer
Listen and reply
- segment
- people complaining about {competitor} in the last 7 days, on reviews, X or Reddit
- offer
- free migration help, or the first month free
- playbook
- Founder-led outbound
signal-based-outbound - sequence
- public reply with a workaround
- private message with the switch offer
- one follow-up after 4 days
- window
- 21 days
- stop
- 15 offers and 0 trials
- metric
- trials started per offer
- holdout
- 10% of eligible people get nothing
camp.review-responders — First customers
Review-site responders
Listen and reply
- segment
- 1 to 3 star reviews of {competitor} on G2, Capterra or the app stores, last 30 days, found by hand
- offer
- free help switching
- playbook
- Founder-led outbound
signal-based-outbound - sequence
- find the reviewer's public profile
- reply where the site allows it, or message them
- one follow-up
- window
- 30 days
- stop
- 20 reviewers reached and 0 replies
- metric
- replies per reviewer reached
- holdout
- 10% of found reviewers get nothing
Reviewers are often first-name only; skip anyone you can't find publicly.
camp.launch-week-ph — First customers
Launch week on Product Hunt
Your own channels
- segment
- your waitlist, your followers, and anyone who replied in the last 60 days
- offer
- a launch-week price
- playbook
- Launch week
launch-or-launch-again - sequence
- teaser post 7 days out
- email to the list the day before
- launch post and maker comment
- results post the next day
- the-week-after post
- window
- 8 days
- stop
- fixed window; judge on paid customers at day 14
- metric
- signups in launch week
- holdout
- none (audience-wide); compare with the two weeks before
camp.comparison-interception — First customers
Comparison-page interception
Be where they look
- segment
- people searching or posting "{competitor} alternative" or "{competitor} vs"
- offer
- an honest comparison page
- playbook
- Comparison pages
comparison-interception - sequence
- publish the page
- answer "alternative to" threads with it
- update it monthly, with dates
- window
- 30 days, then always on
- stop
- 8 weeks with no visits from the pages: change the targets
- metric
- signups from the pages
- holdout
- stagger: pages for half the competitors first
camp.comment-keyword — Waitlist
Comment-a-keyword lead magnet
Your own channels
- segment
- anyone who comments the keyword on the offer post
- offer
- 3 leads for their product, or a playbook pack
- playbook
- Offer post
comment-a-keyword - sequence
- the offer post
- reply to each commenter
- deliver within 24 hours by message
- the waitlist ask
- window
- 72 hours
- stop
- under 10 comments: the offer isn't wanted
- metric
- waitlist joins per comment
- holdout
- none (public post)
The founder sends each message; nothing goes out automatically.
camp.waitlist-countdown — Waitlist
Waitlist countdown
Your own channels
- segment
- your followers and anyone who replied to you
- offer
- early access, and a founding price if you have one
- playbook
- Waitlist countdown
- sequence
- say what's coming, with the link in a reply
- one pain a day for 12 days
- a confirm-and-ask email on each signup
- open the doors, email first
- window
- 14 days
- stop
- 7 posts and under 5 signups: the pain you're naming isn't theirs
- metric
- signups per post
- holdout
- none; compare post by post
camp.beta-recruit — First customers
Beta tester recruit
Listen and reply
- segment
- {who} who posted the pain in the last 14 days
- offer
- free beta access, set up with them
- playbook
- Beta tester recruiting
- sequence
- the call-out post
- qualify and invite by message
- feedback call on day 3
- ask for a quote on day 10
- window
- 10 days
- stop
- 10 testers set up and none use it twice
- metric
- testers who use it twice
- holdout
- none (small numbers; set up every one)
camp.stalled-trial — Trials to paid
Stalled-trial rescue
Customer lifecycle
- segment
- trial users with no key action by day 3
- offer
- a 15-minute setup call, or a done-for-you setup
- playbook
- Stalled-trial rescue
- sequence
- email on day 3
- a personal note from the founder on day 5
- a last-day email
- window
- 30 days, 7 per user
- stop
- under 1 in 10 reach the key action afterwards
- metric
- trial-to-paid
- holdout
- 20% of stalled trials get nothing
camp.failed-payment — Grow and keep
Failed payment recovery
Customer lifecycle
- segment
- every invoice.payment_failed from Stripe
- offer
- a link to update the card; nothing else
- playbook
- Failed payment
- sequence
- email the same day
- a second email on day 3
- a final notice on day 7, before cancelling
- window
- always on
- stop
- none: runs for as long as payments fail
- metric
- revenue recovered
- holdout
- none: this is money already owed
camp.win-back — Grow and keep
Win-back
Customer lifecycle
- segment
- customers who cancelled 30 to 90 days ago
- offer
- what changed since they left, and one month at half price
- playbook
- Win-back
- sequence
- a what's-new email
- a personal note from the founder
- window
- 14 days
- stop
- under 1 reply in 20
- metric
- reactivations
- holdout
- 20% of cancelled customers get nothing
camp.founder-swap — Grow and keep
Founder swap
Be where they look
- segment
- founders who sell to the same buyers, with a product that doesn't compete, close to your size
- offer
- an even trade: one post or newsletter mention each
- playbook
- Founder swap
- sequence
- the ask, by message
- your post about them on swap day
- compare numbers a week later
- window
- 3 weeks per swap
- stop
- a swap under 3 signups: thank them and don't repeat it
- metric
- signups per swap
- holdout
- none (one partner at a time)
camp.customer-proof — Grow and keep
Customer proof amplification
Your own channels
- segment
- new paying customers who agree to be named
- offer
- a shout-out, with a link to them
- playbook
- Share a new customer
customer-proof-amplified - sequence
- ask permission
- post the story
- reply with their link
- quote it in the newsletter
- window
- per customer
- stop
- none
- metric
- profile visits and signups from the post
- holdout
- none (public post)
the campaign log
What every finished campaign leaves behind.
Presets are reused; campaigns aren't. What carries forward is the log: one row per finished campaign, written at the readout date whether it won or not. The log is where the next campaign's defaults come from.
| Field | What it records | Example |
|---|---|---|
| Who and when | campaign id, preset, playbook and sequence versions, dates | camp.reddit-pain-sprint.2026-10-20, community-answers v3, Oct 20 to Nov 3 |
| Arms | each arm's size and how people were assigned | answer: 41 threads, holdout: 39 threads, random by thread |
| Funnel per arm | counts at each rung of the ladder | found → engaged → pain stated → brief offered → waitlist offered → signed up |
| Lift | goal metric per arm, the difference, and how sure | visits per thread 0.32 vs 0.05; small sample, read as a direction |
| Guardrails | stop requests, reports, removals | 0 stop requests, 1 removed comment |
| Cost | founder minutes and tool spend | 6 hours, $120 of tool spend |
| Stop reason | window ended, stop rule fired, or stopped by hand | window ended |
| Decision | repeat, change one thing, or retire | repeat, swap two subreddits |
| Learning | one sentence, written for the next campaign | "answers under 6 hours old drew almost every visit" |
The example numbers in this table are invented to show the shape of a row.
how it connects
What a campaign takes in, and what it hands on.
Leads — TAKES IN · STAGE 7 · The segment is a filter over scored, tiered leads: tier, triggers, freshness, source.
A playbook — TAKES IN · STAGE 8 · One playbook, pinned to a version. Its stop rule is the default for the campaign's.
A sequence — TAKES IN · STAGE 10 · The steps each lead in a treatment arm receives, also pinned to a version.
Funnel counts — HANDS ON · STAGE 11 · Every touch carries the campaign id and arm, so each rung can be counted per arm.
A readout — HANDS ON · STAGE 12 · The arms are an experiment. The readout and its learning go to the experiment registry.
The tracking plan — RECORDS INTO · campaign_started, lead_assigned and campaign_stopped are its events.
data to capture
Record it so a model can learn what a campaign caused.
record
- the full campaign object at launch, frozen: segment rule, offer, window, stop rule, arms and their shares
- per lead: its arm and the probability it had of landing there, written when it was assigned
- the eligible leads who were left out, and why (holdout, contact policy, already in a campaign)
- why it stopped, with counts at every step, per arm
- its cost: founder minutes and tool spend
label
conversion per arm; lift against the holdout; guardrail breaches
trains
offer and stop-rule choice, preset defaults per stage, and an uplift model: who is persuadable, as against who converts anyway
test
offer, stop rule, holdout share, window length · randomized arms with a holdout