---
title: "WooCommerce out of stock and discontinued products and SEO"
url: https://wpministry.co/blog/woocommerce-out-of-stock-products-seo/
description: "An out-of-stock WooCommerce product keeps its page, which answers 200. One gone for good is redirected to a true replacement or left to answer 404."
lang: en-US
---

Skip to content

# WooCommerce out of stock and discontinued products and SEO: leave, hide, delete or redirect

An out-of-stock WooCommerce product keeps its page. The address still answers 200 and its structured data changes to OutOfStock, so a product that is coming back needs nothing done. One that is gone for good is redirected to a true replacement or left to answer 404, never sent to the home page.

By

WP Ministry

Published

October 8, 2026

Tested on

WordPress 7.1.4, WooCommerce 11.2.0, PHP 8.3.36

## In short

- When a product runs out, WooCommerce changes availability in its structured data to https://schema.org/OutOfStock and removes the add-to-cart button. The address still answers 200, with no noindex.
- "Hide out of stock items from the catalog" takes the product out of the shop, category pages and product search. Its own address still answers 200 and it stays in the sitemap.
- When stock returns, the value goes back to InStock by itself. If the page was left alone, there is nothing to undo.
- A product that is trashed, deleted, draft or private answers 404 to a visitor. WordPress can instead redirect the address to a product with a similar slug, so check what it answers.
- Google's documentation says a removed page with no replacement should answer 404 or 410, and a page with a clear replacement should be redirected to it with a 301.
- On a variable product with one variation sold out, the product's markup still says InStock. Only the address that names that variation says OutOfStock.

When a WooCommerce product runs out, its page stays where it is. The address still answers 200. The page prints "Out of stock" where the add-to-cart button was, and the `availability` in its structured data changes from `https://schema.org/InStock` to `https://schema.org/OutOfStock`. WooCommerce adds no `noindex` and takes nothing out of the sitemap. When stock returns, the value changes back by itself.

So a product that is coming back needs nothing done to its page. A product that is gone for good is a different decision: redirect its address to a true replacement, or let it answer 404. This page covers both, in two halves. Each half says what WooCommerce does by itself and what Google's documentation says about the answer a crawler then gets. It makes no claim about where a page is listed in search results.

The examples use a store at `https://example.com` that sells a Blue Kettle at `/product/blue-kettle/` and a Red Kettle at `/product/red-kettle/`. Put your own addresses in their place.

## Part one: a product that is out of stock

### What changes on the product's page

The stock status is on the product's edit screen, in the "Product data" box under the Inventory tab. "Stock status" has three choices. This is what each one puts on the product's page.

| "Stock status" | `availability` in the structured data | What a visitor sees | The address answers |
| --- | --- | --- | --- |
| In stock | `https://schema.org/InStock` | The add-to-cart button | 200 |
| Out of stock | `https://schema.org/OutOfStock` | "Out of stock", and no add-to-cart button | 200 |
| On backorder | `https://schema.org/BackOrder` | "Available on backorder", and the add-to-cart button | 200 |

If "Track stock quantity for this product" is ticked, there is no "Stock status" to choose. WooCommerce sets the status from the quantity and from "Allow backorders?".

Three things do not change when a product runs out.

- **The price stays.** The page still shows it, and the offer in the structured data still carries it.
- **The robots tag stays.** It reads `max-image-preview:large` before and after. WooCommerce adds no `noindex` to a product that is out of stock.
- **The sitemap stays.** The product is still listed in WordPress's product sitemap.

