URL: /plays/sibling-audiences · Id: `play:sibling-audiences`

# Sibling audiences

> Shows your cold Ads to Contacts your other Startup collected, after each daily build removes every opt-out, and holds a share back to price it.

Shows your cold [Ads](https://startupbuilder.dev/business/nouns/ad) to [Contacts](https://startupbuilder.dev/business/nouns/contact) your other [Startup](https://startupbuilder.dev/business/nouns/startup) collected, after each daily build removes every opt-out, and holds a share back to price it.

```text title="Set it up · Ask"
Be our paid media lead: show Leaseline’s best cold Ad, unchanged, to the people our other Startup collected, rebuilt daily with every opt-out removed first. Hold 30 % of them back so we see what it adds, and watch that the other Startup loses no one. $200 a month. Show me what’s missing; don’t spend.
```

```text title="Run one · Ask"
Hand today’s sister Audience build to the paid media agent and show me what it chose and why. Don’t upload.
```

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

const { events: [last] } = await $.Event.list({ where: 'name in ("Schedule.fired", "Consent.withdrawn", "Contact.created", "Order.paid", "Subscription.canceled", "Offer.published", "Startup.graduated", "Complaint.filed", "Audience.resized", "Experiment.matured")', 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_903",
    "$type": "Decision",
    "choice": "add-to-audience",
    "reason": "38 new host Contacts passed fresh reads; 11 removals were uploaded and acknowledged first; 16 drawn into the held-out 30 % stay out",
    "stakes": "low",
    "options": [
      "add-to-audience",
      "hold-out",
      "leave-out",
      "pair-two-startups",
      "answer-a-report",
      "run-a-lookalike"
    ],
    "by": "worker_7",
    "on": "audience_12",
    "expected": "removals acknowledged within 24h; first paid Orders per $100 above the held-out rate by the block’s end",
    "reopensWhen": "a removal unacknowledged at 24h, or a canary still in the Audience"
  },
  "actions": [
    {
      "$id": "https://api.sb/leaseline.app/actions/action_1",
      "$type": "Action",
      "status": "done",
      "mode": "try",
      "by": "worker_7",
      "verb": "Collection.query",
      "checks": [
        {
          "check": "fresh-reads",
          "status": "pass"
        }
      ]
    },
    {
      "$id": "https://api.sb/leaseline.app/actions/action_2",
      "$type": "Action",
      "status": "done",
      "mode": "try",
      "by": "worker_7",
      "verb": "Audience.update",
      "checks": [
        {
          "check": "removals-first",
          "status": "pass"
        }
      ]
    },
    {
      "$id": "https://api.sb/leaseline.app/actions/action_3",
      "$type": "Action",
      "status": "pending",
      "reason": "awaitingAcknowledgment",
      "mode": "try",
      "by": "worker_7",
      "verb": "Audience.update",
      "checks": [
        {
          "check": "consent-stop",
          "status": "pass"
        },
        {
          "check": "first-party",
          "status": "pass"
        },
        {
          "check": "fresh-reads",
          "status": "pass"
        }
      ]
    }
  ]
}
```

`action_2` uploads today’s 11 removals. `action_3` adds the 38 new members only once the Venue acknowledges every removal; no file leaves your account, and the Audience name carries no Startup or Market.

`+2.6 added first orders per $100 · ■□□□ Too early to tell · n 4,200 · path → arr`

| Try another: the daily build | Choice | Reason |
| --- | --- | --- |
| Today’s build: 38 new host Contacts, 11 removals acknowledged first | `add-to-audience` | fresh reads, collected by the host, outside the holdout |
| A host Contact drawn into the held-out 30 % on Aug 24 | `hold-out` | out of every sister ad set for the block |
| A host Contact who unsubscribed from the sister product an hour ago | `leave-out` | an opt-out at any of your Startups removes them |
| “How did this ad know me?” | `answer-a-report` | the fixed answer: the privacy notice, the entity and a one-step opt-out |

| Worth | Your time | Spend | First signal | Use it when | Instead |
| --- | --- | --- | --- | --- | --- |
| ≈ +$970 ARR a month at $200 | 30 min week 1, then 10 a week | $14 per added first order, ~$200 a month | Day 4: the first signup from the sister Audience | another Startup of yours with 2,000+ Contacts | No other Startup: `retargeting` · no cold winner: `promote-winners` |

**Where it sits:** **Stranger** → Lead → Trialing → Activated → At risk → Churned → Won back · Sibling audience lift → Sent by your other Startups → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +1.4 first paid Orders per $100 (Other Startups’ results; your own read is too early) × $200 a month × $347 Pro ARR ≈ +$972. Under First signal: One 90-day block per read: about 13 weeks to tell +1.4 per $100 at 4,200 Contacts with 30 % held out; under 2,000, 90 days can tell only +3.5 or more.

`sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Schedule.fired · first daily build 6 min, removals first · 8 keys Not live yet`

## Start it this week
```bash
npx startup-builder add play sibling-audiences   # 1 · writes plays/sibling-audiences.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":"sibling-audiences"}'

# 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":"sibling-audiences"}'

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

# off: every sister ad set pauses and uploads stop
curl -X PATCH https://api.sb/leaseline.app/campaigns/sibling-audiences \
  -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": "sibling-audiences can’t start yet: 1 check fails and 1 warns.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "your other Startup: 4,200 Contacts it collected; Lists overlap on small landlords",
      "doc": "/plays/sibling-audiences#check-use-when",
      "fix": "Pair with a Startup of yours holding 2,000 or more Contacts, or run retargeting.",
      "then": "Metric.query"
    },
    {
      "check": "baseline",
      "status": "pass",
      "observed": "0.16 first paid Orders per 100 host Contacts with no Ads, n 4,200",
      "doc": "/plays/sibling-audiences#check-baseline",
      "fix": "Read it once; it fills Before in Your number.",
      "then": "Metric.query"
    },
    {
      "check": "removals-first",
      "status": "fail",
      "observed": "the Facebook connection returns no removal acknowledgments",
      "doc": "/plays/sibling-audiences#check-removals-first",
      "fix": "Reconnect with the Audience scope that acknowledges removals.",
      "then": "Integration.reconnect"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "marketing-lead"
      ],
      "owned": 0,
      "doc": "/plays/sibling-audiences#check-role-unstaffed",
      "fix": "Staff the Marketing Lead, or leave it: pairings and reports 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: 4,200 host Contacts; 0.16 per 100, n 4,200 (gaps #8) | <Op verb="Metric.query" /> on `sibling-audience-lift`, which fills Before in Your number | 1 min | none |
