Detection: Prospecting ad set without a purchaser exclusion
Key: no_purchaser_exclusion
Severity: Medium
Confidence: 70–85%
What this detection looks for
We flag an ad set as missing a purchaser exclusion when all of these are true:
- The ad set is active and lives inside a sales/leads/conversions
campaign (objective:
OUTCOME_SALES,OUTCOME_LEADS,CONVERSIONS,LEAD_GENERATION, orOUTCOME_APP_PROMOTION) - The ad set has spent at least $500 in the audit date range
- It is prospecting, not retargeting — none of its included custom audiences contains purchasers or is a website/engagement/customer-list audience
- The account has a purchaser audience available — either a custom audience flagged as containing purchasers, or the account has had at least 50 purchases (meaning one could trivially be built)
- The ad set's excluded audiences do not include any purchaser audience
Why this matters
Prospecting campaigns are designed to acquire new buyers. When a prospecting ad set does not exclude people who have already purchased, some of the budget goes to serving ads to those existing customers — who are not the target.
The waste is usually small as a percentage of total spend (3–7%) but it has two compounding effects:
- The customers who already bought see your acquisition messaging again, which is at best wasted impressions and at worst hurts brand trust ("I already bought this — why are you still showing me this ad?")
- Meta's optimization treats those re-purchases (when they happen) as prospecting wins, which distorts the algorithm's signal of which audiences convert.
The fix is to add a 90- or 180-day-purchaser custom audience to the ad set's exclusion list. This is one of the cheapest, lowest-risk fixes in a typical account.
How we calculate confidence
| Condition | Confidence |
|---|---|
| Account has at least one audience explicitly flagged as containing purchasers | 85% |
| Account has ≥ 50 purchases but no labeled purchaser audience yet (buildable) | 70% |
| Neither — purchaser audience cannot be built reliably | We don't surface the finding |
How we calculate the estimated monthly cost
We treat 5% of the ad set's spend as recoverable, projected to a 30-day month. This is intentionally conservative — actual industry studies typically report 5–10% impression waste from missing exclusions.
monthly_recoverable = (ad_set_spend × 0.05) × (30 / days_in_range)
If your purchaser-to-traffic ratio is high (a popular DTC brand with many returning visitors), the true number may be higher. We surface the conservative estimate by default.
What would change our mind
This finding can be a false positive in a small number of cases:
- You intentionally re-market to recent purchasers in a sales campaign — for example, a subscription brand where the same buyer needs to be re-acquired monthly. In that case the exclusion would remove valid demand. Flag the campaign as a deliberate re-acquisition flow and the finding should be dismissed.
- You use a separate retargeting campaign that handles purchasers and the prospecting campaign is implicitly excluded by an account-level rule we cannot see. Confirm by checking whether the prospecting ad set has any direct purchaser overlap before acting.
- The purchaser audience is too small (under ~1,000 people) to meaningfully change delivery. In that case the fix is real but the recoverable amount is below noise.
How to fix it
- In Meta Audiences, ensure you have a custom audience for "Purchased in last 180 days" (or 90 days if your product has a short repurchase cycle).
- Edit each prospecting ad set's targeting. In the Custom audiences → Exclude field, add the purchaser audience.
- Save. Meta does not reset the learning phase for exclusion changes, so delivery is uninterrupted.
- Re-audit in 7 days. The impression-to-conversion ratio for the ad set should improve modestly.
What we look at to make this detection
effective_statuson the campaign and ad set- Campaign
objective - Ad set
included_custom_audience_idsandexcluded_custom_audience_ids - Audience metadata:
audience_typeand a heuristiccontains_purchasersflag computed from the audience's name, retention period, and source rule. The flag is best-effort; an audience the fetcher could not classify is left asunknown - Account-level purchase volume in the audit date range, used as a fallback signal that a purchaser audience could be built
Source
This methodology page is generated from
apps/api/app/services/detections/no_purchaser_exclusion.py. The
detection code is open for inspection. We do not have hidden rules.