Early Signal Cut
Shared quality bar: ../references/output-standard.md. All numbers cited here live in ../references/thresholds.md.
Every verdict here is low confidence by definition, and that is the point
rather than a caveat. A buyer shipping dozens of creatives a month gets
needs_data on most of the library, because most creatives never reach
test.volume_floor. This layer trades a stated error rate for throughput.
Nothing it returns is a result.
Use this skill when
A batch launched in the last few days, the ad set is spending, and the decision
is which ones to switch off now. This reads a NEW creative against its ad set's
own medians. A long-running creative against its own past is
creative-fatigue-read-ad-creative. A finished comparison against a named control
is creative-test-readout-ad-creative. If these creatives can plausibly reach
test.volume_floor inside test.min_runtime, wait and read them properly.
Required input
- Per creative since launch: impressions, spend, outbound clicks, and on video,
3-second plays and the video-play figure
early.hold_rateis measured on. - Video length in seconds for every video creative. This sets its
early.duration_bandand without it no hold read runs at all. - Total ad set spend over the same window, and hours live per creative.
- Target cost per acquisition, and per-creative cost per acquisition if any.
- Launch date per creative, and whether any changed after launch.
- Which Advantage+ creative enhancements are on and the date each was switched
on (
test.creative_enhancements_rule).
On LinkedIn this skill runs on early.cost_multiple alone. LinkedIn does not
report the video play metrics that early.hook_rate and early.hold_rate are
built from, so both rows are needs_data on every creative and the cut list
rests on cost per outbound click. Say that in the output rather than letting two
empty columns pass as passing ones.
Analysis workflow
- Apply
delivery.never_delivered_floorfirst, and let it be the only exclusion this skill makes. A creative under it never got a chance, so it gets its own row, stays off the cut list, out of the medians and out of any brief input, and is never reported as a performance finding. - Apply
delivery.starved_flagto everything that cleared step 1. A creative that cleared exposure and still holds a thin slice of spend after its first days has not gone unread; it has been read. Delivery allocates on predicted performance and that prediction is trained on the creative's own early response, so repeated non-allocation is the platform's verdict on the creative rather than an absence of one. Decisioncut, confidencelow, and it goes ON the cut list with that reasoning written into the row. - Group the survivors by
early.duration_band. Everyearly.*median is computed inside a band, never across an ad set holding several, because hold on a short video and hold on a long one are different questions. - Check each band against
early.median_stability_floor, counted after steps 1 and 2. Under the floor the band's median is one middle number driving real cuts, so hook and hold areneeds_datathere and no cut fires on them.early.cost_multiplemay still run against the whole ad set, and the row says that is what it did. - In each band that clears the floor, compute the band's own median hook rate
and hold rate, then test each creative against
early.hook_rateandearly.hold_rateseparately and record which failed. Reporting them together as one bad creative destroys the only information an early read produces. Never import a benchmark from another account. - On statics, on LinkedIn and on any account without video metrics, use
early.cost_multipleinstead and say so. - Before ranking anything or handing a creative to a brief, apply
delivery.ranking_floor. It answers a different question from step 2: one decides whether a creative gets a decision, the other decides whether it gets compared. - Check
test.creative_enhancements_rule. An enhancement switched on since launch means the served asset changed under the read, so the creative goes tomonitorwith no verdict. - Check
money.relevance_floorbefore recommending any budget move. Where cost per acquisition is not supplied, name the decision you cannot make. - Put
early.false_negative_ratein the output every time, and tell the account how to replace it: log each early cut with its date and reason, then check later winners against that log. After a few dozen entries it has its own measured rate and retires this assumption. The same trade applies to the cuts made underdelivery.starved_flag.
Decision rules
- Under
delivery.never_delivered_floor:never_delivered,monitor, evidenceexport, no performance claim of any kind, excluded from the cut list. delivery.starved_flagfires:cut, evidenceexport, confidencelow, and the creative goes on the cut list. State in the row that the platform declined to spend on it repeatedly and that this is its read of the creative.- Band under
early.median_stability_floor: hook and hold areneeds_data, no cut fires on them, andearly.cost_multipleruns against the whole ad set with that substitution named. - Video length not supplied: the hold read is
needs_dataunderearly.duration_band, and no band median is computed from mixed lengths to cover the gap. early.hook_ratefails against the band median, hold passes:cut, and the rewrite direction is the opening only.early.hold_ratefails, hook passes:cut, and the rewrite direction is everything after the opening. Keep the hook.- Both fail, or
early.cost_multiplefails on a static:cutthe concept. - Creative changed after launch, or an enhancement in
test.creative_enhancements_ruleswitched on since launch:monitor, no verdict, because the window covers two different assets. - Below
delivery.ranking_floor: the creative may carry a verdict but may not be ranked against another creative or fed into a brief as evidence.
Output format
No verdict line: this produces a list, and a verdict line on a cut list reads as a result.
| Creative | Band | Spend share | Exposure met | Hook vs band median | Hold vs band median | Failing element | Evidence | Decision | Confidence |
|---|
Then the early.false_negative_rate sentence and how to replace it, then
What this could not see, Missing data, Approval gates.
Practical example
Illustrative made-up account data, not a real advertiser.
Ad set spend in the window: 4,000 units across 13 live creatives. Target cost
per acquisition 40. Text variation has been on for all 13 since launch and
nothing was switched on mid-window, so under test.creative_enhancements_rule
it is a constant here rather than a changed asset.
Delivery, step 1 and step 2. Four creatives sit under
delivery.never_delivered_floor, taking 100 units between them, 2.5 per cent of
ad set spend: never_delivered, off the cut list, out of the medians. Three
creatives carry the ad set: A on 1,180, B on 1,020 and C on 962, which is 29.5,
25.5 and 24.1 per cent, just over 79 per cent between them. The remaining six
cleared exposure and hold between 2.8 and 3.3 per cent of spend each after three
days live, so delivery.starved_flag fires on all six: cut at low, ON the
cut list, because the platform looked at each of them repeatedly and kept
deciding not to spend.
Bands. The 15 to 30 second band holds seven survivors, A, B, C and four of the
starved six, which clears early.median_stability_floor. Band hook rates are
0.130, 0.200, 0.220, 0.240, 0.260, 0.280 and 0.300, so the median is 0.240 and
early.hook_rate triggers at 0.144. Band hold rates are 0.150, 0.280, 0.300,
0.350, 0.360, 0.400 and 0.440, so the median is 0.350 and early.hold_rate
triggers at 0.210.
Creative A: 16,120 three-second plays over 124,000 impressions is 0.130, under
0.144, so hook fails. 5,642 fifty-per-cent plays over 16,120 three-second plays
is 0.350, above 0.210, so hold passes. Failing element: the opening alone. cut,
rewrite the first seconds and keep the rest.
Creative B: 26,520 over 102,000 is 0.260 and hook passes. 3,978 over 26,520 is
0.150, under 0.210, so hold fails. Failing element: everything after the
opening. cut, keep the hook, rebuild the body. Reporting A and B as one finding
would have produced two identical, wrong briefs.
Creative C: 0.300 hook and 0.440 hold, both above trigger. No cut.
The under-15-second band holds only two survivors, both from the starved six,
which is below early.median_stability_floor. Hook and hold there are
needs_data and no cut fires on them; that refusal is stated rather than papered
over with a two-creative median. early.cost_multiple runs against the whole ad
set instead, and the output says it did: ad set median cost per outbound click
1.80, so the trigger is 4.50. The 11-second creative spent 118 for 22 outbound
clicks, which is 5.36, and fires. The 13-second creative spent 115 for 41
outbound clicks, which is 2.80, and does not. Both are cut anyway under
delivery.starved_flag, one on two grounds and one on one.
Ranking: only A, B and C clear delivery.ranking_floor, so only those three may
be compared with each other or handed to a brief. The eight cuts are decisions,
not comparisons, and the output does not rank them.
Guardrails
- Never report an early cut as a result. Everything here is
low. - Never put a
never_deliveredcreative in the cut list or a brief input. - Never exclude a starved creative from the cut list. Non-allocation is a verdict the platform reached, not a gap in the data.
- Never take an
early.*median across mixed video lengths. - Never collapse a hook failure and a hold failure into one row.
- Never omit
early.false_negative_ratefrom the output. - Never compare a creative to another account's benchmark.
- Do not pause anything. Recommend, and let a human approve.