Margin-Based Bidding in Performance Max: Tag Your Feed (2026)

Performance Max spends the same $1 chasing a 5%-margin product and a 50%-margin one, because it optimizes to the number you feed it — and by default that number is revenue. Tag every SKU by margin in your feed, give each tier its own target, and the algorithm starts bidding on profit instead.

Google Performance Max and Meta's Advantage+ Catalog ads bid on revenue, not profit. They can't see your margin unless you put it in the feed. So when two products convert at the same ROAS but one keeps 45 cents on the dollar and the other keeps a nickel, the algorithm treats them as equals and happily pours budget into the loser. This piece is the tactical how behind POAS: a nightly pipeline that tags every SKU by margin tier in Google Merchant Center, plus a campaign structure that gives each tier its own target — so the machine reallocates spend toward the products that actually make you money.

The short version

  • Your ad platform optimizes to revenue, not profit. PMax and Advantage+ chase the conversion value you send them. Send revenue, and they'll happily scale a product with no margin left.
  • Same ROAS, opposite outcomes. A cheap low-margin item and an expensive high-margin one can hit the identical ROAS while one prints cash and the other bleeds. A blended target buries that.
  • The feed is your biggest lever. The algorithm can only optimize the product data you give it. Merchant Center hands you custom_label_0 through custom_label_4 — use one for margin tier.
  • Automate it nightly. A scheduled job pulls live COGS from your ERP, computes gross margin per SKU, maps it to a tier, and writes custom_label_0 back into the feed. Margins move, so a static label rots.
  • Split campaigns by tier. High-margin gets an aggressive target, low-margin gets a cap or exclusion. Then read POAS, not ROAS.

Your ad platform is optimizing for the wrong number

Here's the uncomfortable truth about every automated bidding system you run. Performance Max, Advantage+ Shopping, Smart Bidding. They are extremely good at hitting the goal you set, and completely blind to the goal you actually have. You set "maximize conversion value at a 4x ROAS." They do exactly that. But conversion value is revenue, and revenue is not profit.

The AI optimizes conversions and revenue because that's the data flowing into it. It doesn't know your COGS. It doesn't know that one product ships in a $14 box, gets returned a third of the time, and rides on a supplier price that jumped last quarter. It sees a sale for $200 and logs a win. Whether that $200 sale left you $90 or $9 is invisible to the machine, because you never told it[5].

And this is where a lot of operators get stuck. They assume the fix lives inside the ad account — some bid adjustment, some audience tweak, some setting Google buried three menus deep. It doesn't. With Performance Max you can't set a per-SKU bid the way old Shopping campaigns let you. You influence PMax through three levers: the feed, your listing groups and asset groups, and your per-campaign targets. Of those, the feed is the one you fully control and the one the algorithm leans on hardest[5].

So picture the setup this whole article is about. You've got a $30 throw pillow at a 10% margin and a $1,200 sofa at a 45% margin, both sitting in the same PMax campaign under one blended ROAS target. To the algorithm they're interchangeable inventory. To your P&L they could not be more different. Fix that mismatch and you've done more for profit than any bid tweak ever will.

GP ÷ SpendPOAS — the number that survives your P&L[1]
5custom_label slots (0–4) in Merchant Center[2]
$5.44returned per $1 on marketing automation[6]
The tools you already have: a profit metric, a free feed field, and automation that pays for itself. Sources: Skale Strategy; Google Merchant Center Help; Nucleus Research, 2021.

Same ROAS, opposite outcomes

Start with the definitions, because the whole argument hangs on one word. ROAS is revenue divided by ad spend. POAS — Profit on Ad Spend — is gross profit divided by ad spend[1]. Same denominator, completely different numerator. One counts what the customer paid. The other counts what you actually kept after COGS, returns and fees.

Now watch what happens when a single ROAS target sits on top of two very different products. The following is illustrative — the arithmetic is real, the specific SKUs are invented to show the shape.

SKUPriceMarginAd spend at 4x ROASGross profitPOAS
Throw pillow$3010%$7.50$3.000.4x — loses money
Sofa$1,20045%$300$5401.8x — prints cash

Illustrative, not measured data. Both products hit the exact same 4x ROAS. One returns 40 cents of profit per ad dollar; the other returns $1.80. A blended target treats them as equals. Mechanic: Ayko[3]; numbers invented.

