All articles
Automation5 min read

Out of stock products in catalog ads

Availability lives in your product feed, so out of stock products in catalog ads can spend for days while every ad metric looks fine. Here is the fix.

You find it in the month-end export, never before. Somewhere around a third of the catalog budget went to products that could not be bought on the day the click happened. Two of them had been sold out since the second week. The ad set that carried them looked healthy the whole time: CTR steady, CPM flat, ROAS a little soft but inside the range you would shrug at.

Nobody misconfigured anything. The ads were doing exactly what they were told.

Short answer: Out of stock products in catalog ads keep spending because availability is a field in your product feed, not a setting in Ads Manager. Meta stops serving an item once the feed says it is gone, so every hour of lag between the store and the next feed pull is paid delivery.

The takeaways

  • Delivery follows the availability value in your feed (in stock, out of stock, preorder). Your shop's live stock count never reaches Meta on its own.
  • A dead SKU is invisible at ad level. A catalog ad set reports blended numbers, so one product dropping to zero moves nothing you look at.
  • The reverse case costs more. When a top seller sells out mid-flight, conversion rate falls under unchanged spend and reads as creative fatigue.

Why does an out of stock product keep getting delivery?

Because the ad system is reading a file, and the file is old. Your store knows an item is gone the second the last unit ships. Meta knows when the next feed pull lands, and scheduled pulls run on a clock: some setups refresh a few times a day, some once. A product that sells out at 10am on a Tuesday can serve until the evening on nothing but stale data.

That gap is structural. It is the normal behaviour of a scheduled sync, so no amount of rule-writing inside Ads Manager closes it. The lever is the update mechanism itself: raise the pull frequency, or push the change at the moment stock hits zero through a direct integration or the catalog API. On a fast-moving catalog with flash sales, the default cadence your shop app shipped with is almost always too slow for the way you sell.

How does one dead SKU hide inside a healthy ad set?

It hides in the averaging. Every number you check sits at ad or ad set level, and a catalog ad set with 400 items reports one CTR, one CPM, one ROAS across all of them. A single product going quiet gets absorbed by 399 others. You would need a product-level breakdown to see it, and that view is not where anyone looks during the week.

This is the same reporting wall that stops you writing a rule against a losing SKU, which I went through in more detail in pausing losing products in catalog ads. The short version: the rule builder knows campaigns, ad sets and ads, and stops there. Whatever happens to an individual product has to be caught somewhere other than the rule builder.

What makes the availability value wrong in the first place?

Three failure modes, in the order I have hit them. First, mapping. If the availability column in your feed template was pointed at the wrong source field, or hardcoded during setup, every item reports as sellable forever and the feed looks perfectly healthy while it lies. Nothing errors, because a valid value is present.

Second, the product set. A set defined by a rule (a category, a price band, a brand) keeps serving whatever falls into it, so items you assumed were excluded quietly qualify.

Third, Meta's own check. The feed is one input among several: Meta also reads the product page and pixel activity, which means items can flip to unavailable while your shop shows plenty of stock. Slow pages and variant data that loads late both cause it, and that direction is worth knowing about because the symptom is the opposite one: eligible items falling out for no visible reason.

Why does a sold-out bestseller read as a creative problem?

Because delivery keeps favouring the item with the best history right up until the feed says otherwise. Your top SKU converts, the algorithm leans on it, and then it sells out. For the rest of the lag window the same spend flows into an ad that shoppers click and bounce off, so conversion rate falls while cost per result climbs. Nothing in the account changed, so the meeting decides the creative is tired.

Then it corrects, and the set is still worse off, because the product carrying the conversion rate is gone from the pool. If a catalog campaign drops without an obvious cause, the catalog layer is worth reading before the creative. Rewriting an ad for a stock problem is the most expensive way to spend a week.

What catches this early?

Feed-side signals, plus one habit. Watch the item error and disapproval counts, the feed processing status for failed or partial uploads, and the eligible item count over time. A sharp fall in eligible items is the earliest honest alarm you get. Pair that with a spend-by-product read once a week, which is dull and takes ten minutes and finds money every time.

The habit is simply the order of operations: when a catalog campaign turns, check the feed before you touch the creative. It costs one click and it settles the argument.

What you can automate, and where the line sits

Half of this is automatable. Adscalr's rules fire on 8 ad metrics (CPI, CTR, hook rate, hold rate, ROAS, spend, frequency, CPM), the only actions are pause and kill, every evaluation is logged, and a kill stays reversible for 30 minutes. Full-auto is opt-in, so the default is a recommendation you approve. That covers the spend side, which is the half of the problem living in the ad account.

Stock levels sit outside what any of that can see. Adscalr reads ad performance, so the feed work stays platform-side and yours. That boundary is worth stating plainly: automation and alerts gives you the spend guardrail and the discipline around it, and the availability field remains a job for your shop integration.

This is the thinking behind Adscalr.

See the product