URL: /plays/creator-ads · Id: `play:creator-ads`

# Creator ads

> Runs a creator’s winning post, unedited, as a labeled paid Ad under the rights in their Agreement, and measures it against regions held back.

Runs a creator’s winning post, unedited, as a labeled paid [Ad](https://startupbuilder.dev/business/nouns/ad) under the rights in their [Agreement](https://startupbuilder.dev/business/nouns/agreement), and measures it against regions held back.

```text title="Set it up · Ask"
Be our paid media lead: when Jess posts about Leaseline and the post beats her usual numbers, run it as a paid partnership Ad, exactly as she posted it, at $20 a day. Hold back 1 region in 5 so we know what it added. I approve every Ad. Show me what’s missing; don’t spend.
```

```text title="Run one · Ask"
Hand Jess’s latest post to the paid media agent and show me what it chose and why. Don’t spend.
```

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

const { events: [last] } = await $.Event.list({ where: 'name in ("Post.published", "Post.edited", "Mandate.revoked", "Monitor.checked", "Ad.rejected", "Experiment.matured", "Offer.repriced")', 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_642",
    "$type": "Decision",
    "choice": "promote-the-post",
    "reason": "Jess’s Oct 10 post on 60-day renewal notices held viewers 2.1 times her median; her Agreement grants 90 days of rights, and the screen passed",
    "stakes": "medium",
    "options": [
      "promote-the-post",
      "ask-for-rights",
      "keep-it-organic"
    ],
    "by": "worker_11",
    "on": "post_377",
    "expected": "+3 Leads per $100 against held-back regions within 28d",
    "reopensWhen": "the holdout window closes on Nov 9, or a Stop fires"
  },
  "actions": [
    {
      "$id": "https://api.sb/leaseline.app/actions/action_1",
      "$type": "Action",
      "status": "done",
      "mode": "try",
      "by": "worker_11",
      "verb": "Ad.create",
      "checks": [
        {
          "check": "category",
          "status": "pass"
        },
        {
          "check": "drift",
          "status": "pass"
        }
      ]
    },
    {
      "$id": "https://api.sb/leaseline.app/actions/action_2",
      "$type": "Action",
      "status": "pending",
      "reason": "awaitingApproval",
      "mode": "try",
      "by": "worker_11",
      "verb": "Task.assign",
      "checks": [
        {
          "check": "owned-by-a-person",
          "status": "pass"
        },
        {
          "check": "scale-gate",
          "status": "pass"
        }
      ]
    }
  ]
}
```

`action_1` builds the partnership Ad from the archived post, with enhancements off. `action_2` asks you to approve it in the Venue’s ad manager; nothing spends until you do.

`+4.0 Leads per $100 · ■■□□ Early sign · 40 regions · path → arr`

| Try another: the creator post | Choice | Reason |
| --- | --- | --- |
| Jess Moreno, Oct 10: “How I send renewal notices 60 days out,” 2.1× her median hold | `promote-the-post` | beat her median; rights granted; the screen passed |
| Jess Moreno, Sep 2: a post that beat her median, under an Agreement with no rights clause | `ask-for-rights` | no rights yet: the Agreement summary goes to her |
| Jess Moreno, Sep 28: a post at 0.8× her median | `keep-it-organic` | under her median: it stays organic |

| Worth | Your time | Spend | First signal | Use it when | Instead |
| --- | --- | --- | --- | --- | --- |
| ≈ +$500 ARR a month at $600 a month | 40 min week 1, then 10 min a week | $20 a day plus $95 per 90 days of rights, ~$630 a month | Day 3: first Lead from a served region | A creator under Agreement, a post that beat their median, $600+ a month | No creator under Agreement: `creator-probe` · under $600 a month: `creator-partnership` |

**Where it sits:** **Stranger** → Lead → Trialing → Activated → At risk → Churned → Won back · Creator ad lead lift → New Leads → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +4.0 Leads per $100 × $600 a month ÷ $100 × 0.06 Leads to paid × $348 first order ARR ≈ +$501. Under First signal: A 28-day geo holdout reads once; two windows tell a +3 per $100 lift at $600 a month.

`sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Post.published · first screen verdict 72 h after the post · 9 keys Not live yet`

**Runs inside:** [Promote winners](/plays/promote-winners), as one of its options; this page keeps its own record and URL.

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

# 2 · dry run; below, its 422 on 2026-08-24
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":"creator-ads"}'

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

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

# off: every creator Ad pauses; the posts stay organic
curl -X PATCH https://api.sb/leaseline.app/campaigns/creator-ads \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":"now"}'
```


```json title="The dry run’s 422 · 2026-08-24 · sample"
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "creator-ads can’t start yet: 1 check fails and 2 warn.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "1 creator under Agreement; $600 a month Limit",
      "doc": "/plays/creator-ads#check-use-when",
      "then": "Metric.query"
    },
    {
      "check": "baseline",
      "status": "warn",
      "observed": "no paid creator Leads in 90 days",
      "doc": "/plays/creator-ads#check-baseline",
      "fix": "The held-back regions become the comparison; the first window reads at 28 days.",
      "then": "Metric.query"
    },
    {
      "check": "approved-pages",
      "status": "fail",
      "doc": "/plays/creator-ads#check-approved-pages",
      "fix": "Publish the landing Page the Ad links to, with the live Price.",
      "then": "Site.publish"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "contracts-manager",
        "compliance-officer"
      ],
      "owned": 0,
      "doc": "/plays/creator-ads#check-role-unstaffed",
      "fix": "Leave them: the rights Agreement and each Ad 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: 1 creator, $600 a month · warn: no history (gaps #8) | <Op verb="Metric.query" /> on `creator-ad-lead-lift`; the held-back regions fill Before | 1 min | 28 days |
| <a id="check-approved-pages"></a>`approved-pages` · fail (gaps #8) | <Op verb="Site.publish" /> the landing Page | 20 min | none |
| <a id="check-role-unstaffed"></a>`role-unstaffed` · warn (gaps #8): rights and Ads come to you | <Op verb="Role.staff" />, or leave it: you approve each Agreement and Ad | 0 min | none |

`Your number · Before no paid creator Leads · Now +4.0 Leads per $100 against held-back regions · Target +5 by Dec 31 · ■■□□ Early sign · 40 regions, 8 held back`

Spend is $20 a day ($600 a month, the Venue’s minimum that reads), plus Jess’s $190 post fee and a $95 usage fee per 90 days of rights. Screens and the watch cost about $0.02 a post (Worker cost). That comes to about $630 a month.

## When it starts
| When | Trigger id | Starts on | Window | How it gets in |
| --- | --- | --- | --- | --- |
| A creator under Agreement posts about your Offer | `creator-post-live` | `event` on `Post.published` where a creator under a signed Agreement names or shows the Offer | 30d | <Op verb="Handle.connect" /> reads the creator’s posts |
| A promoted post is edited, deleted or loses its disclosure | `creator-post-changed` | `event` on `Post.edited` where a promoted source post is edited, deleted, made private, or loses its disclosure or partnership toggle | 1h | the daily watch on every promoted post |
| A post’s rights end in 14 days | `rights-expiring` | `at` on `Monitor.checked` where 14 days before a post’s rights term or permission end | 14d | the Agreement’s rights term |
| + 7 more for revoked rights, safety flags, rejected Ads, Venue ad changes, fatigue, closed holdouts and margin changes (`?lanes=all`) | | | | |

```json title="One signed delivery · StartupBuilder-Signature"
{
  "$id": "https://api.sb/leaseline.app/events/event_1219",
  "$type": "Event",
  "name": "Post.published",
  "at": "2026-10-10T15:00:22Z",
  "seq": 1219,
  "data": {
    "post": "post_377",
    "handle": "handle_9",
    "venue": "instagram",
    "creator": "Jess Moreno",
    "agreement": "agreement_14",
    "disclosure": true,
    "partnershipLabel": true
  }
}
```

```bash title="Reproduce it in test"
npx startup-builder trigger Post.published --like event_1219   # replays the delivery
npx startup-builder clock advance --by 3d   # runs the 72-hour screen
npx startup-builder listen Post.published --forward-to http://localhost:3000/hook
```

## Who runs it
**Paid media · your agent** (`role:paid-media-manager`, `worker_11`) holds the Key Result. It hands every Ad build, every rights Agreement and every Limit raise to **you** (Dana Okafor, person, `worker_1`), because the Contracts Manager Role has no person; the creator, **Jess Moreno (person)**, signs her own Agreement. Your number links to Did it work.

| Option | Rung today | Evidence (passed of n) | Moves up at | Drops back when | You can |
| --- | --- | --- | --- | --- | --- |
| Promote the post | You approve each one | 2 of 2 | after 19 of 20 screen verdicts you agree with, then It does it, you can stop it; the Venue caps it there | a Check fails, or `drift` fires → You approve each one | <Op verb="Approval.approve" /> · <Op verb="Approval.refuse" /> |
| Ask for rights · Keep it organic | It does it | 1 of 1 · 4 of 4 | — | — | <Op verb="Action.redirect" /> |
| Raise the Limit, add a Venue, cut the held-back regions | You approve each one | 0: the scale gate waits for a winning readout | never | — | <Op verb="Limit.raise" /> |
| Never: an edit to the creator, her voice or the Product; enhancements on; text in her voice | Refused, every time | 1 build refused (`approved-pages`), 0 drift pauses | never | — | — |

**What it reads · What it may call.** It reads the creator’s posts, their hold and engagement, the Agreement’s rights and the targeting each Venue offers the Offer’s category; who watched picks Audiences and never appears in Ad text.

```md title="The brief (folded): compiled Agent-register Markdown · play:creator-ads@1 · each line names its record key"
You hold the Paid media Key Result: +5 Leads per $100 against held-back regions by 2026-12-31. ← worker, metric
Promote a post only as published: captions, crop and a shorter trim, nothing else. ← copyRules 1, drift
Every Ad carries the Venue’s partnership label and the creator’s own disclosure line. ← copyRules 2
Text Leaseline adds speaks as Leaseline, never in the creator’s voice.           ← copyRules 5
Keep the Venue’s automatic enhancements off.                                     ← copyRules 8
```

**The slow loop, as a Change.** `payback` paused the Play on day 14, reading the first payment ($26 margin) against $184 per first Transaction. `change_27` set the margin in your file to the first year’s ($290), and you merged it; read back at +28d, $211 per first Transaction, under the line.

## What it can do next
| Option | Picked when | Decided by | Runs | Hands to | If it’s just you |
| --- | --- | --- | --- | --- | --- |
| promote-the-post `promote-the-post` | beat the creator’s median, rights granted, the screen passed | Your rule (line 6, the screen) | <Op verb="Ad.create" /> from the archived post → your approval in the Venue | you approve it · Take this one | the same |
| ask-for-rights `ask-for-rights` | beat the median; no rights clause yet | Your rule (the screen) | `creator-rights-ask`: the Agreement summary, one reminder | the creator signs, or it stays organic | the same |
| keep-it-organic `keep-it-organic` | under the creator’s median, or the screen failed | Your rule (the screen) | nothing; the post stays organic | nobody | the same |

| When they write back | Fixture reply | What happens | Who answers | By when | Call |
| --- | --- | --- | --- | --- | --- |
| Interested | “Happy to. Send the Agreement.” | the Agreement with its plain summary; it signs on her press | the creator | — | <Op verb="Agreement.sign" /> (hers) |
| Send me pricing | “What does the usage fee come to?” | the fee in numbers: $95 per 90 days of rights | Paid media · your agent | 1 business day | <Op verb="Conversation.answer" /> |
| Not now | “Not this month.” | the post stays organic; nothing more sends about it | nobody | at once | <Op verb="Conversation.close" /> |
| Wrong person | “My manager handles brand deals.” | asks her to forward it; it never writes to an address from her text | Paid media · your agent | 1 business day | <Op verb="Conversation.answer" /> |
| Out of office | an auto-reply until Oct 28 | the reminder waits for the return date | nobody | the return date | <Op verb="Message.schedule" /> |
| Question it can’t answer | “Can you add a 20 % code for my followers?” | To a person: a discount is never the agent’s call | you | 1 business day | <Op verb="Conversation.escalate" /> |
| Stop | “Please stop running my post.” | every Ad on her posts pauses within 1 hour | nobody | 1 hour | <Op verb="Mandate.revoke" /> |

## When it hands to you
Ad approvals, rights Agreements and Limit raises come to **you** (Dana Okafor, person). One Brief per Role, as captured (`brief` is Not live yet, gaps #7).

```json title="What lands in each queue · sample"
[
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_655",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-14T17:00:00Z",
    "on": "post_377",
    "brief": {
      "who": "Jess Moreno, a landlord creator; post_377 on Instagram",
      "said": "How I send renewal notices 60 days out",
      "chose": "promote-the-post",
      "why": "2.1× her median hold; 90 days of rights in agreement_14",
      "spend": "$20 a day; 8 of 40 regions held back",
      "never": [
        "an edit to her or her voice",
        "enhancements on",
        "a Price the Offer lacks"
      ]
    }
  }
]
```

You answer with <Op verb="Approval.approve" /> in the Venue’s ad manager, <Op verb="Task.return" /> with a reason, or <Op verb="Action.redirect" />. Nothing spends until you approve; an approval left past its due time expires and the Ad never builds. A Limit raise is yours alone, through <Op verb="Limit.raise" />.

**On time:** you, 2 of 2 approved within 1 business day, median 3 h 20 min, n 2, ■□□□ Too early to tell beside Other Startups’ 90 % on time. **Your queue:** counted by kind: 1 Agreement and 1 Ad approval in week 1; since then, about 1 approval a month.

**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 rights email to a creator whose Conversation a person claimed | Leave it to the person who owns it: the draft waits in their queue. | <Op verb="Task.assign" /> |
| `approved-pages` (Not live yet, gaps #8) | a post that states a Product fact your claims source lacks | Keep it off the paid list, or publish the Page that says it. | <Op verb="Site.publish" /> |
| <a id="check-category"></a>`category` (the record’s Category stop) | an Audience or post the Venue would reject for the Offer’s category | Drop the Audience rule the Venue would reject. | <Op verb="Ad.update" /> |
| <a id="check-scale-gate"></a>`scale-gate` (the record’s Scale gate) | a Limit raise, a new Venue or fewer held-back regions before a winning readout | Wait for the holdout readout to win. | <Op verb="Metric.query" /> |

| Stop (pauses the Play) | Pauses when | Then |
| --- | --- | --- |
| <a id="stop-disclosure"></a>`disclosure` | a source post loses its disclosure line, toggle or partnership label | its Ads pause within 1 hour |
| <a id="stop-source-change"></a>`source-change` | a source post is edited, deleted or made private | every Ad on it pauses until the new version passes the screen |
| <a id="stop-rights"></a>`rights` | 1 hour before rights end, or within 1 hour of a revocation | every Ad on that post pauses |
| <a id="stop-safety"></a>`safety` | a creator safety flag | her Ads pause until you release them |
| <a id="stop-comment"></a>`comment` | hostile or false-claim comments over 10 % of 50+ in 24 h | that Ad pauses |
| <a id="stop-venue-rejection"></a>`venue-rejection` | a rejected or restricted Ad; 2 in 30 days | her Ads pause on that Venue; then the Play there |
| <a id="stop-payback"></a>`payback` | cost per first Transaction over the margin in your file, at 5+ first Transactions | the Play pauses |
| <a id="stop-zero-transaction"></a>`zero-transaction` | 14-day spend over 3× the margin with no first Transaction | the Play pauses |
| <a id="stop-refund"></a>`refund` | refunds on creator-Ad first Orders over 2× your 30-day baseline | the Play pauses |
| <a id="stop-spend-limit"></a>`spend-limit` | month-to-date spend reaches the $600 Limit | the Play pauses until the month turns |
| <a id="stop-conversion-feed"></a>`conversion-feed` | no conversion for 72 h while clicks flow | budget changes freeze; at 7 days the Play pauses |
| <a id="stop-drift"></a>`drift` | a live Ad differs from its archived post, or an enhancement switches on | that Ad pauses at once |
| <a id="stop-fence-breach"></a>`fence-breach` | 3 refused writes in one day | the Play drops to read-only |
| <a id="stop-kill-switch"></a>`kill-switch` | you press it | every creator Ad pauses; Jess is told |

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

```json title="The captured refusal · sample"
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The Ad from post_291 did not build: its added headline states a result no Page of yours backs.",
  "checks": [
    {
      "check": "approved-pages",
      "status": "fail",
      "doc": "/plays/creator-ads#check-approved-pages",
      "fix": "Cut the headline, or publish the Page that says it.",
      "then": "Site.publish"
    },
    {
      "check": "category",
      "status": "pass"
    }
  ]
}
```


```json title="The Stops that fired, as Campaign.paused reasons · sample"
[
  {
    "reason": {
      "limit": "payback",
      "observed": "$184 per first Transaction",
      "bound": "$26 first-payment margin",
      "window": "14d"
    },
    "doc": "/plays/creator-ads#stop-payback",
    "task": "task_602"
  }
]
```

## Did it work
The 40 regions were drawn at random, 8 held back from every creator Ad for two 28-day windows, so both halves read from the same assignment (rules m–o); the held-back counts are scaled ×4 to the served regions’ size. Each figure’s call is <Op verb="Metric.query" /> by node, and every node above the leaf is Not live yet (gaps #4).

`+4.0 Leads per $100 · ■■□□ Early sign · 40 regions · path → arr`

| Node | Served (32 regions) | Held back (8 regions, ×4) | Added | Confidence | Basis |
| --- | --- | --- | --- | --- | --- |
| `creator-ad-lead-lift` | 96 new Leads on $1,290 full cost | 44 expected (11 × 4) | +4.0 Leads per $100 [+0.9, +7.1] | ■■□□ Early sign | held back at random · 40 regions · 2 windows of 28 days |
| `new-leads` ↑ | 96 | 44 | +52 [+12, +92] | ■■□□ Early sign | the same assignment |
| `new-arr` ↑ | $2,436, 7 Customers · Booked $2,784: credited, not all caused by this Play | $1,392, 4 expected | +$1,044 [−$1,400, +$3,500] · Worth about +$500 a month | ■□□□ Too early to tell (7 vs 4 Customers) | the same · 6 trials still deciding |
| `net-new-arr` · `arr` | +$2,436 | +$1,392 | +$1,044, carried | ■□□□ Too early to tell | carried from `new-arr` |

The leaf counts new Leads in served regions above the held-back regions’ rate, per $100 of creator Ad spend with usage fees included, over each 28-day window.

**How it moves it:** the post that held Jess’s own viewers 2.1 times her median ran unedited to property managers like them, with the partnership label on.

**Guardrails:** treated against held back: cost per first Transaction (`play-payback`), $211 against your first-year margin of $290, and refunds on first Orders, 0 of 7.

```json title="The Campaign card · sample"
{
  "$id": "https://api.sb/leaseline.app/campaigns/creator-ads",
  "$type": "Campaign",
  "play": "play:creator-ads@1",
  "path": [
    "creator-ad-lead-lift",
    "new-leads",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "creator-ad-lead-lift",
    "unit": "ratio",
    "heldBack": 8,
    "decision": null
  },
  "readout": {
    "value": 4,
    "n": 40,
    "maturing": 0,
    "interval": [
      0.9,
      7.1
    ],
    "readability": "C",
    "basis": "held-back",
    "pooled": false
  },
  "ledger": {
    "spend": 1290,
    "workerCost": 2,
    "hours": 1.6,
    "pipelineArr": 2088,
    "wonArr": 2784,
    "projectedArr": 500,
    "paybackDays": 154
  }
}
```

Outside benchmark: none recorded for this Play yet; Other Startups’ results print beside every row.

**Before it · After it.** Before it: `creator-probe` finds the creator and `creator-partnership` signs her. After it: `promote-winners` holds it as one of its winning messages, and `instant-response` answers the Leads it sends.

## Example
Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days) with one creator, Jess Moreno, a landlord with 60 doors: 7 posts screened, 2 promoted at $20 a day, and 8 of 40 regions held back. Read every captured thread at `?threads=all`; three follow the tables.

| What happened, by route | Posts | Done | Leads · Customers (Booked: credited, not all caused by this Play) |
| --- | --- | --- | --- |
| Promote the post | 2 | 2 Ads, $1,120 spent, 1 build refused first | 96 · 7, $2,784 |
| Ask for rights · Keep it organic | 1 · 4 | 1 signed · — | — |
| At $600 a month (the Use it when volume) | 1 window of 28 days | reads once | Other Startups’ results: +3.1 per $100, ■■■□ Likely, n 96 |

| Day | Event | What happened | Your time |
| --- | --- | --- | --- |
| 0 | `event_118` Campaign.created | the three steps; the dry run fails `approved-pages` | 25 min |
| 3 | `event_160` Agreement.signed | Jess signs the rights clause: 90 days, $95 usage fee | 10 min |
| 5 | `event_188` Action.refused | `approved-pages` refused an added headline; the rebuild ran with Leaseline’s own line | — |
| 8 | `event_221` Ad.created | the first partnership Ad, approved by you; the first Lead on day 11 | 5 min |
| 14 | `event_290` Campaign.paused | `payback` at $184 per first Transaction against the $26 first-payment margin | — |
| 15 | `event_301` Change.merged | `change_27`: the margin in your file becomes the first year’s, $290 | 10 min |
| 47 | `event_655` Ad.created | the second Ad, from post_377 | 5 min |
| 1–56 | `event_150` Approval.created, first of 3 | you approved 2 Ads and 1 Agreement; weekly reviews, from the <Op verb="Task.next" /> log | 35 min · **total 1.6 h measured, 2 h asked** |

> **Jess Moreno, Instagram, Oct 10** · “How I send renewal notices 60 days out for 60 doors,” her own words and screen, with her paid-partnership line.¹
>
> **The Ad, Oct 14 to Oct 19** · the same post, unedited, labeled as a paid partnership with Leaseline, to property managers in 32 regions.² 41 new Leads in 6 days; Leaseline’s own line under it reads as Leaseline.³

```diff title="post_291, 2026-08-29 · the headline approved-pages refused, then the one that ran"
- Leaseline cuts late renewal notices by 90 %.
+ Leaseline sends each renewal notice 60 days out, per owner.
```

> **Jess, 2026-09-03 11:02** · “Can you add a 20 % code for my followers?” · **Paid media · your agent, 11:03** · *Thanks, Jess. Dana handles codes and replies by Sep 4.*⁴ The Brief went to you (`task_571`); you answered on Sep 3 at 16:40.

¹ The creator’s own disclosure line, in the post. ² The Venue’s paid-partnership label; nothing about her or her voice changed. ³ Text Leaseline adds speaks as Leaseline. ⁴ The routed line, compiled from the Role’s Settings.

## Your settings
```mdx title="plays/creator-ads.mdx"
---
holdout: 0.2      # 8 of 40 regions see no creator Ad
limit: 600        # dollars a month
margin: 290       # first-year margin per first Transaction
---
Run Jess’s posts that beat her median as paid partnership Ads, exactly as she posted them. I approve every Ad.
```

```text
$ npx startup-builder show plays/creator-ads
holdout 0.2 · limit 600 · margin 290     your file  plays/creator-ads.mdx:2-4,6 (Ask 2026-08-24; margin by change_27, 2026-09-08)
family demand · runs inside promote-winners · worker role:paid-media-manager, owns never · chooses none (D38) · sequences creator-rights-ask, creator-rights-renewal · checks owned-by-a-person, approved-pages, category, scale-gate · stops 14 · placements instagram, facebook, tiktok, gmail    catalog  play:creator-ads@1 (Not live yet, gaps #5)
```

### Every key from the catalog
| Key | Id | What it is |
| --- | --- | --- |
| Tactic | <a id="tactic-creator-rights-capture"></a>`creator-rights-capture` | Creator rights capture writes paid-usage rights into every creator Agreement before the post exists, and records the Venue’s partnership permission per post. Starts at You approve each one. |
| Tactic | <a id="tactic-creator-post-screen"></a>`creator-post-screen` | Creator post screen qualifies a post for spend when it beats its cell’s median hold rate, shows coded Orders or buyer questions, and passes checks. Starts at Sends nothing. |
| Tactic | <a id="tactic-category-audience-rules"></a>`category-audience-rules` | Category audience rules turn the targeting each Venue offers the Offer’s category, and the Startup’s exclusions, into the saved query of every Audience a paid Play syncs. Starts at Sends nothing. |
| Tactic | <a id="tactic-partnership-ad-build"></a>`partnership-ad-build` | Partnership ad build creates a paused Ad from a creator’s post through the Venue’s partnership path, under the creator’s Mandate, label on. Starts at You approve each one. |
| Tactic | <a id="tactic-creator-post-watch"></a>`creator-post-watch` | Creator post watch reads each promoted post and its creator daily, pauses Ads on any change or rights end, and reports spend weekly. Starts at Sends nothing. |
| Tactic | <a id="tactic-winner-promotion"></a>`winner-promotion` | Winner promotion runs a free-placement winner as a paused, fenced Ad against its control, and judges it on counted conversions from Stripe. Starts at You approve each one. |
| Tactic | <a id="tactic-ad-write-proxy"></a>`ad-write-proxy` | Ad write proxy is the only write path to an ads Venue, holding the token outside the model and forcing every create to paused. Starts at You approve each one. |
| Tactic | <a id="tactic-creative-drift-monitor"></a>`creative-drift-monitor` | Creative drift monitor reads every live Ad each day, diffs it against its approved cut and settings, and pauses any Ad that changed. Starts at Sends nothing. |
| Tactic | <a id="tactic-incrementality-holdout"></a>`incrementality-holdout` | Incrementality holdout measures the first Transactions a paid arm adds, by a geo holdout or a day switchback, before any scale step. Starts at You approve each one. |
| Tactic | <a id="tactic-payback-gate"></a>`payback-gate` | Payback gate pauses a paid Play the moment its cost per first Transaction outruns first-transaction margin, with no approval and no wait. Starts at Sends nothing. |
| Trigger | <a id="trigger-creator-post-live"></a>`creator-post-live` | Creator post live: `event` on `Post.published`, window 30d. |
| Trigger | <a id="trigger-creator-post-changed"></a>`creator-post-changed` | Creator post changed: `event` on `Post.edited`, window 1h. |
| Trigger | <a id="trigger-rights-revoked"></a>`rights-revoked` | Rights revoked: `event` on `Mandate.revoked`, window 1h. |
| Trigger | <a id="trigger-rights-expiring"></a>`rights-expiring` | Rights expiring: `at` on `Monitor.checked`, window 14d. |
| Trigger | <a id="trigger-creator-safety-flag"></a>`creator-safety-flag` | Creator safety flag: `event` on `Post.published`, window 1d. |
| Trigger | <a id="trigger-ad-rejected"></a>`ad-rejected` | Ad rejected: `event` on `Ad.rejected`, window 1d. |
| Trigger | <a id="trigger-venue-rule-change"></a>`venue-rule-change` | Venue ad change: `event` on `Monitor.checked`, window 7d. |
| Trigger | <a id="trigger-ad-fatigue"></a>`ad-fatigue` | Ad fatigue: `threshold` on `Monitor.checked`, window 3d. |
| Trigger | <a id="trigger-holdout-closed"></a>`holdout-closed` | Holdout closed: `event` on `Experiment.matured`, window 7d. |
| Trigger | <a id="trigger-margin-change"></a>`margin-change` | Margin change: `event` on `Offer.repriced`, window 1d. |
| Sequence | <a id="sequence-creator-rights-ask"></a>`creator-rights-ask` | Creator rights ask: 3 steps; it ends on The creator signs.; The creator declines.; Day 7 passes with no signature, and the post stays organic.. |
| Sequence | <a id="sequence-creator-rights-renewal"></a>`creator-rights-renewal` | Creator rights renewal: 3 steps; it ends on The creator signs the renewal.; The creator declines.; The rights term ends.. |