Same 4x ROAS. Opposite outcomes. The pillow clears a 4x return on paper and still loses you money after costs, because at a 10% margin you'd need far more than 4x just to break even. The sofa at 45% is comfortably profitable at the same target. Feed both into one campaign and the algorithm — steering by revenue — has no reason to prefer the sofa. It might even prefer the pillow, if pillows convert faster.

A blended 4x ROAS is an average, and an average can hide a winner quietly paying the losses of a loser sitting right next to it.

Here's the version that keeps people up at night. Say your account shows a healthy blended 4x. That single number can be a $6-profit winner and a $1.50-profit loser averaged into one comfortable figure (again, illustrative). The dashboard looks fine. The high-margin hero is subsidizing the low-margin dog, and you'd never know from the top-line ROAS[3]. You're scaling both when you should be scaling one and capping the other.

And in 2026 the trap is getting deeper. Practitioners are watching input costs, freight and tariffs squeeze DTC contribution margins across the board[4]. As margins compress, the gap between revenue and profit widens — which means a revenue-based metric like ROAS misleads louder than it did two years ago. The thinner your margins get, the more expensive it is to keep bidding on the wrong number. (Treat that as an industry observation, not a measured law — but it lines up with what most operators are seeing.) If you want the strategic case for why this matters, we've covered how ROAS quietly bankrupts D2C brands and the broader MER vs ROAS trade-off separately. This article is about the plumbing that fixes it.

10% margin10x to break even
20% margin5x
33% margin3x
50% margin2x
Break-even ROAS = 1 ÷ gross margin. This is arithmetic, not a study finding — a 20%-margin product needs a 5x return just to break even, while a 50%-margin one breaks even at 2x. One blended target can't be right for both.

The fix: tag your feed by margin

The algorithm can only optimize the product data you give it. That single sentence is the whole strategy. If margin isn't in the feed, the machine can't factor it in. So the job is to get margin into the feed in a form it can segment on.

Google Merchant Center gives you five free fields for exactly this kind of thing: custom_label_0 through custom_label_4. A custom label is a tag you attach to each product. It doesn't show to shoppers, and it doesn't affect how your listing looks. Its only job is to let you group and filter your catalog for bidding and reporting[2]. People use them for season, price band, best-seller status, clearance. You're going to spend one of them on margin.

Pick a slot — say custom_label_0 — and populate it with a margin tier:

  • custom_label_0 = high_margin
  • custom_label_0 = medium_margin
  • custom_label_0 = low_margin

That's it. Once every SKU carries its tier, you can build listing groups and campaigns around those three values and hand each one a different target. The feed is where this belongs — not a spreadsheet, not a bid rule, not a note in your head — because the feed is the input the algorithm reads directly when it decides where your budget goes[2][5]. The same logic applies on the catalog side of paid social, where product sets are built by filtering on catalog attributes rather than per-item bids.

Why not just three separate feeds? You could, but a label on one feed is cheaper to maintain and keeps your source of truth in one place. One product, one row, one margin tag that updates itself. That last part — updates itself — is the whole game, and it's the next section.

The nightly pipeline

A margin label you set by hand is wrong within a week. Supplier prices move. You run a promo. Freight ticks up. A product's return rate creeps. The moment your COGS changes and the label doesn't, you're bidding on a stale number with total confidence. Which is worse than not tagging at all. So the tag has to refresh itself on a schedule. Automatically. Every night.

Automate bad data and all you've done is make the wrong bids faster — with total confidence.

The pipeline is simple in shape. A scheduled job runs overnight and does four things in order:

  1. Pull. Hit your ERP, warehouse or inventory system and pull the current cost data for every SKU.
  2. Compute. Calculate live gross margin per SKU: price − COGS − returns/fees. Not last quarter's margin. Tonight's.
  3. Map. Bucket each SKU into a tier — high / medium / low — against thresholds you set.
  4. Write. Push the tier into custom_label_0 in the feed that syncs to Merchant Center.

You can wire this three ways depending on your stack. A feed-management tool (Feedonomics, DataFeedWatch, GoDataFeed and the like) can transform a supplemental feed and set the label rule. A script — Python on a cron job, a scheduled cloud function — can do the same if you'd rather own the logic. Or an iPaaS flow (Make, Zapier, n8n) can run the event-compute-write chain without you maintaining a server. The pattern is identical across all three: event fires → margin computed → label written.

