URL: /plays/lead-nurture · Id: `play:lead-nurture`

# Lead nurture

> Follows up each unbought Lead with notes keyed to what they did, most in month one, until they buy, reply or go quiet 90 days.

Follows up each unbought [Lead](https://startupbuilder.dev/business/nouns/lead) with notes keyed to what they did, most in month one, until they buy, reply or go quiet 90 days.

```text title="Set it up · Ask"
Be our SDR for follow-up: every Lead who hasn’t bought gets notes keyed to what they did, most in the first month. Big accounts get a note from me on day 3. Stop the moment they buy, reply or go quiet for 90 days. Show me what’s missing; don’t send.
```

```text title="Run one · Ask"
Hand our latest Lead who stalled to the SDR agent and show me what it chose and why. Don’t send.
```

```ts title="Run one · SDK"
import { $ } from 'startup-builder'

const { events: [last] } = await $.Event.list({ where: 'name in ("Lead.qualified", "Conversation.answered", "Conversation.closed", "Visitor.identified", "Customer.activated", "Entitlement.checked", "Offer.trialed", "Order.started", "Event.captured", "Version.deployed", "Meeting.booked", "Waitlist.admitted", "Approval.approved", "Monitor.checked")', limit: 1 })   // { play } compiled to this Play’s Trigger Events
const { subject } = await $.Trigger.fire({ like: last.$id }, { mode: 'try' })   // the same Event again, in try mode · Not live yet, gaps #7
const { decisions: [decision] } = await $.Decision.list({ where: `on = "${subject}"` })   // what it chose, and why · Not live yet, gaps #7
const { actions } = await $.Action.list({ where: `on = "${subject}"` })   // what it did, with its checks · Not live yet, gaps #7
return { decision, actions }
```

```json title="Run one · Response · sample"
{
  "decision": {
    "$id": "https://api.sb/leaseline.app/decisions/decision_437",
    "$type": "Decision",
    "choice": "self-serve-branch",
    "reason": "Ivy Chen at Copper Oak Rentals (38 units) is on the free plan and added no owner 24 hours after signup; the rescue step sends the one next step",
    "stakes": "low",
    "options": [
      "self-serve-branch",
      "assisted-branch",
      "answer-what-they-asked",
      "recap-and-offer-times",
      "rescue-the-checkout",
      "to-the-ae",
      "let-them-go"
    ],
    "by": "worker_2",
    "on": "lead_61",
    "expected": "the first owner added within 3d",
    "reopensWhen": "no Customer.activated for lead_61 within 3d"
  },
  "actions": [
    {
      "$id": "https://api.sb/leaseline.app/actions/action_1",
      "$type": "Action",
      "status": "done",
      "mode": "try",
      "by": "worker_2",
      "verb": "Contact.enroll",
      "checks": []
    },
    {
      "$id": "https://api.sb/leaseline.app/actions/action_2",
      "$type": "Action",
      "status": "pending",
      "reason": "awaitingTime",
      "mode": "try",
      "by": "worker_2",
      "verb": "Message.schedule",
      "checks": [
        {
          "check": "owned-by-a-person",
          "status": "pass"
        },
        {
          "check": "customer-collision",
          "status": "pass"
        },
        {
          "check": "marketing-purpose",
          "status": "pass"
        },
        {
          "check": "collision-hold",
          "status": "pass"
        }
      ]
    }
  ]
}
```

`action_2` is the rescue note, held for Ivy’s quiet hours until 08:00 her time. It ends the moment she adds an owner, replies or buys.

`17.6 per 100 against 7.3 before · before-after, not proof · n 34 · path → arr`

| Try another: the Lead | Choice | Reason |
| --- | --- | --- |
| Ivy Chen, Copper Oak Rentals: free plan, no owner added after 24 h | `self-serve-branch` | a free-plan Lead short of the first step |
| Marcus Webb, Northgate Living: 160 units, asked a question, booked no time | `assisted-branch` | over the 120-unit line; your note goes on day 3 |
| Ola Reyes: started Pro checkout at 14:10, no Order by 15:10 | `rescue-the-checkout` | a started checkout with no Order in 60 minutes |
| Hilltop Rentals: 95 units, on the pricing Page Oct 13 and Oct 16 | `to-the-ae` | a fit Lead back on pricing 2 days in 7 |

| Worth | Your time | Spend | First signal | Use it when | Instead |
| --- | --- | --- | --- | --- | --- |
| ≈ +$570 ARR a month at 35 | 30 min a day week 1, then 20 min a week | $0.01 per note, ~$3 a month at 35 | Day 3: first nurtured Lead books a Meeting | 20+ new Leads a month not bought within 7 days | Under 20: `instant-response` · no marketing Purpose: add it (<Op verb="Site.publish" />) |

**Where it sits:** Stranger → **Lead** → **Trialing** → Activated → At risk → Churned → Won back · Nurture conversion → New paying Customers → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +4 paid per 100 enrolled (Other Startups’ results; no lift of your own to read) × 35 enrolled a month × $410 first order ARR ≈ +$574. Under First signal: Each Lead reads at day 90; at 35 a month, 90 days can tell only +14 per 100 or more, so your file starts at `holdout: 0` and reads before-after.

`sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Visitor.identified · first keyed note 41m · 8 keys Not live yet`

## Start it this week
```bash
npx startup-builder add play lead-nurture   # 1 · writes plays/lead-nurture.mdx (Not live yet, gaps #5)

# 2 · dry run; below, its 422 on 2026-06-22
curl -X POST "https://api.sb/leaseline.app/campaigns?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"play":"lead-nurture"}'

# 3 · keep it, at You approve each one for the first 20 Leads
curl -X POST https://api.sb/leaseline.app/campaigns \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"play":"lead-nurture"}'

# on
curl -X PATCH https://api.sb/leaseline.app/campaigns/lead-nurture \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":null}'

# off: no note sends; service touches still send
curl -X PATCH https://api.sb/leaseline.app/campaigns/lead-nurture \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":"now"}'
```


```json title="The dry run’s 422 · 2026-06-22 · sample"
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "lead-nurture can’t start: 2 checks fail and 1 warns.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "34 new Leads a month not bought or booked within 7 days",
      "doc": "/plays/lead-nurture#check-use-when",
      "then": "Metric.query"
    },
    {
      "check": "baseline",
      "status": "pass",
      "observed": "7.3 paid per 100 within 90 days, n 41",
      "doc": "/plays/lead-nurture#check-baseline",
      "then": "Metric.query"
    },
    {
      "check": "marketing-purpose",
      "status": "fail",
      "doc": "/plays/lead-nurture#check-marketing-purpose",
      "fix": "Add the marketing Purpose to your signup and Form copy; until then only service touches send.",
      "then": "Site.publish"
    },
    {
      "check": "domain-authenticated",
      "status": "fail",
      "doc": "/plays/lead-nurture#check-domain-authenticated",
      "fix": "Add the 3 DNS records shown; it passes once they resolve, often within an hour.",
      "then": "Domain.authenticate"
    },
    {
      "check": "mailbox-warm",
      "status": "pass",
      "observed": "the Startup’s Mailbox, warm since May",
      "doc": "/plays/lead-nurture#check-mailbox-warm",
      "then": "Mailbox.warm"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "sales-lead"
      ],
      "owned": 9,
      "doc": "/plays/lead-nurture#check-role-unstaffed",
      "fix": "Staff the AE, or leave it: call asks come to you.",
      "then": "Role.staff"
    }
  ]
}
```

| Check | Fix (one call) | Your time | Wait |
| --- | --- | --- | --- |
| <a id="check-use-when"></a>`use-when` · <a id="check-baseline"></a>`baseline` · pass: 34 a month; 7.3 per 100, n 41 (gaps #8) | <Op verb="Metric.query" /> on `nurture-conversion`, which fills Before in Your number | 1 min | none |
| <a id="check-marketing-purpose"></a>`marketing-purpose` · fail (gaps #8) | <Op verb="Site.publish" /> the signup and Form copy with the Purpose | 10 min | none |
| <a id="check-domain-authenticated"></a>`domain-authenticated` · fail | <Op verb="Domain.authenticate" /> | 10 min | until DNS resolves, often under 1 h |
| <a id="check-mailbox-warm"></a>`mailbox-warm` · <a id="check-role-unstaffed"></a>`role-unstaffed` · pass; warn (gaps #8): 9 of your open Leads have a person owner, you | <Op verb="Role.staff" />, or leave it: call asks come to you, and the agent drafts into your queue for your 9 | 0 min | none |

`Your number · Before 7.3 per 100 · Now 17.6 per 100 · Target 20 by Dec 31 · before-after, not proof · n 34 matured`

Each note costs under $0.01 to fill (Worker cost), and sending runs on the shared broadcast stream at no charge. Your founder notes cost your 2 minutes each. That comes to about $3 a month at 35 enrolled Leads.

## When it starts
| When | Trigger id | Starts on | Window | How it gets in |
| --- | --- | --- | --- | --- |
| A new Lead routes to nurture or self-serve | `lead-routed-nurture` | `event` on `Lead.qualified` where route in ('nurture', 'self-serve') | 24h | from `instant-response` or your signup, through <Op verb="Lead.qualify" /> |
| A signup has not reached the first step 24 hours later | `activation-stalled` | `state` on `Visitor.identified` where no activation Event 24 hours after signup | 7d | your app calls <Op verb="Event.capture" /> on the first step |
| A known Lead starts checkout and places no Order in 60 minutes | `checkout-abandoned` | `state` on `Order.started` where a known Lead and no Order.placed within 60 minutes | 48h | <Op verb="Integration.connect" /> (Stripe) |
| + 11 more for non-bookers, the first step reached, free limits, trial ends, pricing returns, interest matches, no-shows, waitlist admits, account holds and 90 silent days (`?lanes=all`) | | | | |

```json title="One signed delivery · StartupBuilder-Signature"
{
  "$id": "https://api.sb/leaseline.app/events/event_1211",
  "$type": "Event",
  "name": "Visitor.identified",
  "at": "2026-10-19T09:12:30Z",
  "seq": 1211,
  "data": {
    "lead": "leads/lead_61",
    "name": "Ivy Chen",
    "organization": "Copper Oak Rentals",
    "units": 38,
    "plan": "free",
    "signedUpAt": "2026-10-18T09:12:30Z",
    "activated": false
  }
}
```

```bash title="Reproduce it in test"
# each delivery is signed with the Watch’s secret
curl -X POST https://api.sb/leaseline.app/watches \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"selector":"Visitor.identified","url":"https://leaseline.app/hooks/sb"}'
npx startup-builder trigger Visitor.identified --like event_1211   # replays the delivery
npx startup-builder clock advance --by 1d   # runs the rescue step unless she adds an owner first
```

## Who runs it
**SDR · your agent** (`role:prospector`, `worker_2`) holds the Key Result and picks each step from what the Lead did. Your day-3 notes to big accounts hand to **you** (Dana Okafor, person, `worker_1`), and call asks go to **AE · Priya Shah (person)** (`role:sales-lead`, `worker_3`, staffed on day 72). Notes from the agent are signed by the agent, named as an agent.

| Option | Rung today | Evidence (passed of n) | Moves up at | Drops back when | You can |
| --- | --- | --- | --- | --- | --- |
| Self-serve notes · Start with what they asked for · Recap and offer times | It does it, you can stop it | 20 Leads reviewed, 0 edits on the last 10 | met on day 21 | a `step-stop` → You approve each one, for that template | <Op verb="Action.cancel" /> inside the hold |
| Assisted notes and a founder note | You approve each one | 19 notes, 2 edited | never: a note in your name stays yours | — | <Op verb="Approval.approve" /> · <Op verb="Approval.refuse" /> |
| Rescue the checkout | It does it, you can stop it | 7 of 7 | met on day 21 | the `refund-quality` Stop → You approve each one | <Op verb="Action.cancel" /> |
| To the AE · Let them go | It does it | 6 of 6 · 21 of 21 | — | an `unanswered-reply` Stop → You approve each one | <Op verb="Action.redirect" /> |
| Change the step rule | You approve each one | 1 merged of 1 | never | — | <Op verb="Change.merge" /> · <Op verb="Change.revert" /> |
| Never: a deadline or discount the Offer lacks; a Visit or Page view in a note | Refused, every time | 2 drafted, 2 refused | never | — | the `approved-pages` Check |

**What it reads · What it may call.** It reads what each Lead did in Leaseline and said in their own words, and never names a Visit or a Page view in a note. It may call <Op verb="Contact.enroll" />, <Op verb="Message.schedule" /> and <Op verb="Lead.assign" />; <Op verb="Meeting.book" /> lands on the AE’s calendar under the AE’s name. Its tools are <Op verb="Meeting.book" />, <Op verb="Task.assign" />, and any other call becomes an Approval under the Role’s Mandate.

```md title="The brief (folded): compiled Agent-register Markdown · play:lead-nurture@1 · each line names its record key"
You hold the SDR Key Result: 20 paid per 100 enrolled Leads by 2026-12-31.       ← worker, metric
On each Lead Event, choose one option and say why; at 90 silent days, Let them go. ← triggers, chooses
At 120 units or more, the founder writes a note on day 3.                        ← your file, line 4
Send the closest paid step when they add their first owner, not on a fixed day.  ← your file, line 5
Fill at most three fields; the template holds the Offer, the signature and the stop line. ← copyRules 4
No deadline, countdown or discount the Offer record lacks.                       ← copyRules 5, approved-pages
```

**The slow loop, as a Change.** `decision_301` (2026-09-07, weekly) read 7 of 24 self-serve Leads paying when the closest-paid note followed their first owner within a day, against 2 of 19 when it went on day 4, so `change_16` keyed that note to the first owner (your file, line 5), and Dana merged it with <Op verb="Change.merge" />. **Replayed on past Leads**, <Op verb="Change.review" /> put the branch at 21 per 100; read back at +30d it is 19 per 100, n 21, ■□□□ Too early to tell (Example, day 107).

**Bring your own agent** (folded) sends at It does it, you can stop it when it matches or beats the seated agent on the eval suite, and at You approve each one when it does not; <Op verb="Role.staff" /> seats it.

```bash
npx startup-builder eval --scenario lead-nurture-136 --agent "claude -p" --seat prospector   # seated: 17.6 per 100, 0 Checks failed sent, $0.02 a Lead · yours: 16.1, 1 discount drafted, $0.03 → You approve each one
```

## What it can do next
| Option | Picked when | Decided by | Runs | Hands to | If it’s just you |
| --- | --- | --- | --- | --- | --- |
| Self-serve notes `self-serve-branch` | a free-plan or trial Lead | Your rule (the route) | `nurture-self-serve`: the rescue, the made note, then the closest paid step on the first owner | nobody; it ends when they buy | the same |
| Assisted notes and a founder note `assisted-branch` | a fit Lead at or over the 120-unit line who has not booked | Your rule (line 4) | `nurture-assisted` → your `nurture-founder-note` on day 3 | you approve the note, due 1 business day · Take this one | you |
| Start with what they asked for `answer-what-they-asked` | they came from a piece, a free tool, a Gathering or an outreach reply | Agent’s call, with its reason | `nurture-interest`, starting with what they asked for | nobody | the same |
| Recap and offer times `recap-and-offer-times` | a Form or chat answer offered a time and they booked none | Your rule (the non-booker window) | `form-non-booker` or `chat-non-booker`: a recap and two new times, once | nobody | the same |
| Rescue the checkout `rescue-the-checkout` | a started checkout with no Order in 60 minutes | Your rule (the checkout window) | `checkout-rescue-two-touch`: the restored checkout and one answer, then the stated guarantee | nobody | the same |
| To the AE `to-the-ae` | a reply asking for a call, a fit Lead back on pricing 2 days in 7, or a missed Meeting | Agent’s call, with its reason | <Op verb="Meeting.book" /> with the AE’s times → <Op verb="Task.assign" /> | <Op verb="Task.assign" /> → AE · Priya Shah, due 60 min (`response-60m`), Brief attached · Take this one | you, within 60 min |
| Let them go `let-them-go` | 90 silent days, or day 180 | Your rule (the exit) | nothing; `lead-reactivation` holds them after a 60-day rest, with every fact and Offer used | nobody | the same |

| When they write back | Fixture reply | What happens | Who answers | By when | Call |
| --- | --- | --- | --- | --- | --- |
| Interested | “Can we walk through it for our 160 units?” | To the AE: three times from Priya’s calendar; notes stop | AE · Priya Shah (person) | 60 min | <Op verb="Meeting.book" /> |
| Send me pricing | “What does Pro cost for 38 units?” | answers with the Pricing Page’s list Price and one next step | SDR · your agent | 5 min | <Op verb="Conversation.answer" /> |
| Not now | “We’ll look again in spring.” | notes stop; one note returns on the date they named | SDR · your agent | at once | <Op verb="Message.schedule" /> |
| Wrong person | “My business partner handles software.” | asks them to forward it; it never writes to an address from their text | SDR · your agent | 1 business day | <Op verb="Conversation.answer" /> |
| Out of office | an auto-reply until Oct 28 | the next step waits for the return date | nobody | the return date | <Op verb="Message.schedule" /> |
| Question it can’t answer | “Can you import from our old spreadsheet?” | To a person, the question in the Brief | AE · Priya Shah, or you | 60 min | <Op verb="Conversation.escalate" /> |
| Stop | “Stop emailing me.” | every note stops, on every scope they chose; service touches about their own account still send | nobody | at once | <Op verb="Contact.unsubscribe" /> |

## When it hands to you
Day-3 notes in your name go to **you** (Dana Okafor, person); call asks, pricing returns and no-shows go to **AE · Priya Shah (person)**, and before day 72 they came to you. As captured, one Brief per Role (`brief`, `draft`, `route` and `checks` are Not live yet, gaps #7).

```json title="What lands in each queue · sample"
[
  {
    "$id": "https://api.sb/leaseline.app/approvals/approval_97",
    "$type": "Approval",
    "verdict": null,
    "deadline": "2026-10-20T15:00:00Z",
    "draft": "Marcus, you asked whether Leaseline handles 4 owners on one portfolio. It does; that is why I built it. Want 15 minutes on Thursday?",
    "route": "assisted-branch",
    "checks": [
      {
        "check": "approved-pages",
        "status": "pass"
      },
      {
        "check": "owned-by-a-person",
        "status": "pass"
      }
    ]
  },
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_527",
    "$type": "Task",
    "assignee": "worker_3",
    "due": "2026-10-16T15:20:00Z",
    "on": "lead_47",
    "brief": {
      "who": "Hilltop Rentals, 95 units",
      "did": "the pricing Page on Oct 13 and Oct 16; Team plan open both days",
      "chose": "to-the-ae",
      "why": "a fit Lead back on pricing 2 days in 7",
      "never": [
        "a discount",
        "a deadline the Offer lacks"
      ]
    }
  }
]
```

You answer a founder note with <Op verb="Approval.approve" />, an edit, or <Op verb="Approval.refuse" />; one unanswered by its deadline expires, and the branch carries on without it. The AE answers with <Op verb="Task.claim" /> (Take this one), <Op verb="Task.return" /> with a reason, or <Op verb="Action.redirect" />; once claimed, the agent’s pending notes to that Lead cancel with `claimedByPerson` (Not live yet, gaps #7). A Task nobody claims by its due time goes up a Role through <Op verb="Task.escalate" /> (AE to you), and `unanswered-reply` fires.

**On time:** AE · Priya Shah: 6 of 6 claimed within 60 min, median 21 min, n 6. You: 17 of 19 founder notes approved by their deadline, n 19, ■■□□ Early sign beside Other Startups’ 89 % on time. **Your queue:** counted by kind: in week 1, about 12 note reviews a day; after day 21, about 1 founder note and 1 AE hand-off a week, and 1 weekly readout.

**The fixed line:** <Op verb="Deal.assign" /> sets `owner` to the receiving person, the agent is never a Deal’s owner, and Meetings land on the owner’s calendar under the owner’s name.

## When it won’t send
| Check (refuses one send) | Refuses | Fix | Then |
| --- | --- | --- | --- |
| <a id="check-owned-by-a-person"></a>`owned-by-a-person` (rule j; Not live yet, gaps #8) | a note to a Contact whose Lead or open Deal a person owns, or whose Conversation a person claimed | Leave it to the person who owns it: the draft waits in their queue. | <Op verb="Task.assign" /> |
| <a id="check-customer-collision"></a>`customer-collision` (gaps #1) | a nurture note to a Contact with an active Subscription | Send it to their CSM instead. | <Op verb="Conversation.assign" /> |
| <a id="check-approved-pages"></a>`approved-pages` (Not live yet) | a price, plan, limit, deadline or discount that the claims source and the Offer record lack | Cut the line, or publish the Page that says it. | <Op verb="Site.publish" /> |
| `marketing-purpose` (the Consent gate) | a promotional note with no marketing Purpose valid in the Lead’s Market | Only service touches send; add the Purpose to your copy. | <Op verb="Site.publish" /> |
| <a id="check-claims-hold"></a>`claims-hold` | a queued note after a claims change, before its prices, plans and limits are checked again | Wait for the re-check, often under 10 min. | <Op verb="Decision.list" /> |
| <a id="check-collision-hold"></a>`collision-hold` | a note to a Person with an open Conversation on any channel | It waits until the Conversation closes. | <Op verb="Conversation.close" /> |

| Stop (pauses the Play) | Pauses when | Then |
| --- | --- | --- |
| <a id="stop-step-stop"></a>`step-stop` (email) | a step’s stops pass 1 % of its last 200 delivered | that template returns to You approve each one |
| <a id="stop-bounce"></a>`bounce` (email) | hard bounces over 2 % of a day of 50 or more sends | the Play’s Mailbox pauses |
| <a id="stop-complaint"></a>`complaint` (email) | stop and hostile replies over 0.3 % of the last 1,000, hostile counted 5 times | the Play pauses |
| <a id="stop-provider-spam"></a>`provider-spam` (email) | a mailbox provider reports 0.08 % spam | sends to that provider pause |
| <a id="stop-authentication"></a>`authentication` (email) | an SPF, DKIM, DMARC alignment or one-click stop header check fails | the Play pauses |
| <a id="stop-unanswered-reply"></a>`unanswered-reply` | a reply passes its deadline | new Enrollments pause until it is answered |
| <a id="stop-refund-quality"></a>`refund-quality` | 30-day refunds on nurtured purchases over 1.5 times your others, at 30 or more | every Offer step pauses |
| <a id="stop-holdout-floor"></a>`holdout-floor` | no lift over a held-back half after 400 Leads per arm | the branch drops to its three-step minimum |
| <a id="stop-kill-switch"></a>`kill-switch` | you press it | every Tactic pauses at once; service touches still send |

The captured refusal, then the Stop that fired as a `Campaign.paused` reason (Not live yet, gaps #2); the rewrite that sent is the Elm Street thread in Example.

```json title="The captured refusal · sample"
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The month-one close to Elm Street Rentals did not send: it carries a deadline and a discount no Offer holds.",
  "checks": [
    {
      "check": "approved-pages",
      "status": "fail",
      "doc": "/plays/lead-nurture#check-approved-pages",
      "fix": "Cut the line, or publish the Page that says it.",
      "then": "Site.publish"
    },
    {
      "check": "owned-by-a-person",
      "status": "pass"
    }
  ]
}
```


```json title="The Stops that fired, as Campaign.paused reasons · sample"
[
  {
    "reason": {
      "limit": "unanswered-reply",
      "observed": "2h 10m",
      "bound": "60m",
      "window": "1 reply"
    },
    "doc": "/plays/lead-nurture#stop-unanswered-reply",
    "task": "task_498"
  }
]
```

## Did it work
At about 8 enrolled a week, no held-back half reads within 90 days, so the basis is before-after (rule o): the columns read Now and Before, and nothing prints as Added. Each figure’s call is <Op verb="Metric.query" /> by node, and every node above the leaf is Not live yet (gaps #4).

`17.6 per 100 against 7.3 before · before-after, not proof · n 34 · path → arr`

| Node | Now (119 days) | Before (the 90 days before) | Added | Confidence | Basis |
| --- | --- | --- | --- | --- | --- |
| `nurture-conversion` | 17.6 per 100: 6 of 34 matured Leads paid within 90 days · 102 still maturing | 7.3 per 100: 3 of 41, with no nurture | — · Worth about +$570 a month | — | before-after, not proof · Other Startups’ results +4 per 100, ■■■□ Likely, n 9,800, 10 % held back at random |
| `new-paying-customers` | 15 nurtured Leads paid, 6 of them matured | 3 | — | — | before-after |
| `new-arr` ↑ | $6,393, 15 Customers (13 on Pro, 2 on Team) · Booked: credited, not all caused by this Play | $1,041 | — · 11 trials still deciding | — | before-after, not proof |
| `net-new-arr` · `arr` | carried from `new-arr` | carried | — | — | carried |

Before against after reads Leads enrolled Jun 22 to Jul 21, matured at day 90, against the 41 Leads of the 90 days before, who got no nurture. It is not proof; Other Startups’ results, read against 10 % held back at random at enrollment, print beside it.

**How it moves it:** each step fires within an hour of what the Lead did, and the closest paid step follows the first owner they add instead of a fixed day 4.

**Guardrails:** before against after: `outside-paying-customers`, 15 against 3, and `spam-rate`, 0.04 % of 1,880 notes; stops at 0.6 % of delivered.

```json title="The Campaign card · sample"
{
  "$id": "https://api.sb/leaseline.app/campaigns/lead-nurture",
  "$type": "Campaign",
  "play": "play:lead-nurture@1",
  "path": [
    "nurture-conversion",
    "new-paying-customers",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "nurture-conversion",
    "unit": "percent",
    "heldBack": 0,
    "decision": null
  },
  "readout": {
    "value": null,
    "n": 34,
    "maturing": 102,
    "interval": null,
    "readability": "inadmissible",
    "basis": "before-after",
    "pooled": true
  },
  "ledger": {
    "spend": 0,
    "workerCost": 11,
    "hours": 9.5,
    "pipelineArr": 4800,
    "wonArr": 6393,
    "projectedArr": 574,
    "paybackDays": 1
  }
}
```

Outside benchmark: the record’s `nurture-month-one-plan-upgrades` range, from a subscription-analytics firm’s billing data, puts most first plan upgrades in a subscriber’s first month, which is why the notes are front-loaded there.

**Before it · After it.** Before it: `instant-response` routes Nurture and trial Leads here, and `product-led` signups. After it: every purchase goes to onboarding, call asks to the AE, and Let them go hands Leads to `lead-reactivation` after a 60-day rest.

## Example
Leaseline ran it from 2026-06-22 to 2026-10-19 (119 days): 136 Leads enrolled, 34 matured past day 90 and 102 still maturing, and 1,880 notes sent. Read every captured thread at `?threads=all`; three follow the tables.

| What happened, by option | Decisions | Notes sent | Paid (credited, not all caused by this Play) |
| --- | --- | --- | --- |
| Self-serve notes | 78 | 1,190 | 10 on Pro |
| Assisted notes and a founder note | 19 | 214 + 19 founder notes | 2 on Team, 1 on Pro |
| Start with what they asked for · Recap and offer times · Rescue the checkout | 14 · 12 · 7 | 201 · 24 · 13 | 1 · 0 · 1 on Pro |
| To the AE · Let them go | 6 · 21 | — | 4 Meetings held, 2 Deals open |
| **All** · Before (90 days) | **157** | **1,880** | **15** (6 of 34 matured) · 3 of 41 |
| At 35 a month (the Use it when volume) | about 40 a month | about 480 a month | Other Startups’ results: +4 per 100, ■■■□ Likely, n 9,800 |

| Day | Event | What happened | Your time |
| --- | --- | --- | --- |
| 0 | `event_101` Campaign.created | the three steps; dry run fails `marketing-purpose` and `domain-authenticated` | 35 min |
| 2 | `event_108` Site.published | the marketing Purpose on your signup and Form copy | 10 min |
| 3 | `event_113` Meeting.booked | the first nurtured Lead books a call, from the recap note | — |
| 21 | `event_160` Role.updated | promoted: notes send after a 2-minute hold, 20 Leads reviewed, 0 edits on the last 10 | — |
| 72 | `event_301` Role.staffed | AE · Priya Shah (person) takes `role:sales-lead` | — |
| 77 · 107 | `event_315` Change.merged · `event_820` Readout.created | the closest paid note keyed to the first owner: replayed at 21 per 100, read back at +30d at 19, n 21 | 5 min |
| 98 | `event_640` Campaign.paused | `unanswered-reply`: a call ask waited 2h 10m; enrollments resumed once Priya answered | 5 min |
| 1–119 | `event_104` Approval.created, first of 239 | you reviewed 220 notes in weeks 1 to 3 and approved 19 founder notes | 8.2 h · **total 9.5 h measured, 10 h asked** |

> **Leaseline’s agent → Noor Haddad, Elm Street Rentals, Jul 3, 08:05** · You signed up yesterday; the one step left is adding your first owner, which takes about 2 minutes.¹ https://leaseline.app/owners/new *Signed by Leaseline’s agent, named as an agent, with the stop line.*²
>
> **Noor, Jul 3, 08:40** · added her first owner. **Jul 3, 09:30** · the closest paid note: Pro sends that owner’s renewal batch 60 days out, for $29 a month.³ **Jul 16** · paid for Pro, +$347 ARR.

```diff title="Elm Street Rentals, 2026-07-14 · the draft approved-pages refused, then the rewrite that sent"
- Upgrade by Friday to keep 20% off Pro.
+ Pro sends each owner their renewal batch, 60 days out, for $29 a month. Want it on for your 22 units?
```

> **Hilltop Rentals, 2026-10-16 14:20** · back on the pricing Page for a second day in a week, Team open both times. The agent sent no note and chose To the AE, Brief attached, due 15:20. · **Priya, 14:38** · claimed it with <Op verb="Task.claim" /> and wrote with three times; they booked Oct 21. The Brief is in When it hands to you (`task_527`).

¹ What she did in Leaseline, in her own terms; never a Page view. ² The fixed signature and stop lines, compiled from the Role’s Settings. ³ The Pricing Page’s list Price, and one ask.

## Your settings
```mdx title="plays/lead-nurture.mdx"
---
holdout: 0        # 8 a week is too few to hold 1 in 10 back; it reads before-after
---
At 120 units or more, I write a note on day 3.
Send the closest paid step when they add their first owner, not on a fixed day.
```

```text
$ npx startup-builder show plays/lead-nurture
holdout 0 · founder note at 120 units · closest paid on the first owner     your file  plays/lead-nurture.mdx:2,4,5 (Ask 2026-06-22; line 5 by change_16, 2026-09-07)
family demand · worker role:prospector, owns never · chooses 7 (5 rule, 2 read) · sequences nurture-self-serve, nurture-assisted, nurture-founder-note, nurture-interest, nurture-waitlist, form-non-booker, chat-non-booker, checkout-rescue-two-touch · checks owned-by-a-person, customer-collision, approved-pages, marketing-purpose, claims-hold, collision-hold · stops 9 · placements gmail, outlook, yahoo-mail    catalog  play:lead-nurture@1 (Not live yet, gaps #5)
```

### Every key from the catalog
| Key | Id | What it is |
| --- | --- | --- |
| Tactic | <a id="tactic-nurture-enroll"></a>`nurture-enroll` | Nurture enroll: Turns a hand-raise into one Enrollment on the right branch, with the holdout drawn and the Lead’s own words recorded. Starts at Sends nothing. |
| Tactic | <a id="tactic-nurture-compose"></a>`nurture-compose` | Nurture compose: Picks each due or keyed step and fills at most three fields of its approved template from the Lead’s own words and the claims source. Starts at You approve each one. |
| Tactic | <a id="tactic-lead-send-gate"></a>`lead-send-gate` | Lead send gate: Checks Suppression, Consent, touch class, open Conversations, the Startup’s Lead touch Limits, labels and quiet hours before any Message to a Lead. Starts at Sends nothing. |
| Tactic | <a id="tactic-nurture-send"></a>`nurture-send` | Nurture send: Sends a passed step from the broadcast stream, records it, and moves the Enrollment on each Lead Event that follows. Starts at You approve each one. |
| Tactic | <a id="tactic-non-booker-follow-up"></a>`non-booker-follow-up` | Non-booker follow-up: Recaps a chat or Form answer for a Lead who was offered a time and booked none, with two times and the Lead’s own question. Starts at You approve each one. |
| Tactic | <a id="tactic-checkout-rescue"></a>`checkout-rescue` | Checkout rescue: Sends a Lead who started checkout and stopped two touches at most: the restored checkout with one answer, then the stated guarantee or one question. Starts at You approve each one. |
| Tactic | <a id="tactic-nurture-exit-handoff"></a>`nurture-exit-handoff` | Nurture exit handoff: Ends an Enrollment at 90 silent days or day 180 and hands the Lead to lead reactivation with every fact and Offer already used. Starts at Sends nothing. |
| Tactic | <a id="tactic-nurture-readout"></a>`nurture-readout` | Nurture readout: Reads nurture conversion against the holdout per branch and Variant each week, and drafts the next Variant from edits and replies. Starts at Sends nothing. |
| Tactic | <a id="tactic-nurture-stop-loss"></a>`nurture-stop-loss` | Nurture stop loss: Reads the Play’s own stops, bounces, replies and refunds on every send and pauses a template, the Mailbox, new Enrollments or the Play. Starts at Sends nothing. |
| Tactic | <a id="tactic-reply-matrix"></a>`reply-matrix` | Reply matrix: Labels every outreach reply with one of 11 labels, maps it to one of seven reply kinds, and runs that kind’s move by its deadline. Starts at You approve each one. |
| Trigger | <a id="trigger-lead-routed-nurture"></a>`lead-routed-nurture` | Lead routed to nurture: `event` on `Lead.qualified`, window 24h. |
| Trigger | <a id="trigger-form-non-booker"></a>`form-non-booker` | Form non-booker: `state` on `Conversation.answered`, window 7d. |
| Trigger | <a id="trigger-chat-non-booker"></a>`chat-non-booker` | Chat non-booker: `state` on `Conversation.closed`, window 7d. |
| Trigger | <a id="trigger-activation-stalled"></a>`activation-stalled` | Activation stalled: `state` on `Visitor.identified`, window 7d. |
| Trigger | <a id="trigger-activation-reached"></a>`activation-reached` | Activation reached: `event` on `Customer.activated`, window 72h. |
| Trigger | <a id="trigger-free-limit-near"></a>`free-limit-near` | Free limit near: `threshold` on `Entitlement.checked`, window 7d. |
| Trigger | <a id="trigger-trial-ending"></a>`trial-ending` | Trial ending: `at` on `Offer.trialed`, window 3d. |
| Trigger | <a id="trigger-checkout-abandoned"></a>`checkout-abandoned` | Checkout abandoned: `state` on `Order.started`, window 48h. |
| Trigger | <a id="trigger-lead-pricing-return"></a>`lead-pricing-return` | Lead pricing return: `threshold` on `Event.captured`, window 72h. |
| Trigger | <a id="trigger-interest-match"></a>`interest-match` | Interest match: `event` on `Version.deployed`, window 30d. |
| Trigger | <a id="trigger-meeting-no-show"></a>`meeting-no-show` | Meeting no-show: `state` on `Meeting.booked`, window 72h. |
| Trigger | <a id="trigger-waitlist-admitted"></a>`waitlist-admitted` | Waitlist admitted: `event` on `Waitlist.admitted`, window 7d. |
| Trigger | <a id="trigger-account-touch-hold"></a>`account-touch-hold` | Account touch hold: `event` on `Approval.approved`, window 14d. |
| Trigger | <a id="trigger-lead-silent-90"></a>`lead-silent-90` | Lead silent 90: `state` on `Monitor.checked`, window 1d. |
| Sequence | <a id="sequence-chat-non-booker"></a>`chat-non-booker` | Chat non-booker recap: 2 steps; it ends on A reply; A booked Meeting; A paid Order or Subscription; A stop at any scope; A hard bounce. |
| Sequence | <a id="sequence-form-non-booker"></a>`form-non-booker` | Form non-booker recap: 2 steps; it ends on A reply; A booked Meeting; A paid Order or Subscription; A stop at any scope; A hard bounce. |
| Sequence | <a id="sequence-nurture-assisted"></a>`nurture-assisted` | Assisted nurture: 9 steps; it ends on A reply; A paid Order or Subscription; A stop at any scope; A hard bounce; A Deal opened after a held Meeting; 90 days with no Lead Event; Day 180. |
| Sequence | <a id="sequence-nurture-founder-note"></a>`nurture-founder-note` | Founder note: 1 steps; it ends on A reply; A booked Meeting; A paid Order or Subscription; A stop at any scope. |
| Sequence | <a id="sequence-nurture-self-serve"></a>`nurture-self-serve` | Self-serve nurture: 11 steps; it ends on A reply; A paid Order or Subscription; A stop at any scope; A hard bounce; 90 days with no Lead Event; Day 180. |
| Sequence | <a id="sequence-nurture-interest"></a>`nurture-interest` | Interest nurture: 9 steps; it ends on A reply; A paid Order or Subscription; A stop at any scope; A hard bounce; 90 days with no Lead Event; Day 180. |
| Sequence | <a id="sequence-nurture-waitlist"></a>`nurture-waitlist` | Waitlist nurture: 3 steps; it ends on Admission, into nurture-self-serve; A reply; A stop at any scope; 90 days with no Lead Event. |
| Sequence | <a id="sequence-checkout-rescue-two-touch"></a>`checkout-rescue-two-touch` | Checkout rescue two touch: 2 steps; it ends on A paid Order; A reply; A stop at any scope. |
| Benchmark | <a id="benchmark-nurture-month-one-plan-upgrades"></a>`nurture-month-one-plan-upgrades` | Monthly upgrade rate to a higher plan after purchase: month 4 (low) and month 1 (high): 0.16–0.75 % (A subscription-analytics vendor’s billing data; paying accounts only, 2026-09-30). |
| Benchmark | <a id="benchmark-nurture-month-one-seat-upgrades"></a>`nurture-month-one-seat-upgrades` | Monthly seat upgrade rate after purchase: month 4 (low) and month 1 (high): 0.19–0.83 % (A subscription-analytics vendor’s billing data; paying accounts only, 2026-09-30). |
| Benchmark | <a id="benchmark-nurture-month-one-upgrade-multiple"></a>`nurture-month-one-upgrade-multiple` | Upgrades in month 1 after purchase as a multiple of month 4, plan and seat upgrades: 4.4–4.7 ratio (A subscription-analytics vendor’s billing data; paying accounts only, 2026-09-30). |