# Ad Eligibility & Creative Selection (/docs/concepts/ad-eligibility)



When the optimizer launches a new ad or refreshes an adset, it pulls from your
**eligible creative pool**. Eligibility = `organic_score >= 4.0` OR
`override = 'include'`, AND the creative is not in `override = 'exclude'`,
AND the creative does not have `safetyFailed = true`.

## Selection algorithm [#selection-algorithm]

Creative selection runs each time the content-refresh workflow (or an
ad-manager create/refresh flow) needs to (re)populate one or more adsets:

1. **Filter** to eligible `ads_content` within the project
   (`organic_score >= 4.0` or `override = 'include'`; never
   `override = 'exclude'` or `safetyFailed = true`).
2. **Bucket** candidates into three pools: `generated`, `ugc`, `manual`.
3. **Rank** within each pool by `organic_score` (weighted by
   `organicScoreWeight`).
4. **Pick top N per pool**, where N defaults to `generatedSlots = 3`,
   `ugcSlots = 3`, `manualSlots = 3`, capped by `maxCreativesPerAdset`
   (default 10) and the platform's hard limit (Meta caps adsets at 50 ads).
5. **Skip adsets already at capacity** — adsets already holding 50 ads on
   Meta are excluded from the refresh.

Per-pool slot counts are passed as workflow input — tune them per project by
overriding the content-refresh input mapping.

## Budget change guardrails [#budget-change-guardrails]

The optimizer can adjust adset budgets up or down, but:

* No single change exceeds &#x2A;*50%** of current budget.
* No single change exceeds **$100** absolute.
* Each entity is on a **48h cooldown** between budget changes.

These caps prevent runaway scaling on a single optimizer cycle.

## Refresh cadence [#refresh-cadence]

The content-refresh workflow runs **every 15 minutes** per ad layer:

1. **Disable underperformers** — applies optimizer-style scoring with
   guardrails (min 3 days age, min $5 spent, never TOP\_PERFORMER/HEALTHY,
   never empty an adset/adgroup).
2. **Select top creatives** — pulls the next-best eligible creatives from
   each pool (`generated`, `ugc`, `manual`).
3. **Launch** the selected creatives into the freed slots.

A creative whose `organic_score` drops below threshold while it's already
running keeps running — score is only checked at *selection time*.

## Why your "best" creative isn't running [#why-your-best-creative-isnt-running]

Common reasons:

* It's `override = 'exclude'` somewhere.
* Its score is below 4.0 (check the per-creative score history).
* The adset already has its per-pool slots filled with higher scorers.
* Meta adset is at its 50-ad capacity — refresh skips it.
* It has `safetyFailed = true` — regenerate it.

## Manual overrides [#manual-overrides]

Use `project_ads_content.override = 'include'` to keep a creative permanently
eligible regardless of score, or `override = 'exclude'` to force it
ineligible. Overrides are per-project, so the same `ads_content` row can be
eligible in one project and excluded in another.

## Next [#next]

* [Optimizer](/docs/concepts/optimizer) — what happens after selection.
* [Refresh cycles](/docs/paid-media/refresh-cycle) — the content refresh loop.
