Catalog Campaigns · Bid Strategy · Margin Control

How to Set a Minimum ROAS Floor in Meta Catalog Campaigns (So Low-Margin Products Stop Draining Budget)

By SellTheClick Team · Aug 17, 2026 · Updated Oct 29, 2026 · ⏱ 14 min read · Catalog Ads · ROAS Bidding · Feed Optimization
Stop selling at a loss Minimum roas floor for catalogs. Thumbnail with a stock photo.
Photo: Pexels (free to use). Thumbnail: SellTheClick.

Meta's minimum ROAS setting is a campaign average, not a rule for each product. So a low-margin item can keep taking budget at 2.8x while the campaign as a whole still hits your 3.2x goal.

In Ads Manager it's called ROAS goal. Meta says it keeps your weekly average ROAS near the number you set, and that it "works best when your ad set gets at least 50-100 weekly conversions." There is no setting for a minimum ROAS per product.

The fix is two steps: tag products by margin using custom labels in your feed, then split them into product sets so each group sits in its own campaign with its own ROAS goal. That is the only way the floor applies to the products you care about.

Here's a scenario every catalog advertiser eventually runs into: your blended ROAS looks fine — 3.2x, comfortably profitable on paper — but when you break it down by product, half your ad spend is going toward a SKU with a 12% margin that needs a 5x+ return just to break even, and it's sitting at 2.8x. Meta's algorithm doesn't know that. It sees a product converting reasonably well and keeps feeding it budget, because "converts well" and "makes money" are not the same signal, and nothing in a default catalog campaign tells Meta the difference.

The fix people usually reach for first — "just set a minimum ROAS" — runs into a wall almost immediately, because of how Meta's floor mechanism actually works.

The Floor Is a Campaign-Level Setting, Not a Per-Product One

Meta's bid strategy for this is called ROAS Goal in Ads Manager (LOWEST_COST_WITH_MIN_ROAS at the API level, passed as a roas_average_floor value). Per Meta's own documentation, it's a goal-based bid strategy: you set a target average return, and "the ad delivery system uses AI to dynamically adjust bids to maximize conversion value while keeping your weekly average ROAS near your goal over the campaign lifetime."

Meta Marketing API — bid_strategy
bid_strategy: LOWEST_COST_WITH_MIN_ROAS
roas_average_floor: 3.5 // Ads Manager accepts 0.001 – 1,000.00
optimization_goal: VALUE // prerequisite — must be enabled
scope: ad_set // NOT per-product, NOT per-SKU

Two things in that definition matter more than they first appear:

The key insight: "Set a minimum ROAS" alone doesn't solve the problem. It protects the account average. It does nothing about the specific product quietly losing money underneath a healthy-looking headline number — unless you first separate that product out.

The Actual Fix: Margin Data in Your Feed, Then Structure Around It

The mechanism that gets you to "stop promoting this specific low-profit product" is a two-step combination that Meta supports natively but doesn't set up for you automatically.

Step 1: Put Gross Margin Into Your Feed as a Custom Label

Meta gives you five optional custom label fields per product — custom_label_0 through custom_label_4 — that exist specifically for advertiser-defined segmentation logic Meta doesn't capture natively. The standard use for profitability control is a margin tier:

Gross Margin custom_label_0 Value Tier Bidding Posture
> 40% high_margin High Aggressive — can absorb lower ROAS
20–40% medium_margin Medium Moderate floor set at real breakeven
< 20% low_margin Low Strict ROAS floor or Cost Cap
≤ 0% negative_margin Excluded Never promoted — excluded from all ad sets
Stale labels are worse than no labels. A margin label should update automatically as prices or costs change. If your feed tool doesn't recompute custom_label_0 when a cost or price shifts, a product that was 35% margin in January and discounted to 15% in a sale will keep running under its old, now-wrong bidding logic until someone catches it manually.

