Free Shopify store auditSpeed, SEO and conversion leaks — no cost, no obligation.
Claim it
Thriftizer Solutions LLPShopify Select Partner
Book a Growth Audit
PPC Aug 11, 2026 8 min read

Performance Max for D2C: Building Asset Groups by Product Margin

Split Performance Max by contribution margin, not category. A 4x ROAS on a 22% margin SKU loses money; on a 61% margin SKU it prints. Here's the structure, the feed labels and the arithmetic.

Split your Performance Max campaigns by contribution margin, not by product category. Three asset groups is usually enough: one for products that clear 45% or more after COGS, shipping, payment fees and returns; one for the 25-45% band; one for everything thin. Then set separate tROAS targets for each, because a 3x return on a 55% margin SKU makes money and a 3x return on an 18% margin SKU does not. That single change is the highest-leverage thing most D2C advertisers can do with Performance Max, and it takes an afternoon of spreadsheet work.

Most people set up Performance Max for ecommerce the way they set up Shopping: one campaign, category-based asset groups, a single ROAS target across the account. Google's bidding then does exactly what you asked. It finds the cheapest conversions. Cheapest conversions are, almost always, your lowest-priced and lowest-margin products, because those convert most easily. You end up scaling the SKUs you'd rather not sell.

Why category-based asset groups quietly lose money

A skincare brand we worked with had asset groups for cleansers, serums, sunscreen and kits. Sensible on paper. But the cleanser range included a ₹349 travel size with a 22% contribution margin after COD RTO losses, sitting in the same asset group as a ₹1,890 serum at 61%. Google spent 70% of that group's budget on the travel size, hit the 4x target comfortably, and the group looked like the account's star performer.

Run the arithmetic. ₹1,00,000 of ad spend at 4x ROAS gives ₹4,00,000 revenue. At 22% contribution margin that's ₹88,000 of gross profit, against ₹1,00,000 of spend. You lost ₹12,000. The same spend at 4x on the 61% margin product returns ₹2,44,000 of contribution, so ₹1,44,000 of profit. Identical ROAS. Opposite outcomes.

The reporting never surfaces this, because Google reports revenue and you think in profit. Nobody in the platform is going to flag it for you.

Working out contribution margin properly, including the Indian bits

Contribution margin per SKU, for D2C in India, needs more subtraction than most brands do:

  • Landed COGS including inward freight and customs, not the factory invoice
  • Outbound shipping at your actual blended rate, which for a 500g parcel to a tier-2 pincode is rarely the rate on your rate card
  • Payment gateway fees — Razorpay and similar sit around 2% plus GST on domestic cards and UPI, so 2.36% effective
  • COD handling plus the RTO cost. This is the number people fudge. If 18% of COD orders come back and you eat forward and reverse freight on all of them, a product with 35% headline margin on prepaid can drop into the twenties on COD
  • Packaging, including the insert nobody remembers to cost
  • Returns and refunds at your actual rate by category, since apparel and footwear behave nothing like supplements

GST usually washes out for a registered seller, so exclude it from the margin calculation, but do exclude it from the revenue side too. Comparing GST-inclusive revenue against ex-GST COGS inflates every margin by roughly the tax rate, and we see it constantly.

Do this at SKU level, dump it into a sheet, and sort descending. Most catalogues break cleanly into three or four clusters. If yours doesn't, you probably have a pricing problem rather than an ads problem.

Getting margin bands into the Merchant Center feed

Google won't accept "contribution margin" as a field, so use custom_label_0 through custom_label_4. We normally write the band into custom_label_0 as margin_high, margin_mid, margin_low, and reserve custom_label_1 for stock depth so you can throttle bestsellers that are about to go out of stock.

On Shopify the practical routes are a metafield per product populated from your margin sheet and surfaced through your feed app, or a tag-based approach if your feed app maps tags to custom labels. Metafields are cleaner and survive theme changes. Tags are faster to set up and easier for a merchandiser to edit without touching admin metafield definitions. Pick based on who maintains it.

The awkward case: if you sell the same product at different prices across markets — say a Shopify Markets setup covering India and the UAE, where your Dubai pricing carries a different landed cost and no COD losses — margin bands diverge per market and one custom label can't hold both. You need separate feeds per country, which most feed apps handle, and separate campaigns anyway because currency and bidding differ.

Recalculate the bands monthly. Cost prices move, freight rates move, and a SKU that crossed into the top band because of a supplier discount should get its budget back when the discount ends.

Structuring the campaign: one campaign or three?

Asset groups inside a single Performance Max campaign share a budget and a bidding target. That's the constraint that matters. If you want different tROAS per margin band — and you do, that's the whole point — you need separate campaigns, not separate asset groups within one.

