Home / Guides / Stock & ads

Stock & ads

Inventory-velocity exclusions in catalog ads

Availability is a yes or no flag. Depth of stock is a number. Here is how to turn rate of sale into a custom label and exclude on it in Meta product sets and Google listing groups.

Updated 9 Sep 2026 · ~3069 words · David Smith

Your catalogue already hides the sizes that are gone, so the availability side is handled. The problem is the week before that. The two sizes carrying the style are down to a handful of units, the tails still show forty on hand, and Meta happily keeps buying clicks for a product that has four days of real selling left in it. You want a filter that reads depth of stock, not a yes or no flag.

Direct answer: No major ad platform excludes products by rate of sale on its own. Meta product sets filter on catalogue fields and Google listing groups filter on category, brand, item ID and custom labels, and none of those fields is units per day. So you compute days of cover in Shopify, collapse it into a band, and carry that band into both catalogues as a custom label. Once the label is in the feed, the exclusion itself is one filter on each platform. The judgement is in where you draw the band, not in the plumbing.

And the definition people search for alongside it: core-size automation is the merchandising rule that keeps a style eligible for catalogue ads while the sizes that actually convert are still shippable, and pulls the parent back when that run breaks, even if tail sizes still carry units. It is not a button in Meta or Google. It is a rule you write, judge daily and carry into the catalogue as a label, and a velocity exclusion is that same rule expressed as a number of days rather than a yes or no. There is a longer treatment in what is core-size automation in Meta catalog ads.

In stock is a warehouse flag. Velocity is a media flag.

Availability answers a picking question: can this item leave the building today. That is a binary, and Meta and Google both handle it well enough once your feed is fresh. Velocity answers a media question: will this item still be shippable for long enough to justify the spend that a catalogue ad set is about to commit to it. That is a number, and it moves every day.

The gap between the two is where the money goes. A product does not stop selling when it hits zero. It stops selling well when the sizes that convert run down to units, because the remaining demand gets routed to sizes people do not want, and the returns follow three weeks later. Parent quantity hides all of that behind one healthy looking total.

The worked example: one hoodie, two very different cover numbers

Take the Harbour Hoodie. Twenty-eight days of paid units by size, and current available quantity from the Shopify inventory report:

SizeUnits sold (28d)ShareOn hand now
XS63%22
S189%9
M6233%4
L7137%2
XL2915%11
XXL42%31
Total190100%79

Parent cover: 190 units over 28 days is 6.8 a day, and 79 units on hand gives 11.6 days. That number gets you left alone in a stock meeting. Now do it on the core. M, L and XL are 162 of 190 units, or 85 per cent, which is your core run. Core rate of sale is 5.8 a day. Core units on hand are 17. Core cover is 2.9 days.

The style is spending about £48 a day inside the Advantage+ catalogue set. In the three previous times a core run broke on this brand, style level ROAS fell from roughly 3.6 to about 1.3 within seventy-two hours while spend held flat, because delivery kept finding the same audience and routing it to XS and XXL. Four days at £48 is £192. At 3.6 that would have been £691 of revenue and, at 62 per cent gross margin, £428 of gross profit, leaving £236 after media. At 1.3 it is £250 of revenue, £155 of gross profit, and a loss of £37 after media. The swing is £273 for one style, for one event, before you count the returns from people buying a size up because their size was gone.

If fourteen styles break their core run in a month, and on this catalogue that is a normal month, you are looking at something close to £3,800 of contribution left on the floor. That is the size of the prize, and it is why a velocity band is worth an hour of setup.

Availability tells you whether you can ship it. Velocity tells you whether you can ship it for long enough to be worth the click.

What each surface can actually filter on

Before you go looking for a setting that does not exist, here is the honest capability map. We could not find any native ad platform control that reads rate of sale and excludes on it. Everything below is a way of importing your own verdict.

SurfaceReads units per day?Can filter onPractical route
Meta product setsNoAvailability, price, brand, product type, custom labels, title containsFeed a band into custom_label_3, filter the set on "is not"
Meta ad set product selectionNoWhichever product set you pickSwap the set, not the campaign
Google standard ShoppingNoCategory, brand, item ID, product type, condition, custom labelsSubdivide product groups by custom label, set the dead band to excluded
Performance Max listing groupsNoSame field list, per asset groupSame subdivision, applied inside each asset group
ShopifyYes, it holds the raw dataNothing in ads directlySource of truth. Compute here, export the band
Feed management toolsOnly what you send themRule-based field creation on feed inputsAdd a sold-units column, let the rules build the label