| <a id="check-removals-first"></a>`removals-first` · fail: no removal acknowledgments | <Op verb="Integration.reconnect" /> with the Audience scope | 5 min | none |
| <a id="check-role-unstaffed"></a>`role-unstaffed` · warn (gaps #8): no Marketing Lead | <Op verb="Role.staff" />, or leave it: pairings and reports come to you | 0 min | none |

`Your number · Before 0.16 · Now 2.6 added first orders per $100 · Target 2.0 by Jan 21 · ■□□□ Too early to tell · n 4,200 · the block ends Nov 21`

The Ads cost what the Venues bill, capped at $200 a month by your Limit; the daily build, the removal audit and the canaries cost about $0.15 a day (Worker cost). That comes to about $14 for each added first order at Other Startups’ rate.

## When it starts
| When | Trigger id | Starts on | Window | How it gets in |
| --- | --- | --- | --- | --- |
| The daily build time | `sibling-build-due` | `at` on `Schedule.fired` where the daily build time in your file, for every exposed pair | removals acknowledged before any addition | the host’s Contacts, read in your account; nothing leaves as a file |
| Someone opts out or is suppressed at any of your Startups | `pool-opt-out` | `event` on `Consent.withdrawn` where an opt-out, withdrawal or Suppression a Person records at any of your Startups | out of every Audience at the next build, within 24 h | <Op verb="Contact.unsubscribe" /> and <Op verb="Contact.suppress" /> at either Startup |
| A sister Audience member pays Leaseline for the first time | `receiver-first-order` | `event` on `Order.paid` where a receiver's first paid Order from a Person in a randomized pair | 90d | <Op verb="Integration.connect" /> (Stripe) |
| + 5 more for signups, host cancels, a Startup leaving, knowledge reports and the block start (`?lanes=all`) | | | | |

```json title="One signed delivery · StartupBuilder-Signature"
{
  "$id": "https://api.sb/leaseline.app/events/event_9701",
  "$type": "Event",
  "name": "Schedule.fired",
  "at": "2026-10-19T05:00:00Z",
  "seq": 9701,
  "data": {
    "audience": "audience_12",
    "trigger": "sibling-build-due",
    "added": 38,
    "removed": 11,
    "heldOut": 16,
    "readsAgeMinutes": 12
  }
}
```

```bash title="Reproduce it in test"
npx startup-builder trigger Schedule.fired --like event_9701   # replays the daily build
npx startup-builder clock advance --by 1d   # runs the removal audit and the next build
npx startup-builder listen Consent.withdrawn --forward-to http://localhost:3000/hook
```

## Who runs it
**Paid media · your agent** (`role:paid-media-manager`, `worker_7`) holds the Key Result. Pairing two Startups, any lookalike and every knowledge report come to **you** (Dana Okafor, person, `worker_1`), because the Marketing Lead Role has no person. It writes to no one; it builds Audiences. Your number links to Did it work.

| Option | Rung today | Evidence (passed of n) | Moves up at | Drops back when | You can |
| --- | --- | --- | --- | --- | --- |
| Add to the sister Audience · Hold out · Leave them out | It does it | 2,940 · 1,260 · 214 | — | a removal unacknowledged at 24 h → every sister ad set pauses | <Op verb="Action.redirect" /> |
| Answer a knowledge report | You approve each one | 1 of 1 | never: it answers in your name | — | <Op verb="Approval.approve" /> |
| Pair two Startups · Run a lookalike | You approve each one | 1 of 1 · 0 | never | — | <Op verb="Approval.approve" /> · <Op verb="Approval.refuse" /> |
| Change the held-out share or the block length | You approve each one; next block only | 0 merged | never | — | <Op verb="Change.merge" /> · <Op verb="Change.revert" /> |
| Never: an Ad written for them, an Ad that names the other Startup, a bought or matched member | Refused, every time | 1 concept refused | never | — | nothing; the Checks hold it |

**What it reads · What it may call.** It reads the host’s own Contacts with Suppression, Consent and opt-out reads under 1 hour old, and Leaseline’s approved cold concepts. No Ad names, mimics or borrows the other Startup, or implies anything a Person did there. Its tools are <Op verb="Audience.update" />, <Op verb="Flag.evaluate" />, <Op verb="Audience.create" />, <Op verb="Conversation.answer" />, <Op verb="Contact.suppress" />, <Op verb="Ad.create" />, and any other call becomes an Approval under the Role’s Mandate.

```md title="The brief (folded): compiled Agent-register Markdown · play:sibling-audiences@1 · each line names its record key"
You hold the paid media Key Result: 2.0 added first orders per $100 by 2027-01-21. ← worker, metric
Each day, upload removals, wait for every acknowledgment, then add.              ← removals-first
Only Contacts the host collected, read fresh within the hour.                    ← first-party, fresh-reads
Hold 30 % out for each 90-day block.                                             ← your file, line 2
Run Leaseline’s approved cold concepts unchanged; never write one for them.      ← copyRules 1, 2
Watch the host: its cancellations among the exposed never rise past held out.    ← host-churn
```

**The slow loop.** The block runs to Nov 21 and no Change can touch its held-out share inside it, so there is no replay or read-back to print.

**Bring your own agent** (folded) starts at It does it for builds only when it matches the seated agent’s removals-first order on the eval suite; spend and pairing stay with you. <Op verb="Role.staff" /> seats it.

```bash
npx startup-builder eval --scenario sibling-audiences-4200 --agent "claude -p" --seat paid-media-manager   # seated: every removal acknowledged before additions, 0 Checks failed served · yours: 1 addition before an acknowledgment, refused
```

## What it can do next
| Option | Picked when | Decided by | Runs | Hands to | If it’s just you |
| --- | --- | --- | --- | --- | --- |
| Add to the sister Audience `add-to-audience` | a Contact the host collected, fresh reads, no opt-out, outside the holdout | Your rule (line 4) | <Op verb="Audience.update" />, after the day’s removals are acknowledged | nobody | the same |
| Hold out `hold-out` | drawn into the 30 % at the block’s start | Your rule (line 2) | <Op verb="Flag.evaluate" />: out of every sister ad set for 90 days | nobody | the same |
| Leave them out `leave-out` | an opt-out, a Suppression, no Consent your file asks for, or not collected by the host | Your rule (the Guard) | nothing; the Guard holds them and logs a private reason | nobody | the same |
| Pair two Startups `pair-two-startups` | Lists overlap and Offers complement each other | Agent’s call, with its reason | <Op verb="Audience.create" /> for the pair, after your approval | you approve the pair · Take this one | you |
| Answer a knowledge report `answer-a-report` | someone says an Ad seemed to know them | Your rule (copy rule 10) | <Op verb="Conversation.answer" /> with the privacy notice → on request <Op verb="Contact.suppress" /> | you approve it, due 1 business day · Take this one | you |
| Run a lookalike `run-a-lookalike` | the list arm already won its read | Agent’s call, with its reason | <Op verb="Audience.create" /> seeded from paying host Customers → <Op verb="Ad.create" />, read by region | you approve it · Take this one | you |

| When they write back | Fixture reply | What happens | Who answers | By when | Call |
| --- | --- | --- | --- | --- | --- |
| Interested | a click to Leaseline’s trial Page from the cold concept | Leaseline’s standard Offer Page; nothing changes for a sister Audience | nobody | — | <Op verb="Audience.update" /> |
| Send me pricing | a comment: “What does Leaseline cost?” | the Pricing Page’s list Price, as it stands | Paid media · your agent | 1 h | <Op verb="Conversation.answer" /> |
| Not now | a hide on the Ad | that ad set stops for them | nobody | at once | <Op verb="Audience.update" /> |
| Wrong person | a comment: “I don’t manage property.” | a plain answer; they leave the sister Audience | Paid media · your agent | 1 h | <Op verb="Conversation.answer" /> |
| Out of office | an auto-reply to a trial email | the trial’s own notices wait for the return date | nobody | the return date | <Op verb="Message.schedule" /> |
| Question it can’t answer | “How did this ad know me?” | the fixed answer: the privacy notice, the entity it names, and the one-step opt-out | you approve it | 1 business day | <Op verb="Conversation.answer" /> |
| Stop | “Stop showing me ads.” | out of every Audience at every one of your Startups within 24 h | nobody | at once | <Op verb="Contact.suppress" /> |

## When it hands to you
This Play hands no buyer to a person. What lands in **your** queue is the pairing, any lookalike and each knowledge report, because the Marketing Lead Role has no person. As captured (`draft` and `checks` are Not live yet, gaps #7).

```json title="What lands in each queue · sample"
[
  {
    "$id": "https://api.sb/leaseline.app/approvals/approval_151",
    "$type": "Approval",
    "verdict": "approved",
    "deadline": "2026-08-25T17:00:00Z",
    "draft": "Pair: your other Startup hosts, Leaseline receives; Lists overlap on small landlords; 30 % held out; $200 a month",
    "route": "pair-two-startups",
    "checks": [
      {
        "check": "first-party",
        "status": "pass"
      },
      {
        "check": "removals-first",
        "status": "pass"
      }
    ]
  },
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_914",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-02T17:00:00Z",
    "on": "contact_388",
    "brief": {
      "who": "a commenter on the cold concept",
      "said": "How did this ad know me?",
      "chose": "answer-a-report",
      "why": "a knowledge report gets the fixed answer, in your name",
      "never": [
        "arguing",
        "naming what they did anywhere"
      ]
    }
  }
]
```

You answer with <Op verb="Approval.approve" /> or <Op verb="Approval.refuse" />, <Op verb="Task.claim" /> (Take this one) or <Op verb="Task.return" /> with a reason, each a one-call window. A suppression request never waits on you: it leaves every Audience at the next build. A Task nobody claims by its due time goes up a Role through <Op verb="Task.escalate" />, and `person-promise` fires.

**On time:** you, 2 of 2 within 1 business day, n 2, ■□□□ Too early to tell beside Other Startups’ 95 % on time. **Your queue:** in week 1, the pairing and 2 concepts to approve; then about 1 report a month and the weekly review.

**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-fresh-reads"></a>`fresh-reads` (the record’s Fresh reads only) | an upload whose Suppression, Consent or opt-out read is over 1 h old | Read again; the upload runs on reads under 1 h old. | <Op verb="Collection.query" /> |
| `removals-first` (the record’s Removals first) | an addition before the Venue acknowledges every removal in the build | Wait for the acknowledgments; additions follow. | <Op verb="Audience.update" /> |
| <a id="check-first-party"></a>`first-party` (the record’s First-party only) | a member whose identifier the host did not collect from the Person | Use only Contacts the host collected itself. | <Op verb="Audience.update" /> |
| <a id="check-knowledge-hold"></a>`knowledge-hold` (the record’s Knowledge hold) | a concept that names, mimics or borrows the host, or implies what a Person did there | Run Leaseline’s approved cold concept unchanged. | <Op verb="Ad.update" /> |
| <a id="check-consent-stop"></a>`consent-stop` (gaps #3) | a member with no advertising Consent in a Market your file marks consent-first | Leave them out until a Consent is recorded. | <Op verb="Message.schedule" /> |
| <a id="check-claims-resolve"></a>`claims-resolve` (hub) | an Ad sentence no approved Page backs | Cut the sentence, or publish the Page that says it. | <Op verb="Content.draft" /> |
| <a id="check-price"></a>`price` (gaps #1) | a Price in an Ad that differs from the Offer’s live Price | Quote the Pricing Page’s live Price. | <Op verb="Approval.approve" /> |

| Stop (pauses the Play) | Pauses when | Then |
| --- | --- | --- |
| <a id="stop-removal-lag"></a>`removal-lag` | a removal unacknowledged 24 h after it was written | every sister ad set on that Venue pauses |
| <a id="stop-membership-leak"></a>`membership-leak` | an uploaded member the Guard refuses today | every sister ad set on that Venue pauses |
| <a id="stop-canary"></a>`canary` | a canary still in an Audience after its next removal batch | the Play pauses on every Venue and drops to You approve each one |
| <a id="stop-market-consent"></a>`market-consent` | a member in a consent-first Market with no advertising Consent | the Play pauses on every Venue |
| <a id="stop-pool-exit"></a>`pool-exit` | a Startup leaves the pool | its pairs end; its Contacts leave every Audience within 24 h |
| <a id="stop-knowledge-report"></a>`knowledge-report` | 2 knowledge reports on one pair in 30 days; 5 across the Play | the pair pauses; 5 pause the Play |
| <a id="stop-withdrawal"></a>`withdrawal` | sister-product opt-outs among the exposed above held out by 2 per 1,000 in a block, over 5,000 | the receiver pauses |
| <a id="stop-host-churn"></a>`host-churn` | at 90 days, host cancellations among the exposed above held out by 1 per 100 | every pair of the receiver pauses |
| <a id="stop-audience-floor"></a>`audience-floor` | an Audience under its Venue’s minimum | its ad set holds; it never widens to keep spending |
| <a id="stop-frequency"></a>`frequency` | an ad set’s 7-day frequency above 10 | that ad set pauses |
| <a id="stop-yield-floor"></a>`yield-floor` | a loser Readout | the receiver’s sister ad sets end; a Decision opens |
| <a id="stop-spend-limit"></a>`spend-limit` | month-to-date spend reaches the Limit | the Play pauses until the month turns (<Op verb="Limit.raise" />) |
| <a id="stop-kill-switch"></a>`kill-switch` | you press it | every sister ad set and lookalike pauses through the proxy; uploads stop |

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

```json title="The captured refusal · sample"
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The concept did not run in the sister ad set: it addresses the other Startup’s users by name.",
  "checks": [
    {
      "check": "knowledge-hold",
      "status": "fail",
      "doc": "/plays/sibling-audiences#check-knowledge-hold",
      "fix": "Run Leaseline’s approved cold concept unchanged.",
      "then": "Ad.update"
    },
    {
      "check": "price",
      "status": "pass"
    }
  ]
}
```


```json title="The Stops that fired, as Campaign.paused reasons · sample"
[
  {
    "reason": {
      "limit": "removal-lag",
      "observed": "3 removals unacknowledged at 26h",
      "bound": "24h",
      "window": "Facebook, Sep 15 build"
    },
    "doc": "/plays/sibling-audiences#stop-removal-lag",
    "task": "task_902"
  }
]
```

## Did it work
The host’s Contacts were held out at random, 30 % for the block that ends Nov 21 (rules m–o); each figure’s call is <Op verb="Metric.query" /> by node and by arm, and every node above the leaf is Not live yet (gaps #4).

`+2.6 added first orders per $100 · ■□□□ Too early to tell · n 4,200 · path → arr`

| Node | Agent half (exposed, 70 %) | Your half (held out, 30 %) | Added | Confidence | Basis |
| --- | --- | --- | --- | --- | --- |
| `sibling-audience-lift` | 14 first paid Orders of 2,940 (0.48 per 100) on $360, 0 more host cancels than held out | 2 of 1,260 (0.16 per 100) | +2.6 per $100 [−0.1, 4.8] | ■□□□ Too early to tell | held back at random · n 4,200 · 34 days left in the block · Other Startups’ results +1.4, ■■■□ Likely, n 61,000 |
| `sibling-sourced-share` | 14 new Customers sent by your other Startup | 2 | +9.3 [−0.3, 18.5] | ■□□□ Too early to tell | the same assignment |
| `new-arr` ↑ | $4,858, 14 Customers on Pro · Booked: credited, not all caused by this Play (kind `sibling`) | $694, 2 Customers | +$3,239 [−$149, +$6,626] · Worth about +$970 a month | ■□□□ Too early to tell (14 vs 2 Customers) | the same · 6 trials still deciding |
| `net-new-arr` · `arr` | +$4,858 | +$694 | +$3,239, carried: it moves no other bridge term | ■□□□ Too early to tell | carried from `new-arr` |

The leaf counts Leaseline first paid Orders from the host’s Contacts, exposed against held out, less any rise in the host’s cancellations, per $100 of sister spend over the 90-day block; the block reads on Nov 21.

**How it moves it:** people who already pay your other Startup saw Leaseline’s best cold concept, unchanged, at a 7-day frequency of 3.2.

**Guardrails:** exposed against held out, the pair under `sibling-sourced-share`: host cancellations, 1.9 against 2.3 per 100 host Customers, and sister-product opt-outs, 1.0 against 0.8 per 1,000.

```json title="The Campaign card · sample"
{
  "$id": "https://api.sb/leaseline.app/campaigns/sibling-audiences",
  "$type": "Campaign",
  "play": "play:sibling-audiences@1",
  "path": [
    "sibling-audience-lift",
    "sibling-sourced-share",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "sibling-audience-lift",
    "unit": "ratio",
    "heldBack": 1260,
    "decision": null
  },
  "readout": {
    "value": 2.6,
    "n": 4200,
    "maturing": 4200,
    "interval": [
      -0.1,
      4.8
    ],
    "readability": "inadmissible",
    "basis": "held-back",
    "pooled": false
  },
  "ledger": {
    "spend": 360,
    "workerCost": 8,
    "hours": 1.4,
    "pipelineArr": 0,
    "wonArr": 4858,
    "projectedArr": 972,
    "paybackDays": 27
  }
}
```

Outside benchmark: this Play’s catalog record carries no sourced range yet, so Other Startups’ results stand in: +1.4 added first orders per $100, ■■■□ Likely, n 61,000 Contacts.

**Before it · After it.** Before it: `family-opt-in` and your other Startup’s own Plays collect the Contacts it hosts. After it: `product-led` and `instant-response` take the trials and forms it brings, and `cross-sell` holds the sister-product Offers inside each product.

## Example
Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days) as the receiver, with Unitledger, Dana’s other Startup, as the host: 4,414 host Contacts, 214 left out by the Guard, and 4,200 assigned, 2,940 exposed and 1,260 held out, on Facebook and Instagram at about $6.40 a day. Read every captured Ad and comment at `?threads=all`; three follow the tables.

| What happened, by option | Decisions | People | First paid Orders (counts) |
| --- | --- | --- | --- |
| Add to the sister Audience | 56 daily builds | 2,940 exposed | 14 |
| Hold out · Leave them out | 1 draw · 214 | 1,260 · 214 | 2 · — |
| Pair two Startups · Answer a knowledge report · Run a lookalike | 1 · 1 · 0 | 1 pair · 1 answer · — | — |
| **Exposed** · held out | **2,940** · 1,260 | **$360** · $0 | **14** · 2 |
| At 2,000 host Contacts (the Use it when volume) | about 1,400 exposed | held back at random, 30 % | Other Startups’ results: +1.4 per $100, ■■■□ Likely, n 61,000 |

| Day | Event | What happened | Your time |
| --- | --- | --- | --- |
| 0 | `event_9602` Campaign.created | the three steps; the dry run fails `removals-first` | 15 min |
| 0 | `event_9605` Integration.reconnected | the Audience scope that acknowledges removals | 5 min |
| 1 | `event_9611` Approval.approved | you approved the pair and 2 cold concepts | 10 min |
| 4 | `event_9630` Contact.created | the first Leaseline signup from the sister Audience | — |
| 22 | `event_9655` Campaign.paused | `removal-lag` on Facebook: 3 removals at 26 h; resumed when acknowledged | 6 min |
| 39 | `event_9672` Task.claimed | you answered the knowledge report with the fixed answer | 8 min |
| 1–56 | `event_9610` Approval.created, first of 4 | you approved the pair, 2 concepts and 1 answer; `knowledge-hold` refused 1 concept; weekly reviews | 56 min · **total 1.4 h measured, 1.5 h asked** |

> **Leaseline’s cold concept, Instagram, Sep 9** · Every renewal notice, 60 days out, for every owner you manage. Try Leaseline free for 14 days.¹
>
> **A small landlord who keeps her books in Unitledger, exposed, Sep 10** · started a trial; paid for Pro on Sep 24: +$347 ARR, an Acquisition of kind `sibling`.²

```diff title="The sister ad set, 2026-08-25 · the concept knowledge-hold refused, then the concept that ran"
- Already on Unitledger? Add Leaseline and your renewals sync with your books.
+ Every renewal notice, 60 days out, for every owner you manage. Try Leaseline free for 14 days.
```

> **A commenter, 2026-10-01 18:20** · “How did this ad know me?” · **The agent, 18:21** · drafted the fixed answer and assigned it to you (`task_914`), due tomorrow 17:00 · **Dana, Oct 2 09:05** · posted it: the privacy notice, the entity it names and a one-step opt-out.³ They opted out; they left every Audience at the next build.

¹ Leaseline’s approved cold concept, unchanged: nothing written for the sister Audience. ² Credit through `noun:acquisition` with kind `sibling`; the sister product’s own cancellations read beside it. ³ The answer copy rule 10 fixes: never an argument.

## Your settings
```mdx title="plays/sibling-audiences.mdx"
---
holdout: 0.3      # 30 % of the host’s Contacts held out for each 90-day block
budget: $200/month
---
Rebuild daily: removals first, then additions, on reads under 1 hour old.
Run Leaseline’s approved cold concepts only, unchanged.
```

```text
$ npx startup-builder show plays/sibling-audiences
holdout 0.3 · budget $200/month · daily build, removals first · cold concepts unchanged     your file  plays/sibling-audiences.mdx:2,3,5,6 (Ask 2026-08-24)
worker role:paid-media-manager, owns never · chooses 6 (4 rule, 2 read) · approval first-send, every-send · checks fresh-reads, removals-first, first-party, knowledge-hold, consent-stop, claims-resolve, price · stops 13 · placements facebook, instagram, linkedin, google-display    catalog  play:sibling-audiences@1 (Not live yet, gaps #5)
```

### Every key from the catalog
| Key | Id | What it is |
| --- | --- | --- |
| Tactic | <a id="tactic-audience-pairing"></a>`audience-pairing` | Audience pairing picks host and receiver Startups each week whose ICPs overlap and whose Offers complement each other, for one owner approval per pair. Starts at You approve the first wave. |
| Tactic | <a id="tactic-sibling-audience-guard"></a>`sibling-audience-guard` | Sister audience guard decides, per Person and pair before each upload, whether a host Contact may join a receiver’s Audience, and logs a private reason. Starts at Sends nothing. |
| Tactic | <a id="tactic-sibling-audience-build"></a>`sibling-audience-build` | Sister audience build rebuilds each exposed pair’s hashed Audience daily, uploads removals before additions, and shares it to the receiver without a file. Starts at You approve each one. |
| Tactic | <a id="tactic-sibling-audience-creative"></a>`sibling-audience-creative` | Sister audience creative runs only the receiver’s approved cold concepts in sister ad sets, unchanged, after a knowledge check and a claims check. Starts at You approve each one. |
| Tactic | <a id="tactic-sibling-audience-pacing"></a>`sibling-audience-pacing` | Sister audience pacing splits the Play’s Limit across exposed pairs, cuts tiring ad sets, and pauses a receiver that spends without a first paid Order. Starts at Sends nothing. |
| Tactic | <a id="tactic-sibling-removal-audit"></a>`sibling-removal-audit` | Sister removal audit proves each opt-out leaves every sister Audience, with fresh reads, Venue acknowledgments and weekly canaries, and pauses on a gap. Starts at Sends nothing. |
| Tactic | <a id="tactic-sibling-audience-readout"></a>`sibling-audience-readout` | Sister audience readout randomizes pairs by Startup cluster each 90 days and reads incremental receiver Acquisitions net of host cancellations per $100. Starts at Sends nothing. |
| Tactic | <a id="tactic-sibling-lookalike"></a>`sibling-lookalike` | Sister lookalike runs a lookalike Audience seeded from exposed hosts’ paying Customers, for a receiver whose list arm already won, read by a geo holdout. Starts at You approve each one. |
| Tactic | <a id="tactic-sibling-exclusion"></a>`sibling-exclusion` | Sibling exclusion decides, before every sibling render, Message and Audience sync, whether a Person may see a receiver’s Offer, and logs the reason. Starts at Sends nothing. |
| 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-ad-drift-monitor"></a>`ad-drift-monitor` | Ad drift monitor diffs every live Ad’s rendered creative, text and enhancement settings against the approved source daily, and pauses or resets what drifted. 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. |
| Tactic | <a id="tactic-ad-tag-consent-gate"></a>`ad-tag-consent-gate` | Ad tag consent gate decides on every Visit which Venue tags load, by the Visitor’s Market, Consent and opt-out signal, before any tag fires. Starts at Sends nothing. |
| Trigger | <a id="trigger-sibling-build-due"></a>`sibling-build-due` | Sibling build due: `at` on `Schedule.fired`, window 1d. |
| Trigger | <a id="trigger-pool-opt-out"></a>`pool-opt-out` | Pool opt-out: `event` on `Consent.withdrawn`, window 1h. |
| Trigger | <a id="trigger-receiver-sign-up"></a>`receiver-sign-up` | Receiver sign-up: `event` on `Contact.created`, window 1h. |
| Trigger | <a id="trigger-receiver-first-order"></a>`receiver-first-order` | Receiver first order: `event` on `Order.paid`, window 90d. |
| Trigger | <a id="trigger-host-cancel"></a>`host-cancel` | Host cancel: `event` on `Subscription.canceled`, window 90d. |
| Trigger | <a id="trigger-sibling-offer-change"></a>`sibling-offer-change` | Sibling offer change: `event` on `Offer.published`, window 7d. |
| Trigger | <a id="trigger-sibling-left-pool"></a>`sibling-left-pool` | Sibling left pool: `event` on `Startup.graduated`, window 1d. |
| Trigger | <a id="trigger-ad-knowledge-report"></a>`ad-knowledge-report` | Ad knowledge report: `event` on `Complaint.filed`, window 1d. |
| Trigger | <a id="trigger-pair-block-start"></a>`pair-block-start` | Pair block start: `at` on `Schedule.fired`, window 90d. |
| Trigger | <a id="trigger-audience-floor-crossed"></a>`audience-floor-crossed` | Audience floor crossed: `threshold` on `Audience.resized`, window 7d. |
| Trigger | <a id="trigger-holdout-closed"></a>`holdout-closed` | Holdout closed: `event` on `Experiment.matured`, window 7d. |