OOS bestsellers leak revenue while ad spend continues, feeds ads_on_oos kill-shot.
At a glance
Real-time count of distinct products in the Salesforce Commerce Cloud realm whose inventory level has fallen to zero (or below the backorder allowance). Feeds the cross-channel “Active Ads on Out-of-Stock SKUs” kill-shot, paid acquisition pushing traffic to a dead-end PDP is the most expensive leak on a commerce stack.
| What it counts | COUNT(DISTINCT productId WHERE availabilityModel.inStock = false) across every inventory list connected to any siteId in the realm, evaluated in real time. |
| VAT / tax treatment | n/a, this is a count of products. |
| Shipping | n/a, count metric. |
| Discounts | n/a, count metric. |
| Refunds | n/a, count metric. |
| Cancelled / voided orders | n/a, this card looks at inventory, not orders. |
| Currency | n/a, count metric. |
| Inventory model | Per inventoryListId, not per siteId. Multiple sites typically share one warehouse-backed inventory list. A SKU at zero on the shared list shows OOS on every site at the same moment. To get per-site OOS counts, sites must be assigned distinct inventory lists (a realm setup decision). |
| Backorder allowance | A SKU with available_for_backorder = true continues to show in-stock at zero ats; only false-flagged SKUs flip to OOS. A SKU with allocation against future deliveries (scheduled_inventory > 0) follows the merchant’s preorder rule. |
| Reservation handling | SFCC reserves inventory during checkout (ats - reservedAtsLevel); abandoned-checkout reservations expire after the configured timeout (typically 30 to 60 minutes). The card uses the post-reservation available-to-sell figure, not the raw warehouse count. |
| Variation Master products | A Variation Master shows OOS only when every variant is OOS. A specific colour / size variant going OOS does not flip the master to OOS; the variant-level dial is on a separate card. |
| B2B inventory | Counted with the same definition. B2B products often run on a separate inventory list with contracted stock allocations; filter by inventoryListId to read DTC vs B2B independently. |
| Time window | RT (real-time, evaluated on the most recent OCAPI / SCAPI inventory snapshot, typically <60 second freshness) |
| Alert trigger | >10 (placeholder default), tune per-realm. A 50,000-SKU realm with hero-product concentration cares about OOS only on the 200 hero SKUs; raise the threshold and add a category filter. |
| Roles | owner, operations |
Calculation
Calculated automatically from your Salesforce Commerce Cloud data. See the At a glance summary above for what the metric tracks and the worked example below for a typical reading.Worked example
A Fortune-500 fashion retailer running on Salesforce Commerce Cloud, 4 DTC sites + 1 B2B portal + 1 headless sub-brand, ~38,000 SKUs total. Reading at 09:30 UTC on 12 Apr 26.inventoryListId | Sites it serves | Total SKUs | OOS count | Hero SKUs OOS | Notes |
|---|---|---|---|---|---|
inv-us-warehouse | RefArch-US, Headless-Subbrand | 22,400 | 1,840 | 14 | Shared between flagship and sub-brand |
inv-eu-warehouse | RefArch-UK, RefArch-DE | 18,200 | 1,210 | 9 | One EU warehouse for both UK and DE |
inv-jp-warehouse | RefArch-JP | 14,600 | 1,420 | 12 | JP-specific inventory, smaller catalogue |
inv-b2b-allocation | RefArch-B2B | 4,200 | 38 | 0 | Contract-allocated, low OOS by design |
| Realm-wide (distinct) | ~38,000 | 4,508 | 35 | 11.9% of catalogue OOS at this moment |
- The realm-wide OOS count of 4,508 (11.9%) is well above the
>10placeholder threshold. The default alert would fire constantly on this realm. Tune the threshold to (a) hero SKUs only (35 OOS, more actionable) or (b) a percentage-of-catalogue rule (>15% would be the right alert-fire level here, currently 11.9%). - 35 hero SKUs are OOS right now. That is the actionable number on a 38,000-SKU realm. Each hero OOS SKU is leaking ~40,000 / day in lost revenue depending on velocity and AOV. The cross-channel kill-shot card (Active Ads on Out-of-Stock SKUs, when added) joins this list against active campaigns; on this realm 11 of the 35 hero OOS SKUs have active Google Ads / Meta Ads, ~$8,400 / day in acquisition spend pushing customers to dead-end PDPs.
- The shared
inv-us-warehouselist serves both the flagship US site and the headless sub-brand. When a SKU goes OOS on this list, both sites flip simultaneously. The per-site OOS reading is therefore the same on both, this is by design, not a bug. To split, the merchant would need to allocate the sub-brand to a distinct inventory list with its own stock pool. - B2B OOS count (38) is structurally low. B2B uses contract-allocated stock; OOS happens only when contracted volume is exhausted. A B2B OOS spike usually means the buyer-team’s forecast was below actual draw-down, not a fulfilment outage.
- The Monday-morning effect is real. Read at 09:30 UTC Monday: count is 4,508. Same realm Friday at 17:00 UTC last week: 3,940. Weekend sales ran the hot SKU list down; Monday inbound restocking is incomplete. The number drops as Monday afternoon’s warehouse shifts get put away. Pair with Top Products to confirm the Monday OOS list overlaps with the weekend top-sellers.
Sibling cards merchants should reference together
| Card | Why pair it with Out-of-Stock Products |
|---|---|
| Top Products | The hero-SKU list. OOS on a top-10 SKU is operationally a different conversation from OOS on a long-tail SKU. Filter the OOS list against this for the actionable subset. |
| Low Stock | The leading indicator. Low Stock fires before OOS; lets the merchandising team restock before the SKU goes dark. |
| Total Revenue | The lost-revenue context. A 1pp lift in OOS percentage on a 3M in annualised gross leakage, depending on substitution. |
| Conversion Rate | OOS spikes drop CR. A 2pp CR drop with a 12% catalogue OOS share is usually the same story. |
| Refund Rate | A counter-intuitive pair: when OOS spikes, customers buy back-up SKUs they end up returning. OOS-driven refund rate is real. |
| Active Ads on Out-of-Stock SKUs | The cross-channel kill-shot. Joins the OOS list against connected ad platforms to surface paid acquisition spend that should be paused. |
| Total Orders | The volume context. OOS on a low-velocity SKU may not need same-day action; OOS on a high-velocity hero SKU needs immediate attention. |
adobe_commerce.oos_products | Closest enterprise-tier peer. Documentation cross-link only. |
Reconciling against the vendor’s own dashboard
Where to look in Business Manager: SFCC’s admin tool is Business Manager athttps://<realm>.business.demandware.net. The closest like-for-like view is Merchant Tools, Site, Inventory, Inventory Lists, [select list] then filter by availabilityStatus = NOT_AVAILABLE. The count of returned rows should approximate this card’s per-list OOS count.
For the realm-wide read, Merchant Tools, Administration, Inventory, Inventory Lists lists every list and a status summary; or use the Reports & Dashboards, Inventory view on enterprise realms with that module enabled.
Other Business Manager views that look like the same number but aren’t:
- Catalog → Products → filter by “Online = false”: includes products manually disabled, not just OOS.
- Search Indexes → Inventory Index status: shows the search-engine inventory snapshot; can lag the live inventory list by minutes.
- Einstein recommendations dashboard: products excluded from Einstein output; not the same population as OOS.
| Reason | Direction | Why |
|---|---|---|
Reservation timing. Vortex IQ uses post-reservation ats - reservedAtsLevel; some BM views show pre-reservation raw warehouse stock. | Vortex IQ higher (more SKUs flagged OOS) | Active checkout sessions on a low-stock SKU can flip it to OOS in this card while BM still shows it available. Reservations expire after the configured timeout. |
| OMS sync lag. If your Order Management System pushes stock updates on a schedule (e.g. every 15 minutes), there is always a window where the warehouse and SFCC disagree. Vortex IQ reads SFCC’s most recent OCAPI / SCAPI snapshot. | Either, depending on which side is fresher | Self-resolves at next OMS push. |
Backorder allowance. SKUs with available_for_backorder = true show in-stock at zero ats; they do not appear in this card. BM’s filter may include them as “OOS but backorderable”. | Vortex IQ lower | Operational policy choice, not a bug. |
| Variation Master vs variant. This card flags Variation Masters only when every variant is OOS. BM’s variant view counts each OOS variant individually. | Vortex IQ much lower than per-variant counts | The variant-level dial is a separate card. |
Excluded SKUs. Products with online = false for any reason (discontinued, seasonal hidden) are typically excluded from this card. BM’s full inventory list includes them. | Vortex IQ lower | Filter out online = false in BM to match. |
oos_count ÷ total_active_products is the right normalised view for cross-realm benchmarking; raw counts vary too much by catalogue size.
Cross-connector reconciliation:
This card has no direct payment- or analytics-side counterpart. Its primary cross-connector use is feeding the Active Ads on Out-of-Stock SKUs kill-shot card, which joins this list against connected ad platforms (Google Ads, Meta Ads, Microsoft Ads). For consistency:
| Card | Expected relationship | What causes legitimate divergence |
|---|---|---|
google_ads.product_status | A SKU OOS in this card AND active in Google Ads is the kill-shot signal | Google Merchant Center’s stock signal (via product feed) typically lags SFCC by 1 to 6 hours; Google may keep an ad serving on a SKU that flipped OOS minutes ago. |
facebook_ads.catalog_status | Same shape | Meta’s catalog feed sync varies from 30 minutes to several hours. |
Known limitations / merchant FAQs
Why does the OOS count look the same across all my sites? SFCC’s inventory model is perinventoryListId, not per siteId. Multiple sites typically share a single warehouse-backed inventory list (e.g. one US DTC inventory list serves both RefArch-US and the headless sub-brand). When a SKU goes to zero in the inventory list, every site assigned to that list sees it OOS at the same moment. To split per-site, attach distinct inventory lists per site (a setup decision). Most realms do not, deliberately.
A SKU is showing OOS but my warehouse system says we have stock. What’s wrong?
Three usual causes. (1) Reservation drift. SFCC reserves inventory during checkout (ats - reservedAtsLevel); if checkout sessions abandon without releasing the reservation, the available level lags actual stock. Reservations expire after the configured timeout (typically 30 to 60 minutes). (2) OMS sync lag. If your Order Management System pushes stock updates on a schedule (e.g. every 15 minutes via OCAPI or B2C-Commerce-to-OMS connector), there is always a window where the warehouse and SFCC disagree. (3) Backorder allowance setting. A SKU configured available_for_backorder = false flips to OOS at zero; one with true continues to show available. Check the SKU’s inventory record.
Will the card include B2B SKUs?
Yes, the count includes any product on any inventory list connected to a siteId in the realm. B2B products often have their own inventory list and contract pricebooks; if you only want a DTC view, filter by inventory list ID. B2B OOS handling is usually different operationally (the customer is allowed to backorder against contracted stock); the card flags both equally.
Why is the OOS count rising from the same baseline every Monday?
Two structural patterns common on enterprise SFCC realms. (1) Weekend sales clear stock. The hot SKU list runs hard Saturday and Sunday, hits zero on Monday morning before Monday inbound restocking arrives. Pair with Top Products to confirm the Monday-OOS list overlaps with the weekend top-sellers. (2) Receive-to-shelf delay. Inbound deliveries are received in the warehouse over the weekend but not put away (and therefore not flipped to “available” in SFCC) until Monday afternoon’s shift starts. The OOS count drops as Monday goes on.
How does this card feed the “Active Ads on Out-of-Stock SKUs” alert?
The cross-channel kill-shot card joins this OOS list against active campaigns in connected ad platforms (Google Ads, Facebook, Microsoft Ads). Any ad serving on a productId whose inventoryListItem.ats <= 0 triggers a real-time alert. The leakage cost is acquisition spend pushing customers to a dead-end PDP. Pause those ads first; restock or sub-recommend second.
Should I configure SFCC’s “show out-of-stock” or “hide out-of-stock” on the storefront?
Operational call, not a metric question. Most DTC SFCC sites hide OOS SKUs from category pages entirely (product.online == false or availabilityModel.inStock == false filtering), and show “Notify me when back” on the PDP. This keeps SEO equity but stops navigation friction. The card counts the underlying inventory state, not the storefront visibility.
Why is my realm-wide OOS count higher than the sum of my per-site counts?
A SKU shared across two sites only appears in the count once if it’s OOS once, but per-site reports may show it appearing on each site (where it is configured for each siteId and OOS in the shared inventory list). Use the per-inventory-list view when reconciling against finance / merchandising counts.
The card threshold is >10, but we sell 50,000 SKUs. Is 10 the right alert level?
Almost certainly not. The threshold is a placeholder; tune per realm based on (a) total SKU count and (b) what fraction of revenue comes from the long-tail vs hero SKUs. A realm with 50,000 SKUs where 80% of revenue comes from 200 hero SKUs cares about OOS only on those 200; raise the threshold and add a per-tag filter (e.g. category = bestsellers) to the alert. A 1,000-SKU long-tail-heavy boutique might want the threshold at 1.