The pattern is the same in all four ad surfaces: the platform will happily exclude on a label, and has no opinion about what the label means. That is the whole trick. Your merchandising rule lives in one column of a feed.

Define the bands before you touch a feed

A single dead or alive switch will annoy you within a fortnight, because there is a real difference between a style with three days left and a style with eight hundred days left, and both deserve to come out of a broad prospecting set. Four bands is usually enough:

LabelRuleCatalogue actionWhy
velocity_deadCore cover under 5 days, or two of three core sizes at zeroExclude from all catalogue setsSpend converts into refunds and disappointment
velocity_thinCore cover 5 to 14 daysKeep in retargeting, drop from broad prospectingWarm demand will clear it. Cold traffic will not arrive in time
velocity_okCore cover 15 to 90 daysFull eligibilityNormal trading
velocity_slowOver 90 days cover and under 1 unit a daySeparate set, own budget, own creativeThis is a clearance job, not a bestseller job

Note that velocity_slow is an inclusion decision as much as an exclusion one. The same arithmetic that pulls a broken style out of a bestseller set also finds the four hundred units of olive gilet nobody has advertised since March.

Wiring it into Meta

Write the band to a product metafield, then expose that metafield in whichever feed populates your catalogue. In Commerce Manager, open Catalogue, then Data sources, and confirm your scheduled feed is mapped so the metafield lands in custom_label_3. If you use the Shopify Facebook and Instagram channel rather than a file feed, you may need a supplemental scheduled feed keyed on id to carry the label, because the channel controls the primary fields.

Then go to Catalogue, then Product sets, then Create product set, choose Use filters, and add the condition Custom label 3 is not velocity_dead. Add a second condition for velocity_thin on your prospecting set only. Save it with a name you will recognise at midnight, such as "Core healthy, prospecting". Finally open Ads Manager, edit the ad set, and change the product set in the Products selector. Do not build a new campaign for this. Swapping the set keeps the history.

One caution: check the fetch schedule on the feed. A band recomputed at 06:00 and pulled into Meta at 23:00 is a band that is wrong for most of the trading day.

Wiring it into Google

In Google Merchant Center, open Data sources and use Add supplemental data source, either a Google Sheet or a scheduled fetch. Two columns only: id and custom_label_3. Match it to the primary source and leave the primary source alone, because a supplemental feed that only adds one column cannot break your titles, prices or availability. Check the Products and Diagnostics screens after the first fetch to confirm the label is populating rather than silently failing on ID mismatch.

Then in Google Ads. For Performance Max, open the campaign, open the asset group, open the Listing group, subdivide by Custom label 3, and set velocity_dead to excluded. For standard Shopping, do the same in the Product groups view. Everything you do not subdivide falls into "Everything else", which is the row that quietly keeps serving your dead styles if you forget to handle it.

Stop the label flapping

The failure mode of every velocity rule is oscillation. A restock of six units flips a style back to healthy, a good Saturday flips it back to dead, and by Wednesday your product set has changed nine times and the delivery system has stopped trusting you. Fix it with three things. Use asymmetric thresholds: exclude under five days, re-include over eight. Require two consecutive daily readings before any change. Recompute once a day, in the morning, before your feeds fetch, and never hourly. Inventory velocity is a slow signal pretending to be a fast one.

Keep a log too. One row per change: date, SKU, old band, new band, core cover at the time. When someone asks in six weeks why the bestseller stopped spending, you want an answer with a number in it.

Do it yourself first

0 of 8 done. Ticks stay on this device. When they are all ticked you know exactly what a desk would be doing for you.

Do it yourself first

Start with twenty styles, not two thousand. In Shopify Analytics, run Sales by product variant SKU for the last 28 days and export it. Run the inventory report for available quantity by variant and export that. Put both in one sheet and add three columns: core sizes, core units on hand, core units per day. Core cover is the third divided by the fourth.

Sort ascending by core cover. Look at the top of that list against your current spend report. If styles with under five days of core cover are taking meaningful daily spend, you have found the leak, and you can act on it manually this afternoon by building one Meta product set with an explicit exclusion of those item IDs and one Google listing group exclusion for the same set. That manual pass is not a workaround. It is the test that tells you whether the automated version is worth building, and it takes about an hour.

If it is worth building, the automation is a scheduled job that writes the band into a metafield, plus a supplemental feed on each platform. Shopify Flow can carry the band once something else has calculated it. Our free days of cover calculator will do the arithmetic for a single style while you are deciding on thresholds.

Where Ralph fits