Text label or number? Custom labels are treated as text. Meta's developer changelog says numeric operators (greater than, less than) are "not available" on custom_label fields and points to custom_number_0–custom_number_4 instead. So if you'd rather store margin as a number (say, custom_number_0 = 18) and filter "less than 20", use a custom number field. Text tiers like low_margin work fine with "is" filters.

Step 2: Build Product Sets Filtered by That Label

In Commerce Manager → Catalog → Sets, create sets filtered on custom_label_0. At minimum, build one set per margin tier, plus a dedicated exclusion set for anything at or below breakeven. This last one is the actual answer to the original question — a negative-margin product set that simply never gets included in any ad you run. No floor, no bid strategy: it's excluded from the pool Meta is allowed to draw from at all.

Step 3: Give Each Remaining Tier Its Own Ad Set and Its Own Floor

For the tiers you do want running, don't put them all in one ad set with one blended ROAS Goal. Split them:

High-Margin Set

Can run with a lower ROAS floor — or no floor at all, prioritizing volume — because the unit economics tolerate a less efficient acquisition cost. Breakeven ROAS ≈ 1 ÷ 0.40 = 2.5x gives you real room to scale.

Medium-Margin Set

A moderate floor calculated off its own breakeven, not a round number that "feels safe." Runs with enough headroom that delivery stays consistent. Example at 30% margin: breakeven is 1 ÷ 0.30 ≈ 3.3x, so anything you set below that accepts a loss on paper.

Low-Margin Set

Strict ROAS floor, or a Cost Cap strategy if conversion volume is too thin for value-based bidding to learn properly. Even small overspend erodes the already-thin margin quickly on this tier.

Negative-Margin Exclusion Set

Never touches an ad. Excluded at the product-set level across every campaign in the account. This is the actual mechanism for "stop promoting this." No bid strategy needed — it never enters the auction.

The Breakeven ROAS Formula — Use It, Don't Guess

The number to set each floor against is your breakeven ROAS, not a round number that feels safe. A product line at 35% margin breaks even around 2.9x — a floor of "3.5" on that set isn't a safety margin, it's telling Meta to hold a standard the auction may not clear consistently.

Breakeven ROAS = 1 ÷ Gross Margin %

Set it too high and the cost shows up as unspent budget, not as better profit. Meta says so directly: ROAS goal "may spend less than your full budget when the market is competitive to protect your performance target." If the tier can't reach its breakeven at all, a ROAS goal won't fix that. The product needs a better price, a better margin, or to leave the ad pool.

What This Looks Like End to End

Put together, the structure looks less like "one catalog campaign with a ROAS floor" and more like a small portfolio:

This is more setup than typing a number into one field, but it's the only version of "minimum ROAS" that actually maps onto the real question — which product should Meta stop spending on — rather than the question Meta's native floor actually answers, which is closer to "keep my blended average acceptable."

Get the Sequencing Right Before You Set Any Floor

Can You Exclude Low-Margin Products From Meta Catalog Ads?

Yes, and it's the most reliable part of this whole setup. A product set is just a filter on your catalog. Build one that leaves out negative_margin (or whatever label you use), and use that set in every catalog ad set. Products outside the set can't be shown, whatever the bid strategy.

Two things to check after you do it:

ROAS Goal vs Highest Value for Catalog Ads

Both bid strategies chase conversion value. The difference is what they give up when the auction gets expensive. From Meta's help page:

ROAS goalHighest value
PriorityKeep weekly average ROAS near your numberSpend the full budget
When competition risesMay spend less than budgetKeeps spending, ROAS can drop
Use it forLow- and medium-margin tiersHigh-margin tier, or any tier while you collect two weeks of data

Meta's own rule of thumb: "Choose ROAS goal bidding if maintaining a specific return matters most. Choose Highest value bidding if spending your full budget matters most."

A Worked Example

Our numbers, made up for illustration. A store has three tiers. Breakeven is 1 ÷ margin:

TierMarginBreakeven ROASTrailing ROASWhat to do
High45%2.2x3.1xHighest value, push budget
Medium30%3.3x4.0xROAS goal ≈ 3.4x (15% under 4.0x, still above breakeven)
Low15%6.7x3.5xNo ROAS goal saves this; exclude, or fix price or margin

