WP Manifestindependent plugin directory
manifest / ecommerce / product-retirement

Product Retirement

Retires a product without deleting it: the page stays live and indexed, the buy button goes, the structured data says discontinued rather than out of stock, and a replacement can be offered in its place.

by George Vasiliades · github.com/poseidonas/product-retirement · website

0stars
1release downloads
0forks

Install

The author publishes release zips, so WP-CLI can install straight from GitHub:

wp plugin install https://github.com/poseidonas/product-retirement/releases/download/v1.0.0/product-retirement.zip

Declares an update source (https://github.com/Poseidonas/product-retirement), so updates arrive through the plugin's own updater.

Readme

Product Retirement

Latest release WordPress 6.7+ WooCommerce 9.0+ PHP 8.0+ License GPL-2.0-or-later

Retires a product without deleting it. The page stays live, keeps its address and keeps its place in your sitemap, so the search rankings that page has earned are not thrown away. What changes is that it cannot be bought, it says so plainly, and search engines are told it is discontinued rather than temporarily out of stock.

  • Author: George Vasiliades - https://github.com/Poseidonas
  • License: GPL-2.0-or-later
  • Requires WordPress 6.7 or newer
  • Requires PHP 8.0 or newer
  • Requires WooCommerce 9.0 or newer, tested up to 11.0
  • Compatible with High-Performance Order Storage and with the cart and checkout blocks
  • Settings live in WooCommerce > Retired Products

What was measured before writing this

Measured on WooCommerce 11.0.1. The core offers three ways to take a product off sale, and none of them does this job:

Option What it gets right What it gets wrong
outofstock Keeps the page, hides the purchase form The structured data says OutOfStock, which tells search engines the product is coming back. And is_purchasable() stays true
catalog_visibility = hidden is_visible() becomes false is_purchasable() stays true, so the product can still be bought straight from its address
draft or trash Removes it everywhere The page, the backlinks and the ranking go with it

The measurable gap is in the structured data. Schema.org defines https://schema.org/Discontinued, and WooCommerce never emits it — only InStock and OutOfStock. There is a filter, woocommerce_structured_data_product_offer, so it can be put right.

Verified: a product marked here reports

"availability": "https://schema.org/Discontinued"

with priceValidUntil removed, because a price that is no longer offered should not carry a validity date. Its post_status stays publish, so it remains in the sitemap, and its page still answers 200.

What happens to a retired product

Behaviour Default Why
Structured data says discontinued on The honest answer, and the one that stops it being offered as buyable
Cannot be added to the cart always Through woocommerce_is_purchasable, so it holds on the classic path and on the blocks
Left out of shop and category pages on The page itself stays reachable and indexed either way
Left out of your site's search off Somebody searching for it by name usually wants to find out what happened to it
Never suggested as a related product on
Successor shown on the page on
Permanent redirect to the successor off See below

Why the redirect is off by default

A 301 passes the ranking to the successor, and that is sometimes right. But the old page stops existing, so the reviews, the questions and the record of what the product was are gone, and a customer who searched for the old name lands somewhere that never explains what happened.

Keeping the page and stating plainly that the product is discontinued, with a link to what replaced it, usually serves both the customer and the search engine better. The redirect is there for the case where the successor really is the same thing under a new name.

Marking products

On a single product, the Inventory panel gains a Discontinued checkbox and a "Replaced by" product search. From the products list, two bulk actions mark or unmark several at once, and a Retirement column shows which are retired and what replaced them.

The date a product was retired is recorded the first time it is marked, and cleared when it goes back on sale.

The list

WooCommerce > Retired Products holds the settings and a table of every retired product, when it was marked, what replaced it, and a link to its live page.

Honest limits

  • This does not delete anything and does not touch orders. Past orders containing a retired product are unaffected.
  • The successor is shown only if it is published and not itself retired. A retired successor is simply not shown, rather than sending the customer to another dead end.
  • Leaving a product out of the catalogue is done through the product query, so a theme or plugin that builds its own product list with raw SQL will not be affected.
  • The plugin does not write to your sitemap. It keeps the product published, which is what keeps it in whatever sitemap your site uses, whether that is the WordPress one or an SEO plugin's.
  • Search engines decide for themselves how quickly to act on a discontinued marking. The plugin states the fact correctly; it cannot set the timetable.

Filters

add_filter( 'icxcnika_ret_is_retired', function ( bool $retired, int $product_id ): bool {
    return $retired;
}, 10, 2 );

add_filter( 'icxcnika_ret_settings', function ( array $settings ): array {
    return $settings;
} );

icxcnika_ret_is_retired receives whether a product counts as retired and is the last word before any behaviour applies. icxcnika_ret_registry_payload receives the data sent to the installation registry.

Data stored

  • Option icxcnika_ret_settings (the settings).
  • Post meta on products: _icxcnika_ret_retired, _icxcnika_ret_replacement and _icxcnika_ret_date.
  • Option icxcnika_ret_registry_key (random installation key of 48 characters, created only if installation reporting is active).
  • Transient icxcnika_ret_release (cached GitHub release lookup, 12 hours).
  • Cron event icxcnika_ret_registry_ping (weekly, only if installation reporting is active).

Installation reporting

On activation, on deactivation and once a week the plugin sends a small JSON message to the author's installation registry: plugin slug, plugin version, home URL, site URL, WordPress version, WooCommerce version, PHP version, locale and whether the site is a multisite. Each report carries a random installation key generated locally on first use. No product, customer or order data is ever sent.

The reporting address is empty by default, which means nothing is sent at all. Add define( 'ICXCNIKA_REGISTRY_DISABLE', true ); to wp-config.php to turn the reporting off, or define( 'ICXCNIKA_REGISTRY_URL', '...' ); to point it elsewhere.

Updates

Updates are delivered from GitHub Releases through the Update URI header of WordPress. The Plugins screen shows View details and allows automatic updates to be enabled, exactly as for a plugin from the directory.

Uninstall

Deleting the plugin removes the option, every value it wrote on products, the installation key, the cached release check and the scheduled report. Every product returns to being purchasable as WooCommerce would have it.


Product Retirement (Ελληνικά)

Αποσύρει ένα προϊόν χωρίς να το διαγράψει. Η σελίδα μένει ζωντανή, κρατά τη διεύθυνσή της και τη θέση της στο sitemap, ώστε να μην πεταχτεί η κατάταξη που έχει κερδίσει. Αυτό που αλλάζει είναι ότι δεν μπορεί να αγοραστεί, το δηλώνει καθαρά, και οι μηχανές αναζήτησης μαθαίνουν ότι καταργήθηκε αντί για προσωρινά εξαντλημένο.

  • Δημιουργός: George Vasiliades - https://github.com/Poseidonas
  • Άδεια: GPL-2.0-or-later
  • Απαιτεί WordPress 6.7 ή νεότερο
  • Απαιτεί PHP 8.0 ή νεότερη
  • Απαιτεί WooCommerce 9.0 ή νεότερο, δοκιμασμένο έως 11.0
  • Συμβατό με το High-Performance Order Storage και με τα μπλοκ καλαθιού και ταμείου
  • Οι ρυθμίσεις βρίσκονται στο WooCommerce > Καταργημένα προϊόντα

Τι μετρήθηκε πριν γραφτεί

Μετρήθηκε σε WooCommerce 11.0.1. Ο πυρήνας δίνει τρεις τρόπους να βγει ένα προϊόν από την πώληση, και κανένας δεν κάνει αυτή τη δουλειά:

Επιλογή Τι πετυχαίνει Τι χαλάει
outofstock Κρατά τη σελίδα, κρύβει τη φόρμα αγοράς Τα structured data λένε OutOfStock, δηλαδή για τις μηχανές αναζήτησης το προϊόν θα επιστρέψει. Και το is_purchasable() μένει true
catalog_visibility = hidden Το is_visible() γίνεται false Το is_purchasable() μένει true, οπότε το προϊόν αγοράζεται κατευθείαν από τη διεύθυνσή του
πρόχειρο ή κάδος Το αφαιρεί από παντού Μαζί του φεύγουν η σελίδα, οι σύνδεσμοι προς αυτήν και η κατάταξη

Το μετρήσιμο κενό είναι στα structured data. Το schema.org ορίζει το https://schema.org/Discontinued, και το WooCommerce δεν το βγάζει ποτέ — μόνο InStock και OutOfStock. Υπάρχει όμως το φίλτρο woocommerce_structured_data_product_offer, οπότε διορθώνεται σωστά.

Επαληθεύτηκε: ένα προϊόν σημειωμένο εδώ αναφέρει

"availability": "https://schema.org/Discontinued"

με το priceValidUntil αφαιρεμένο, γιατί μια τιμή που δεν προσφέρεται πια δεν πρέπει να φέρει ημερομηνία ισχύος. Το post_status του μένει publish, οπότε παραμένει στο sitemap, και η σελίδα του απαντά ακόμα 200.

Τι γίνεται με ένα καταργημένο προϊόν

Συμπεριφορά Προεπιλογή Γιατί
Τα structured data λένε ότι καταργήθηκε ενεργό Η τίμια απάντηση, και αυτή που σταματά να προσφέρεται ως αγοράσιμο
Δεν μπαίνει στο καλάθι πάντα Μέσω woocommerce_is_purchasable, οπότε ισχύει στην κλασική διαδρομή και στα μπλοκ
Εκτός σελίδων καταστήματος και κατηγοριών ενεργό Η ίδια η σελίδα παραμένει προσβάσιμη και ευρετηριασμένη έτσι κι αλλιώς
Εκτός αναζήτησης του ιστότοπου ανενεργό Όποιος το αναζητά με το όνομά του συνήθως θέλει να μάθει τι απέγινε
Ποτέ ως σχετικό προϊόν ενεργό
Διάδοχος στη σελίδα ενεργό
Μόνιμη ανακατεύθυνση στον διάδοχο ανενεργό Δείτε παρακάτω

Γιατί η ανακατεύθυνση είναι ανενεργή από την αρχή

Μια 301 περνά την κατάταξη στον διάδοχο, και κάποιες φορές αυτό είναι το σωστό. Όμως η παλιά σελίδα παύει να υπάρχει, οπότε χάνονται οι κριτικές, οι ερωτήσεις και η καταγραφή του τι ήταν το προϊόν, και ο πελάτης που αναζήτησε το παλιό όνομα προσγειώνεται κάπου που δεν του εξηγεί ποτέ τι έγινε.

Το να κρατήσετε τη σελίδα και να δηλώσετε καθαρά ότι το προϊόν καταργήθηκε, με σύνδεσμο σε αυτό που το αντικατέστησε, συνήθως εξυπηρετεί καλύτερα και τον πελάτη και τη μηχανή αναζήτησης. Η ανακατεύθυνση υπάρχει για την περίπτωση που ο διάδοχος είναι πραγματικά το ίδιο πράγμα με νέο όνομα.

Σήμανση προϊόντων

Σε ένα προϊόν, ο πίνακας Αποθήκη αποκτά ένα κουτάκι «Καταργήθηκε» και μια αναζήτηση προϊόντος «Αντικαθίσταται από». Από τη λίστα προϊόντων, δύο μαζικές ενέργειες σημειώνουν ή αναιρούν πολλά μαζί, και μια στήλη Κατάργηση δείχνει ποια είναι καταργημένα και τι τα αντικατέστησε.

Η ημερομηνία κατάργησης καταγράφεται την πρώτη φορά που σημειώνεται, και καθαρίζεται όταν το προϊόν επιστρέψει σε πώληση.

Ο πίνακας

Στο WooCommerce > Καταργημένα προϊόντα βρίσκονται οι ρυθμίσεις και ένας πίνακας με κάθε καταργημένο προϊόν, πότε σημειώθηκε, τι το αντικατέστησε, και σύνδεσμο στη ζωντανή σελίδα του.

Τίμιοι περιορισμοί

  • Δεν διαγράφει τίποτα και δεν αγγίζει παραγγελίες. Οι παλιές παραγγελίες με καταργημένο προϊόν δεν επηρεάζονται.
  • Ο διάδοχος εμφανίζεται μόνο αν είναι δημοσιευμένος και δεν είναι ο ίδιος καταργημένος. Ένας καταργημένος διάδοχος απλώς δεν εμφανίζεται, αντί να στείλει τον πελάτη σε άλλο αδιέξοδο.
  • Η απόκρυψη από τον κατάλογο γίνεται μέσω του ερωτήματος προϊόντων, οπότε ένα θέμα ή πρόσθετο που φτιάχνει δική του λίστα με σκέτη SQL δεν επηρεάζεται.
  • Το πρόσθετο δεν γράφει στο sitemap σας. Κρατά το προϊόν δημοσιευμένο, και αυτό είναι που το κρατά σε όποιο sitemap χρησιμοποιεί ο ιστότοπός σας, είτε του WordPress είτε ενός πρόσθετου SEO.
  • Οι μηχανές αναζήτησης αποφασίζουν μόνες τους πόσο γρήγορα θα ενεργήσουν. Το πρόσθετο δηλώνει σωστά το γεγονός· δεν μπορεί να ορίσει το χρονοδιάγραμμα.

Φίλτρα

add_filter( 'icxcnika_ret_is_retired', function ( bool $retired, int $product_id ): bool {
    return $retired;
}, 10, 2 );

add_filter( 'icxcnika_ret_settings', function ( array $settings ): array {
    return $settings;
} );

Το icxcnika_ret_is_retired δέχεται το αν ένα προϊόν θεωρείται αποσυρμένο και έχει τον τελευταίο λόγο πριν εφαρμοστεί οποιαδήποτε συμπεριφορά. Το icxcnika_ret_registry_payload δέχεται τα δεδομένα που στέλνονται στο μητρώο εγκαταστάσεων.

Δεδομένα που αποθηκεύονται

  • Option icxcnika_ret_settings (οι ρυθμίσεις).
  • Post meta στα προϊόντα: _icxcnika_ret_retired, _icxcnika_ret_replacement και _icxcnika_ret_date.
  • Option icxcnika_ret_registry_key (τυχαίο κλειδί εγκατάστασης 48 χαρακτήρων, δημιουργείται μόνο αν είναι ενεργή η αναφορά εγκατάστασης).
  • Transient icxcnika_ret_release (cache της αναζήτησης έκδοσης στο GitHub, 12 ώρες).
  • Cron event icxcnika_ret_registry_ping (εβδομαδιαίο, μόνο αν είναι ενεργή η αναφορά εγκατάστασης).

Read the full README on GitHub →

Releases

TagPublishedAssetDownloads
v1.0.0 Aug 19, 2026 product-retirement.zip 1