Three build details decide whether this actually runs. First, the join key: your ERP export and your feed have to share item_id / SKU, or nothing lines up — this is the single most common place these pipelines break. Second, your thresholds: something like high ≥ 40%, medium 20–40%, low < 20% is a fine place to start, but pull the cutoffs to the shape of your margin distribution, not ours. Third, write to a supplemental feed, not your primary one — a supplemental feed overrides custom_label_0 on matching item_ids without you rebuilding the source feed every night.

02:00 Scheduled job wakes, connects to your ERP / inventory system.
02:01 Pulls current price and COGS for every SKU in the catalog.
02:02 Computes live gross margin: price − COGS − returns/fees.
02:03 Maps each SKU to a tier and writes custom_label_0 to the supplemental feed.
Morning Merchant Center syncs the refreshed feed. Every campaign now bids on today's margins.
The nightly margin pipeline. The exact times don't matter; the loop does — live margin in, fresh label out, before the day's spend starts. Mechanic: Store Growers[5].

Nightly beats monthly for one concrete reason: the morning after you drop a product to clearance, it falls out of your high-margin campaign on its own. No one has to remember to move it. If you want the deeper build on wiring inventory data into ad accounts, we walk through the full inventory-to-ad-account pipeline elsewhere. And automation like this tends to pay for itself: Nucleus Research pegged marketing automation at $5.44 returned per $1 spent over three years, with payback under six months[6].

Structuring campaigns around the tiers

A labeled feed does nothing on its own. The label is just a hook. Now you hang campaign structure on it, so each margin tier gets a target that fits its economics instead of one blended average that over-invests in low-margin winners-on-paper.

Split by custom_label_0. In practice that means listing groups or separate asset groups / campaigns per tier, each with its own target ROAS or target CPA:

  • High-margin (~45%, break-even ~2.2x) — go hungry. Set a target ROAS around 2.5–3x. Low enough to tell the algorithm to buy volume, high enough that every sale still clears real profit.
  • Medium-margin (~25%, break-even ~4x) — steady. A target around 4.5–5x keeps them profitable without starving the high-margin push.
  • Low-margin (~10%, break-even ~10x) — cap or cut. Cap the target around 11–12x so you're not overspending on thin products, or exclude the ones with nothing left to give.

Illustrative targets. Each number is anchored to break-even ROAS = 1 ÷ gross margin, then nudged up to leave profit headroom — plug in your own margins. The principle holds even when the numbers don't: every tier's target sits a controlled distance above its own break-even, never on a blended average.

Remember the direction of the target. A lower ROAS target tells the algorithm to spend more aggressively; a higher one reins it in. So your high-margin tier gets the lower, hungrier target, and your low-margin tier gets the higher, tighter one. That's the whole reallocation. You're not touching a single bid by hand, you're setting the rules of engagement per tier and letting the machine do the placement.

One pattern a lot of practitioners have settled into, as a rule of thumb rather than a rule: PMax for scale on the bulk of the catalog, plus Standard Shopping kept alive for the two cases where you want tighter control, pushing high-margin heroes and controlling clearance. PMax is a blunt instrument on purpose. Standard Shopping gives you back the manual grip it took away.

High-margin — aggressive targetspend more
Medium-margin — steady targethold
Low-margin — cap or excludespend less
Illustrative budget posture by tier. Once the feed is labeled, each tier gets a target that matches its profit — the reallocation the blended average was blocking. Mechanic: 85SIXTY[2]; posture illustrative.

Where this goes wrong

This works, but it's unforgiving in four specific ways. Skip these and you'll automate a mistake at scale.

Garbage COGS in, wrong bids out. The entire system runs on your margin data being accurate and current. If your COGS is stale, or it ignores returns and fulfillment fees, you'll tag products into the wrong tier and then bid on that lie with total confidence. A product with a 35% gross margin that gets returned 30% of the time is not a high-margin product. Get returns and fees into the calculation or don't bother.

Give it time to recalibrate. When you change targets, the algorithm needs a learning window to adjust — it doesn't flip overnight. Don't panic on day 3 and rip it all out because the numbers wobbled. Automated bidding rebalances over weeks, not days. Judging it too early is how good structures get killed before they've had a chance to work.

Don't over-segment a thin catalog. Three tiers is usually right. Seven is usually wrong. Every split you make divides your conversion data into smaller pools, and PMax needs volume to learn. Slice a modest catalog into too many campaigns and you starve each one of the signal it needs. If you've got 200 SKUs, three tiers. Save the fine-grained segmentation for when you have the volume to support it.