WooCommerce schema markup and rich snippets (https://wpministry.co/blog/woocommerce-schema-markup-rich-snippets/) covers the rest of the structured data on a product page and how to test it.

### Read the value your store serves

This asks for a product's page and prints the `availability` in it.

bash

```
curl -s https://example.com/product/blue-kettle/ | grep -o '"availability":"[^"]*"'
```

text

```
"availability":"https://schema.org/OutOfStock"
```

Without a terminal, open the product's page, view its source, and search for `availability`.

### Change the stock status with WP-CLI

Editing the product and choosing "Out of stock" is the usual way. With many products, WP-CLI does the same from the command line. Put the product's ID in place of `123` and the username of an administrator in place of `admin`. WooCommerce's commands refuse to run without `--user`. How to use WP-CLI (https://wpministry.co/blog/use-wp-cli-manage-wordpress/) covers connecting and where to run commands.

bash

```
wp wc product update 123 --user=admin --in_stock=false
```

It answers `Success: Updated product 123.`

### What "Hide out of stock items from the catalog" does

Go to WooCommerce, then Settings, open the Products tab and choose Inventory. The row "Out of stock visibility" holds one checkbox, "Hide out of stock items from the catalog". It is unticked on a new store. WooCommerce stores it as the option `woocommerce_hide_out_of_stock_items`, which is `no` while the box is unticked and `yes` while it is ticked.

bash

```
wp option get woocommerce_hide_out_of_stock_items
```

This is where a product that is out of stock appears, with the box each way.

| Place | Box unticked | Box ticked |
| --- | --- | --- |
| The shop page | Listed, with "Read more" in place of the add-to-cart button | Not listed |
| Its category page | Listed | Not listed |
| A product search (`?s=kettle&post_type=product`) | Listed | Not listed |
| The site's ordinary search (`?s=kettle`) | Listed | Still listed |
| The product's own address | 200, with `OutOfStock` | 200, with `OutOfStock` |
| The product sitemap | Listed | Still listed |

"Related products" on another product's page depends on the theme. With a block theme and WooCommerce's own product template, that section lists only products that are in stock or on backorder, whichever way the box is set. On a classic theme, WooCommerce picks related products with a function that leaves out products that are out of stock only while the box is ticked.

So the box changes your own listings and nothing else. It does not take the page down, does not add `noindex`, and does not remove the address from the sitemap. A search engine that already knows the address can still fetch the page and read `OutOfStock` on it. What does change is that the shop and category pages stop linking to the product for as long as the box is ticked and the product is out of stock.

### What Google's documentation says availability is for

Google's documentation for merchant listings says a listing can show a product's price, its availability, and shipping and return information. In that documentation `availability` is a recommended property of the offer, not a required one. It accepts ten values: `BackOrder`, `Discontinued`, `InStock`, `InStoreOnly`, `LimitedAvailability`, `OnlineOnly`, `OutOfStock`, `PreOrder`, `PreSale` and `SoldOut`, each with or without the `https://schema.org/` in front, and it asks for only one value per offer.

WooCommerce prints three of the ten: `InStock`, `OutOfStock` and `BackOrder`. It has no status that produces `Discontinued`, `SoldOut` or `PreOrder`.

The same documentation recommends putting product markup in the HTML the server sends, because availability and price change fast. WooCommerce does that: the value in the table above is in the page as served.

### What Merchant Center does with an item that is out of stock

This matters only if your store sends its products to Google Merchant Center. Merchant Center's help page for the availability attribute says these things.

- **Availability is required for every product,** and takes one of four values: `in_stock`, `out_of_stock`, `preorder` and `backorder`.
- **It maps the values in your markup to its own.** `InStock` counts as `in_stock`, `OutOfStock` as `out_of_stock`, and `BackOrder` as `backorder`. `Discontinued` and `SoldOut` also count as `out_of_stock`.
- **The values have to agree.** The product data, the product's page, its structured data and the checkout must show the same availability. A mismatch gets the product disapproved.
- **A product on backorder needs a date.** Merchant Center requires an availability date for `backorder`, and wants that date visible on the product's page. WooCommerce prints "Available on backorder" with no date, so the date is yours to add to the page.
- **A product that is temporarily out of stock stays in the product data,** marked `out_of_stock`. The page advises against deleting an item you will sell again, because an item added back takes a significant time to show again.
- **A product you no longer sell is removed from the product data,** not left there as `out_of_stock`.

The product data specification adds that the price must still be visible on the page of an item that is out of stock. WooCommerce keeps it there, as above. Mismatched price in Merchant Center on a WooCommerce store (https://wpministry.co/blog/merchant-center-mismatched-price-woocommerce/) covers the price side of the same check.

### When it comes back in stock

Set "Stock status" back to "In stock", or run the command below. The add-to-cart button returns and the structured data says `InStock` again from the next request. If "Hide out of stock items from the catalog" is ticked, the product returns to the shop and its category by itself.

bash

```
wp wc product update 123 --user=admin --in_stock=true
```

If the page was left published, there is nothing else to undo: the address never changed and never stopped answering 200. If a caching plugin stores whole pages, clear it, so that visitors and crawlers are not served the copy that says "Out of stock".

## Part two: a product that is gone for good

### What each choice gives a visitor and a crawler

| What you do | The product's address answers | In the product sitemap |
| --- | --- | --- |
| Leave it published and out of stock | 200, with `OutOfStock` | Yes |
| Set "Catalog visibility" to "Hidden" | 200. The shop, category pages and both searches stop listing it | Yes |
| Switch it to draft | 404 | No |
| Make it private | 404 for anyone who is not logged in | No |
| Move it to the trash | 404 | No |
| Delete it permanently | 404 | No |

This command prints the status an address answers with, and where it redirects to if it does. It does not follow the redirect.

bash

```
curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" https://example.com/product/blue-kettle/
```

text

```
404
```

And this one lists the addresses in WordPress's product sitemap. An SEO plugin that makes its own sitemap replaces this one, and the WordPress sitemap at wp-sitemap.xml (https://wpministry.co/blog/wordpress-sitemap-wp-sitemap-xml/) shows how to tell which one a site serves.

bash

```
curl -s https://example.com/wp-sitemap-posts-product-1.xml | grep -o "<loc>[^<]*</loc>"
```

### What the trash does to the address

Moving a product to the trash does not reserve its address. WordPress renames the slug of a trashed post, so `blue-kettle` becomes `blue-kettle__trashed`, and it keeps the original in a field named `_wp_desired_post_slug` so that a restored post can try to take it back. WordPress has done this since version 4.5.

- **Restored before anything took the slug,** the product comes back published at its old address.
- **If a new product was given the same name in the meantime,** the new product has the address. The restored one becomes `/product/blue-kettle-2/`.
- **The trash empties itself.** WordPress's documentation gives 30 days as the default, set by `EMPTY_TRASH_DAYS` in `wp-config.php`. After that the product is deleted permanently.

### WordPress may redirect the address by itself

A removed product's address does not always answer 404. When WordPress has nothing at an address, it looks for a published post whose slug begins with the same words and, if it finds one, redirects there with a 301.

With a Blue Kettle in the trash and a Blue Kettle Large still published, the command above prints this:

text

```
301 https://example.com/product/blue-kettle-large/
```

The answer carries the header `X-Redirect-By: WordPress`, which is how to tell this redirect from one of your own. It happens the same way for a product that was deleted, or switched to draft.

So check what the old address answers before you decide it is a 404. If WordPress sends it to a product that is not a replacement, a rule of your own for that address answers first. Both rules below do that. WordPress also has a filter, `do_redirect_guess_404_permalink`, that switches this guessing off for the whole site.

### What Google says about each answer

**A 404 or a 410.** Google's documentation on status codes says it treats every 4xx answer except 429 the same way. It does not use the content, and an address that was indexed is removed from the index. Its guidance on soft 404 errors says that a page you removed, with no replacement that has similar content, should answer 404 or 410. Search Console's help for the Page indexing report adds that a 404 is not necessarily a problem when a page was removed without a replacement.

**A redirect.** The same guidance says that when a page has moved or has a clear replacement, the old address should answer with a 301 to it. Google's page on redirects says a permanent redirect is a signal that the target should be the address shown in results.

**A redirect to something unrelated.** Google's guide to moving a site warns against sending many old addresses to one irrelevant destination, such as the home page, and says:

> This can confuse users and might be treated as a soft 404 error.

That sentence is written about site moves. Google's pages on status codes, on soft 404 errors and on redirects do not repeat it. It is still the reason not to point every discontinued product at the home page.

**A page that stays up.** A discontinued product left published answers 200 and says `OutOfStock`, which is one of the values Google's product documentation accepts. Google describes a soft 404 as a page that tells the visitor it does not exist while answering 200, and says it leaves such pages out of Search. Its documentation does not say whether a product page that has been out of stock for a long time is read that way.

### Redirect a discontinued product to its replacement

Use this when a newer model has taken the product's place. The rule goes in `.htaccess` on an Apache server and answers before WordPress starts, so it works whether the old product is in the trash, deleted or still published. How to set up redirects in WordPress (https://wpministry.co/blog/set-up-wordpress-redirections/) has the other ways: a redirect plugin's list, nginx, and code.

1. ### Step 1: Ask what the old address answers now
   Run the command under "What each choice gives a visitor and a crawler" for the old product's address. Note whether it prints 200, 404, or a 301 that WordPress made.
2. ### Step 2: Add the rule above WordPress's block
   Put the rule at the top of `.htaccess`, above the line `# BEGIN WordPress`. WordPress rewrites the lines between its two markers, so a rule placed there is lost.
   .htaccess Copy

   ```
   RedirectMatch 301 "^/product/blue-kettle/?$" "/product/red-kettle/"
   ```

3. ### Step 3: Ask again
   The command should now print 301 and the replacement's address.
   text Copy

   ```
   301 https://example.com/product/red-kettle/
   ```

4. ### Step 4: Follow it to the end
   Open the old address in a browser. It should land on the replacement's page, and that page should answer 200 with no further redirect. The redirect checker (https://wpministry.co/tools/redirect-checker/) shows each hop without a terminal.
5. ### Step 5: Move the old product to the trash
   With the redirect in place, the old product's own page can no longer be reached. Trash it, so that it leaves the shop and the sitemap.

To undo the redirect, remove the line and save.

### Or say plainly that it is gone

For a product with nothing like it, a 404 is enough, and trashing the product gives you one. Use this rule when WordPress redirects the old address to a product that is not a replacement, or when you want the answer to say the page was removed on purpose. It goes in the same place, above `# BEGIN WordPress`.

.htaccess

```
RedirectMatch gone "^/product/blue-kettle/?$"
```

Answers 410 for /product/blue-kettle/, with or without the final slash.

The address then answers 410 with Apache's own short page, not your theme's "Page not found" page. Google's documentation treats a 410 the same as a 404.

### Which to choose

| The situation | What to do | What the address answers |
| --- | --- | --- |
| Back soon | Leave the page published. Set "Stock status" to "Out of stock", or to "On backorder" if you take orders now | 200, with `OutOfStock` or `BackOrder` |
| Back at a date you do not know | Leave the page published and out of stock. Tick "Hide out of stock items from the catalog" if you do not want it in the shop meanwhile | 200, with `OutOfStock` |
| Replaced by a newer model | Redirect the old address to the new model's page, then trash the old product | 301 to the replacement, which answers 200 |
| Gone, with nothing like it | Trash the product. Check that the address answers 404, and add the 410 rule if WordPress redirects it somewhere unrelated | 404 or 410 |

## A variable product with one variation out of stock

On a variable product, each variation has its own stock status. With a Tea Tin sold in Small at 10.00 and Large at 14.00, and Small set to "Out of stock", this is what the pages say.

| Address | The offer in the structured data | `availability` |
| --- | --- | --- |
| `/product/tea-tin/` | An `AggregateOffer` from 10.00 to 14.00, counting 2 offers | `https://schema.org/InStock` |
| `/product/tea-tin/?attribute_size=Small` | One `Offer` at 10.00 | `https://schema.org/OutOfStock` |
| `/product/tea-tin/?attribute_size=Large` | One `Offer` at 14.00 | `https://schema.org/InStock` |

The product's own address says `InStock` as long as one variation can be bought, and its price range still starts at the price of the variation that is sold out. It says `OutOfStock` only when every variation is out of stock.

"Hide out of stock items from the catalog" reaches this too, late. With the box ticked, the sold-out variation's price left the range only after the variable product was saved again, and the markup then became one `Offer` at 14.00. WooCommerce's "Clear transients" tool did not bring that forward.

WooCommerce variations and SEO (https://wpministry.co/blog/woocommerce-variations-seo/) covers the addresses that name a variation and what each one tells a search engine.

## When to get help

- **Ask your host** if you cannot edit `.htaccess`, or if the server is nginx and you cannot change its configuration. A redirect plugin does the same job from the dashboard.
- **Hand it over** if a store has many discontinued products and each needs a decision. WP Ministry's WooCommerce SEO service (https://wpministry.co/services/woocommerce-seo/) is the one for a store. To start from a written list of what to fix, a WordPress SEO audit (https://wpministry.co/services/wordpress-seo-audit/) is a one-time, written audit of what stands between a WordPress or WooCommerce site and a search engine.

## Common questions

Should I delete out-of-stock products in WooCommerce?

Not if they are coming back. A product that is out of stock keeps its address, answers 200 and says `OutOfStock`, and it says `InStock` again when you restock it. Deleting it makes the address answer 404, and a product created later is a new page. Delete or trash a product only when it is gone for good.

Does WooCommerce add noindex to a product that is out of stock?

No. The robots tag on the product's page is the same before and after, and the product stays in the sitemap. Ticking "Hide out of stock items from the catalog" does not add one either. That box changes which of your own pages list the product.

Does "Hide out of stock items from the catalog" remove the product from Google?

It does nothing that asks for that. The product's own address still answers 200 and is still in the sitemap. The box takes the product out of the shop, category pages and product search on your own site. Whether Google keeps showing a page is Google's decision.

Should I redirect a discontinued product to the home page or to its category?

Not to the home page. Google's guide to site moves says a redirect to an irrelevant destination, with the home page as its example, might be treated as a soft 404. Its guidance is to redirect when a page has a clear replacement, and to answer 404 or 410 when it has none. A category that happens to hold similar products is a judgment call that Google's documentation does not settle.

What does the address of a product in the trash answer?

404, with the site's "Page not found" page, unless WordPress finds a published post whose slug begins the same way. Then it answers 301 to that post. Run the status command on this page to see which.

How long does Google take to drop a removed product?

Google gives no date. Its documentation says an address that answers 404 is removed from the index, and that Google stops using such an address over time. Search Console's help says Googlebot will probably keep trying a removed address for a while, less and less often.

## More on this subject

- WooCommerce stores: https://wpministry.co/topics/woocommerce/
- WordPress SEO: https://wpministry.co/topics/wordpress-seo/
- Cost guide WooCommerce maintenance cost: why a store costs more, and what the extra should buy: https://wpministry.co/cost/woocommerce-maintenance/
- Error fix WooCommerce order stuck on "Pending payment": how to tell paid from unpaid, and fix the cause: https://wpministry.co/errors/woocommerce-orders-stuck-pending-payment/
- Resource WooCommerce sale readiness checklist: Black Friday or any big sale: https://wpministry.co/resources/woocommerce-sale-readiness-checklist/
- Glossary term Action Scheduler: https://wpministry.co/glossary/action-scheduler/
- Error fix How to fix WooCommerce not sending order emails: https://wpministry.co/errors/woocommerce-orders-not-sending-emails/
- Error fix How to fix WooCommerce payment gateway errors: https://wpministry.co/errors/woocommerce-payment-gateway-errors/

## SEO audit, done for you

SEO audit is $249. A written audit, each finding with its source, and up to 2 hours of fixes done and tested again.

More about this work: WordPress SEO audit (https://wpministry.co/services/wordpress-seo-audit/)

May we measure how this site is used?

A yes notes the pages of this visit and loads Google Analytics. A no keeps and loads nothing. See the cookies page (https://wpministry.co/legal/cookies/).

If you say yes, we note the pages you look at during this visit and load Google Analytics. If you say no, nothing is kept and nothing is loaded. The site works the same either way. The cookies page (https://wpministry.co/legal/cookies/) has the details.

## Structured data

```json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "@id": "https://wpministry.co/#organization",
      "name": "WP Ministry",
      "url": "https://wpministry.co/",
      "logo": "https://wpministry.co/brand/logo.png",
      "address": {
        "@type": "PostalAddress",
        "streetAddress": "1309 Coffeen Ave STE 1200",
        "addressLocality": "Sheridan",
        "addressRegion": "WY",
        "postalCode": "82801",
        "addressCountry": "US"
      },
      "sameAs": [
        "https://www.linkedin.com/company/wp-ministry/",
        "https://x.com/wpministryco",
        "https://www.instagram.com/wpministryco/",
        "https://www.facebook.com/wpministryco",
        "https://www.tiktok.com/@wpministryco",
        "https://www.pinterest.com/wpministryco/",
        "https://www.youtube.com/channel/UCOZRuAukk5QSTRPG6BaHl3Q"
      ]
    },
    {
      "@type": "WebSite",
      "@id": "https://wpministry.co/#website",
      "name": "WP Ministry",
      "url": "https://wpministry.co/",
      "inLanguage": "en-US",
      "publisher": {
        "@id": "https://wpministry.co/#organization"
      }
    },
    {
      "@type": "Article",
      "@id": "https://wpministry.co/blog/woocommerce-out-of-stock-products-seo/#article",
      "headline": "WooCommerce out of stock and discontinued products and SEO: leave, hide, delete or redirect",
      "description": "An out-of-stock WooCommerce product keeps its page, which answers 200. One gone for good is redirected to a true replacement or left to answer 404.",
      "url": "https://wpministry.co/blog/woocommerce-out-of-stock-products-seo/",
      "mainEntityOfPage": "https://wpministry.co/blog/woocommerce-out-of-stock-products-seo/",
      "inLanguage": "en-US",
      "image": "https://wpministry.co/og/blog/woocommerce-out-of-stock-products-seo.png",
      "author": {
        "@id": "https://wpministry.co/#organization"
      },
      "publisher": {
        "@id": "https://wpministry.co/#organization"
      },
      "datePublished": "2026-10-08T00:00:00.000Z",
      "dateModified": "2026-10-08T00:00:00.000Z"
    },
    {
      "@type": "BreadcrumbList",
      "itemListElement": [
        {
          "@type": "ListItem",
          "position": 1,
          "name": "Home",
          "item": "https://wpministry.co/"
        },
        {
          "@type": "ListItem",
          "position": 2,
          "name": "Guides",
          "item": "https://wpministry.co/blog/"
        },
        {
          "@type": "ListItem",
          "position": 3,
          "name": "WooCommerce out of stock and discontinued products and SEO: leave, hide, delete or redirect"
        }
      ]
    }
  ]
}
```