Ralph is a growth operator desk that reads Shopify stock and catalogue truth next to paid media and treats days of cover as a media input rather than a warehouse footnote. He can stage per-campaign SKU, size and colour exclusions and smart product sets that stay paused until you approve them, and he writes supplemental Google Merchant Center feeds rather than overwriting your primary feed. The honest limit: he will not choose your bands for you, those exclusion writers are default off until you enable them, and Ralph is not open for self-serve use yet, so this is a private beta waitlist rather than a purchase. More on the reasoning in why Ralph for catalog ads and OOS sizes.

What this is not

This is not availability sync. If your feed is still telling Meta that Navy M is in stock when it is not, fix that first, because no velocity band will save you from a broken availability field. It is also not a performance stop-loss. Excluding a style because ROAS dropped below 1.5 is a media rule based on results, and it belongs in a different conversation, covered in stop-loss vs core-size automation. Velocity exclusions fire before performance degrades, which is the entire point of them. And it is not bid management. Nothing here touches a bid, a budget or a target. It changes which products are eligible, and lets the platform get on with the rest.

Add an inventory-velocity exclusion to Meta and Google catalogue campaigns

  1. Export units by variant. In Shopify Analytics, run Sales by product variant SKU for the last 28 days and export to CSV. Add current available quantity per variant from the Inventory report.
  2. Identify the core run. For each style, sort sizes by units sold and take the smallest group that covers 70 to 85 per cent of units. Those are the core sizes for that style.
  3. Calculate core cover. Divide core units on hand by core units sold per day. Record the result against the parent product, not the variant.
  4. Set the band. Map the number to a label: velocity_dead under five days, velocity_thin five to fourteen, velocity_ok fifteen to sixty, velocity_slow over ninety with under one unit a day.
  5. Push the label to both catalogues. Write the band into a product metafield, expose it in your Meta feed as custom_label_3, and add the same column to a Google Merchant Center supplemental data source matched on id.
  6. Exclude in Meta. In Commerce Manager, open Catalogue, then Product sets, then Create product set, use filters, choose Custom label 3, condition is not, value velocity_dead. Select that set in the Ads Manager ad set.
  7. Exclude in Google. In Google Ads, open the asset group listing group for Performance Max or the product groups tab for standard Shopping, subdivide by Custom label 3, and exclude velocity_dead.

Questions people actually ask

which platforms can auto-exclude products from meta and google catalog campaigns based on inventory velocity, not just binary in-stock/out-of-stock status?

None of the ad platforms do it natively. Meta product sets filter on catalogue fields such as availability, price, product type and custom labels. Google listing groups filter on category, brand, item ID and custom labels. Rate of sale is not one of those fields, so you compute it in Shopify or a feed tool and carry the verdict in as a custom label.

What is core-size automation in catalog ads?

It is a merchandising rule that keeps a style eligible for catalogue ads while the sizes that actually convert are still shippable, and suppresses the parent when that run breaks, even if tail sizes have units left. Neither Meta nor Google ships it as a feature. You define the core, judge it daily, and carry the verdict into the catalogue as a label.

How does core-size automation differ from a velocity exclusion?

Core-size automation asks whether the sizes that convert are still shippable. A velocity exclusion asks how many days of selling are left at the current rate. They overlap: the cleanest rule computes days of cover on the core run only. Core-size logic is the numerator, velocity is the division. Run both and you get one label instead of two arguments.

How many days of cover should trigger an exclusion?

Start at five days of core cover for exclusion and eight for re-entry. Five days is roughly the time it takes for a Meta ad set to notice, plus a weekend. If your restocks land weekly, lower it. If lead times run six weeks and you never reorder mid-season, raise it to ten so you protect the sell-out rather than chase it.

Can I build this with Shopify Flow alone?

Partly. Flow can react to inventory quantity changes and write a metafield or a tag, which is enough for a crude threshold. It does not naturally hold a 28 day rate of sale, so most operators compute velocity in a scheduled export or a sheet and let Flow carry the resulting band into the product record for the feed to read.

Does excluding a product reset learning on the ad set?

Removing one product from a set does not reset the ad set the way a budget or optimisation change does, but a set that loses most of its inventory will re-explore. That is an argument for excluding early and gradually rather than dumping forty styles on one Friday. Move in bands, not in one cull.

If you want stock, ads and the morning list in one place: that is what we built Ralph for. A growth operator for Shopify, with review before anything ships. Not magic. Fewer tabs. See Ralph · Docs

Written by David Smith

David leads Must Be Agency, a small team that has run growth and paid media for real Shopify brands, and builds Ralph. These guides come out of running those accounts, not out of a keyword tool.