The low tier is the one the original question is really about. It "converts", so Meta keeps spending on it, but at 3.5x on a 15% margin every sale loses money. A floor wouldn't help: to protect it you'd set 6.7x or more, and Meta would likely stop spending on it anyway. Excluding it says the same thing honestly and frees the budget for the tiers that make money.

The Short Version

There's no field in Meta Ads Manager that says "minimum ROAS per SKU." The ROAS Goal / LOWEST_COST_WITH_MIN_ROAS bid strategy sets a floor on an ad set's blended average — not on individual products inside it. To get the outcome you actually want — specific low-profit products stop getting promoted — you build that outcome yourself:

  1. Custom labels to tag margin tiers in your feed
  2. Product Sets in Commerce Manager to separate those tiers
  3. Per-tier ad sets each carrying a floor set against that tier's real breakeven
  4. A hard exclusion set for anything at or below zero margin

The floor is the enforcement mechanism. The product-set structure is what makes it enforce the right thing.

FAQ: Minimum ROAS in Meta Catalog Campaigns

Can I set a minimum ROAS per product in Meta?

No. ROAS goal applies to the whole ad set (or campaign, with Advantage+ campaign budget) and Meta keeps the weekly average near your number. To control individual products, group them by margin with custom labels and product sets, and give each group its own ad set and goal.

Where do I set a minimum ROAS in Meta Ads Manager?

Pick Maximise value of conversions as the performance goal at the ad set level, then choose ROAS goal as the bid strategy and enter the number. If you use Advantage+ campaign budget, Meta says to choose ROAS goal at the campaign level first, then set the value in each ad set.

Why did my catalog campaign stop spending after I set a ROAS goal?

Most likely the goal is higher than the auction can deliver right now. Meta says ROAS goal may spend less than the full budget in a competitive market. Its advice for this case is to lower the goal 5–10% and wait a week, or to consolidate ad sets that get fewer than 50–100 conversions a week.

What ROAS goal should I start with?

Meta suggests starting 10–20% below your average ROAS from Ads Manager, measured within your attribution setting. Then check it against your breakeven (1 ÷ margin). If the starting number is below breakeven, that product group is losing money at current performance, and the bid strategy won't change that.

How do I stop Meta promoting low-margin products?

Tag them in your feed with a custom label (or a custom number for the margin itself), build a product set that leaves them out, and use that set in every catalog ad set. Products outside the set can't be shown.

Should I use custom_label or custom_number for margin?

Use custom labels for text tiers like high_margin and low_margin. Use custom_number_0 to custom_number_4 if you want to store the margin as a number and filter with greater than or less than; Meta says numeric operators don't work on custom labels.

Sources
Meta Business Help Center, About ROAS goal — facebook.com/business/help/1113453135474912
Meta Business Help Center, Best practices for ROAS goal — facebook.com/business/help/288309751798466
Meta for Developers, changelog Mar 3, 2022 (custom_label vs custom_number filters) — developers.facebook.com/docs/graph-api/changelog/non-versioned-changes/mar-3-2022
Facts checked Oct 29, 2026.
Meta for Developers, Bid Strategy (Minimum ROAS bidding, roas_average_floor) — developers.facebook.com/docs/marketing-api/bidding/overview/bid-strategy/
Meta for Developers, Advantage+ Shopping Campaigns — developers.facebook.com/docs/marketing-api/advantage-shopping-campaigns/

Know Which Creatives Meta Is Merging Before You Spend

Creative clustering is the silent budget drain before your ROAS floor even kicks in. SellTheClick shows you which of your ads Meta sees as the same — so you stop running 5 variations of one idea.

Analyze My Creative Library →
AV

SellTheClick Team

Founder, SellTheClick. Building AI ad intelligence tools for DTC brands and media buyers. Focused on creative distinctness analysis and how small teams can compete without a bigger budget.

← Back to all playbooks