The problem with "the best ad"
A ROAS or a CPL says nothing without two questions. How much volume is behind it? And how much budget did the platform give the ad?
An example, made up but familiar. One ad shows ROAS 30. It ran for three days, got €11 of spend and produced one purchase. One order from a customer who happened to have a large cart. Next to it runs a video with ROAS 3.7 on €840 of spend and 28 purchases. The first one tops your table. The second one pays for your month.
The method below separates the two. You can apply it in a spreadsheet. The skill at the bottom does it in a minute.
Step 0: write down your norm
Without a norm there is no winner. Answer this before you look at numbers:
| Question |
Why |
| What is your ROAS floor (ecommerce) or your CPL ceiling (leads)? |
That is the bar. Not the account average, but what your margin allows. |
| What is your average order value? |
The volume gate needs it. |
| Is your conversion tracking reliable right now? |
Measure wrong and the wrong ad wins. Never name winners on broken tracking. |
| Was there a promo or a sale in the last 14 days? |
On a sale day every ad looks like a winner. |
| What is prospecting and what is retargeting? |
You judge them apart. |
Does lead quality matter more to you than lead volume? Then judge on the lead type that really counts, not on all leads.
Step 1: the volume gate
No label without a floor:
- Ecommerce: at least 3 purchases in the window, or spend of at least 2 times your average order value
- Leads: at least 5 leads in the window, or spend of at least 3 times your CPL ceiling
An ad that does not reach the floor gets the label too early. Not a winner, not a loser. The ROAS 30 ad with one purchase drops out here. This is the most important rule of the whole method: one order does not make a winner, however good the ratio looks.
Mind the second half of the rule. An ad with no purchases that has already spent twice your order value does have enough volume. Enough to call it a drain.
Step 2: the matrix
Two axes. Does the ad meet your norm? And does it get at least 5% of the spend of its own campaign?
|
meets the norm |
misses the norm |
| 5% or more of campaign spend |
Winner: replicate and scale |
Drain: cap or stop |
| under 5% |
Potential: underfunded, give it budget or test it on its own |
Irrelevant: do not report, only count |
The top right box costs you money. The bottom left box is missed revenue: ads that meet the norm but get no budget from the platform. You never see that box when you only sort by ROAS.
Step 3: three windows at once
Look at 3, 7 and 14 days together. Persistence decides, not the peak of one day.
| Pattern |
Label |
What you do |
| Winner in 2 of the 3 windows or more |
Confirmed winner |
Safe to build variants on |
| Winner in 3 days only |
Hot, observe |
No creative production on this yet |
| Winner in 7 days only |
Unconfirmed |
Look again next week |
| Winner in 14 days, no longer in 3 and 7 |
Fatigue candidate |
It won, it no longer wins. Check frequency and CTR. This calls for a refresh, not a copy. |
Step 4: correct for promos
Two cases, not one.
Loose peak days in an account with normal pricing: exclude them. Otherwise every ad that happened to run that day looks like a winner.
A full sale campaign next to full-price campaigns: do not exclude, segment. Compare sale ads with sale ads. A ROAS of 6 on discounted stock is no norm for your new collection, and a sale winner is no brief for the next season.
Three traps
- Paused ads are still in your export and can carry the highest ROAS. Set them apart. A paused winner is a different question (turn it back on, or was it off on purpose?) than a live winner.
- Retargeting is not prospecting. A retargeting ad with ROAS 8 is not a winner you copy to a cold audience.
- A filtered export gives wrong shares. The spend share is only right when every ad of the campaign is in the file.
The Winner Detector
The skill does all of the above on one CSV export. It only reads a file. It has no access to your ad account and never changes anything.
Download the Winner Detector (zip)
How to use it:
- Export from Ads Manager: Ads tab, last 14 days ending yesterday, breakdown by day, as CSV. Columns: campaign name, ad set name, ad name, ad ID, ad delivery, amount spent, impressions, link clicks, and purchases plus purchases conversion value (ecommerce) or leads.
- Install the skill. In Claude Code, copy the folder to
~/.claude/skills/. In the Claude app, upload the zip in the skills settings. The README in the zip covers both.
- Ask "which ads are winning?" and attach the file. The first time, the skill asks the step 0 questions and saves the answers. After that it does not ask again.
You get a report with winners, potentials, drains, fatigue candidates and paused ads with a signal. Ten winners and ten potentials at most, sorted by spend. Nobody reads a list of sixty ads.
Want to try it without your own data first? The zip contains a fictional export. It includes the ROAS 30 ad with one purchase, which lands neatly under "too early".
No Claude? The script in the zip also runs on its own, with Python and no extra packages.
What this is not
The thresholds (5%, 3 purchases, 5 leads, 2 of 3 windows) are rules of thumb from practice, not statistics. They work in accounts that spend every day. In a small account almost everything lands under "too early". That is the honest answer.
The skill judges results, not the creative itself. Why an ad wins (the hook, the offer, the format) remains human work. And it is not affiliated with or endorsed by Meta.
One next step
Run the skill once this week on your own export. Then count two things: how much budget went to drains, and how many potentials got less than 5%? Together those two numbers show how much of your budget could have gone elsewhere.