This fixes allocation, not economics. Margin-based bidding moves budget toward your profitable products. It cannot manufacture profit that isn't there. If a product has no margin after all costs, the honest move is to fix the price, fix the supply cost, or stop advertising it. Not hope the algorithm rescues it. This is a targeting tool, not a turnaround plan.

What to build first

Don't try to do all of this in a weekend. The order matters — get the margin data right before you automate anything, because automating bad data just makes the wrong bids faster.

#StepWhy it's first / why it matters
1Get accurate per-SKU gross margin, including returns and fees.Everything downstream bids on this. Wrong margin = confidently wrong bids.
2Define 3 tiers and add custom_label_0 to the feed.Three is enough. The label is the hook the whole structure hangs on[2].
3Automate the nightly refresh (feed tool, script, or iPaaS).Margins move. A static label rots within a week.
4Restructure campaigns by tier — aggressive target high, cap/exclude low.This is where reallocation actually happens.
5Give it 2–4 weeks, then read POAS, not ROAS.Let it learn, then judge it on profit per dollar — the number you were trying to fix[1].

Build order. Data first, automation second, structure third, patience last. Source: Polar Analytics[1].

The mechanism is boring and that's the point. There's no growth hack here: just accurate margin data, a free feed field, a nightly job, and campaign structure that respects the difference between a pillow and a sofa. Do that and the algorithm you already run starts hunting profit on its own.

FAQ

Can't I just set a per-SKU bid in Performance Max instead?+
No — and this trips up people who came from old Shopping campaigns. Performance Max doesn't let you set a bid on an individual product the way manual Shopping did. You influence PMax through three levers: the product feed, your listing groups and asset groups, and your per-campaign targets (Store Growers, 2026). Margin tagging works precisely because it uses the feed — the one input you fully control and the one the algorithm reads directly.
Which custom_label should I use for margin?+
Any of the five — custom_label_0 through custom_label_4 are functionally identical, so pick one and be consistent (Google Merchant Center Help). Most teams reserve custom_label_0 for margin tier because it's the first slot and easy to remember, leaving the others for season, best-seller status or clearance. The label is invisible to shoppers; its only job is to let you group products for bidding and reporting.
How many margin tiers should I create?+
Three is the safe default: high, medium, low. Each split divides your conversion data into a smaller pool, and automated bidding needs volume to learn. Over-segment a modest catalog into five or seven tiers and you starve each campaign of the signal it needs to optimize. Add finer segmentation only once you have the sales volume to support it.
Why does the margin label need to update every night?+
Because margin is a live number, not a fixed one. Supplier costs move, you run promotions, freight fluctuates, and return rates drift — any of which can flip a product from one tier to another. A label you set by hand is wrong within a week, and a stale label means you're bidding on last month's economics. A nightly job that recomputes margin from your ERP keeps the tiers honest, so a product dropped to clearance falls out of your high-margin campaign the next morning automatically.
Will margin-based bidding lower my ROAS?+
It might, and that can be the correct outcome. If the algorithm shifts budget from a high-revenue, low-margin product toward a lower-revenue, high-margin one, your reported ROAS can dip even as actual profit rises. That's the whole trade — ROAS measures revenue over spend, POAS measures gross profit over spend (Skale Strategy; Polar Analytics). Judge the change on POAS, not on whether the vanity ratio went up or down.

Sources

  1. Skale Strategy — Profit on Ad Spend for Google Ads (POAS = Gross Profit ÷ Ad Spend). skalestrategy.com; Polar Analytics — POAS: Profit on Ad Spend. polaranalytics.com
  2. Google Merchant Center Help — Custom label [custom_label_0..4]. support.google.com; 85SIXTY — Using custom labels to subdivide products. 85sixty.com
  3. Ayko — POAS bidding and why it outperforms ROAS for e-commerce growth (margin-variance illustration, industry). ayko.com; JudeLuxe — POAS vs MER vs ROAS. judeluxe.com
  4. Pigeon Digital — Tariff Math for DTC: When a COGS Spike Quietly Shrinks Your Q4 Ad Budget, 2026 (margin compression from tariffs/freight, industry observation). pigeondigital.com
  5. Store Growers — Performance Max campaigns guide (the feed as the highest-leverage lever, industry). storegrowers.com; 85SIXTY — Custom labels. 85sixty.com
  6. Nucleus Research (V61, 2021) — Marketing automation returns $5.44 for every dollar spent, payback under six months. nucleusresearch.com

Back to all posts