So the real structure is:

  • Campaign A, high margin. tROAS around 2.5-3x. Most of the budget. Listing group filtered to custom_label_0 = margin_high.
  • Campaign B, mid margin. tROAS 4-5x. Moderate budget.
  • Campaign C, thin margin. tROAS 7x or higher, small budget, or excluded from paid acquisition entirely and pushed through email and on-site cross-sell instead.

Inside each campaign, then use asset groups for creative relevance — different image sets and headlines for different product families. That's what asset groups are actually good at. Creative, not economics.

To work out your target for each band, invert the margin. Break-even ROAS is 1 divided by contribution margin. At 55% margin, 1 ÷ 0.55 = 1.82x. At 25%, 1 ÷ 0.25 = 4x. At 15%, 6.67x. Add your desired profit on top and your overheads, and you have a floor. If a band's realistic ROAS ceiling is below its break-even, stop advertising it. Some brands need to hear that about a third of their catalogue.

Budget minimums, and when three campaigns is two too many

Performance Max needs volume to learn. Below roughly 30 conversions a month per campaign the bidding stays jumpy and you'll misread noise as signal. In practice that means a brand spending under about ₹2,00,000 a month across Google should run one Performance Max campaign, filtered to high and mid margin products only, and exclude the thin tail through the listing group. Two bands, one campaign, done.

Splitting a small account into three campaigns produces three campaigns that all learn badly. We've had to undo this more than once, usually after a previous agency built a beautiful structure that the data volume couldn't support.

Feeding it signals that respect margin

Two things move Performance Max more than most people expect.

First, conversion value. If you send Google order revenue, it optimises for revenue. Send profit instead. Shopify's Google & YouTube channel sends revenue by default, so this means a custom purchase event via GA4 or the Google tag where the value parameter is your calculated contribution rather than the order total. Once Google is bidding on profit, a lot of the structural work becomes redundant, because the algorithm stops chasing cheap conversions on its own. Getting the tracking right is fiddly — you need margin data available client-side or a server-side setup — but it's the version of this that scales.

Second, audience signals. Feeding a customer list of high-LTV buyers into the high-margin campaign works better than a generic all-purchasers list. Segment by second order, not first.

Brand traffic will eat your high-margin campaign if you let it

Performance Max absorbs branded search unless you stop it. Branded search converts cheaply, so the high-margin campaign's ROAS looks excellent while you're mostly paying for people who typed your name.

Ask your Google rep to apply brand exclusions at campaign level, and keep a separate exact-match brand search campaign so you can see that spend in isolation. If your high-margin Performance Max campaign is reporting 9x and your brand search is reporting 11x, they're running on the same traffic and you're double-counting. Check search terms in the Insights report. It's incomplete, but the pattern is visible.

What the first six weeks look like

Week one to two: don't touch it. Performance Max needs about two weeks to settle after any structural change, and impatient tROAS adjustments reset the learning.

Week three: check whether spend is actually landing on the products you filtered for. Listing groups occasionally behave oddly when a feed has stale custom labels. We get feed label mismatches on the first pass maybe a third of the time.

Week four onward: move tROAS in increments of no more than 15%. If the high-margin campaign is holding target and spending its full budget, raise the budget by 20% and leave the target alone. If it's underspending, the target is too high for available inventory of demand.

Festive season changes the maths. Through the Diwali window, RTO rates climb, courier SLAs stretch, and discounting compresses margin on exactly the products you'd been scaling. Recalculate bands before the sale period, not after. A 45% margin SKU discounted 25% is a 27% margin SKU, and it belongs in a different campaign for those three weeks.

The bit that isn't Google's fault

If your product page takes 4 seconds to render on a mid-range Android on 4G, no campaign structure saves you. Performance Max drives a lot of traffic through Display and YouTube placements, which skew mobile and skew impatient. We have seen accounts where fixing a 3.8s LCP down to 1.6s moved Performance Max ROAS more than six weeks of bid work did, because Google's bidding responds to conversion rate and conversion rate responds to speed. If you haven't checked, run SwiftStore against the store before you touch the campaign, or read through how we approach Shopify speed optimization generally.

Same for collection pages. If your Performance Max traffic lands on a 400-product collection with no usable filtering, you're paying Google for sessions that bounce.

Start here

Build the margin sheet first. Every SKU, all the deductions above, sorted descending. Before you touch Google Ads, look at where your last quarter's ad spend actually went against that sorted list. Most brands find 30-40% of spend sitting below break-even ROAS, and the fix is a filter, not a rebuild.

If you want a second pair of eyes on the feed, the campaign structure and the store speed underneath it, our free audit covers all three.

Previous postNext post

Ready to scale your D2C brand profitably?

Let's build a growth engine that drives more traffic, more conversions and more profit.

Book a Growth Audit
📅 Free Audit💬 WhatsApp