{"id":376584,"date":"2026-09-30T08:24:49","date_gmt":"2026-09-30T08:24:49","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/product-expiry-dates-for-woocommerce\/"},"modified":"2026-09-30T08:24:27","modified_gmt":"2026-09-30T08:24:27","slug":"plugincity-product-expiry-dates","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/plugincity-product-expiry-dates\/","author":23565792,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.0","stable_tag":"1.0.0","tested":"7.1.2","requires":"6.7","requires_php":"8.1","requires_plugins":null,"header_name":"PluginCity Product Expiry Dates for WooCommerce","header_author":"PluginCity","header_description":"Give a product a date it can no longer be sold after. It comes off sale when that date passes, and a basket still holding it cannot be checked out.","assets_banners_color":"1167d7","last_updated":"2026-09-30 08:24:27","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/www.plugincity.net\/plugins\/product-expiry-dates-for-woocommerce","header_author_uri":"https:\/\/www.plugincity.net","rating":0,"author_block_rating":0,"active_installs":0,"downloads":30,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"plugincitywp","date":"2026-09-30 08:24:27","revision":3720678}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3720678,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3720678,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3720678,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3720678,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3720678,"resolution":"1","location":"assets","locale":"","width":852,"height":431},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3720678,"resolution":"2","location":"assets","locale":"","width":1692,"height":811},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3720678,"resolution":"3","location":"assets","locale":"","width":1208,"height":583},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3720678,"resolution":"4","location":"assets","locale":"","width":1208,"height":679},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3720678,"resolution":"5","location":"assets","locale":"","width":1208,"height":1121},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3720678,"resolution":"6","location":"assets","locale":"","width":1006,"height":647}},"screenshots":{"1":"The Expiry tab on a product. Type the date it can no longer be sold after, and the time of day if the date alone is not close enough.","2":"The Expires column on your products list. Every date in the shop on one screen, with whatever has already stopped selling marked.","3":"A product whose date has passed. The Add to basket button is gone and your own sentence stands where it was.","4":"A basket holding something that has since gone off. The product is named at the top, the shop's own message sits with the totals, and the order will not go through until it comes out.","5":"The same basket at the checkout. A customer who comes straight to this page is refused here too, so an expired product cannot be paid for by skipping the basket.","6":"The two sentences a customer reads are yours to write, and %s is where the products get named."}},"plugin_section":[],"plugin_tags":[270232,1946,56513,243341,286],"plugin_category":[45],"plugin_contributors":[282135],"plugin_business_model":[],"class_list":["post-376584","plugin","type-plugin","status-publish","hentry","plugin_tags-best-before","plugin_tags-expiration","plugin_tags-expiry-date","plugin_tags-perishable","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_contributors-plugincitywp","plugin_committers-plugincitywp"],"banners":{"banner":"https:\/\/ps.w.org\/plugincity-product-expiry-dates\/assets\/banner-772x250.png?rev=3720678","banner_2x":"https:\/\/ps.w.org\/plugincity-product-expiry-dates\/assets\/banner-1544x500.png?rev=3720678","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/plugincity-product-expiry-dates\/assets\/icon-128x128.png?rev=3720678","icon_2x":"https:\/\/ps.w.org\/plugincity-product-expiry-dates\/assets\/icon-256x256.png?rev=3720678","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/plugincity-product-expiry-dates\/assets\/screenshot-1.png?rev=3720678","caption":"The Expiry tab on a product. Type the date it can no longer be sold after, and the time of day if the date alone is not close enough."},{"src":"https:\/\/ps.w.org\/plugincity-product-expiry-dates\/assets\/screenshot-2.png?rev=3720678","caption":"The Expires column on your products list. Every date in the shop on one screen, with whatever has already stopped selling marked."},{"src":"https:\/\/ps.w.org\/plugincity-product-expiry-dates\/assets\/screenshot-3.png?rev=3720678","caption":"A product whose date has passed. The Add to basket button is gone and your own sentence stands where it was."},{"src":"https:\/\/ps.w.org\/plugincity-product-expiry-dates\/assets\/screenshot-4.png?rev=3720678","caption":"A basket holding something that has since gone off. The product is named at the top, the shop's own message sits with the totals, and the order will not go through until it comes out."},{"src":"https:\/\/ps.w.org\/plugincity-product-expiry-dates\/assets\/screenshot-5.png?rev=3720678","caption":"The same basket at the checkout. A customer who comes straight to this page is refused here too, so an expired product cannot be paid for by skipping the basket."},{"src":"https:\/\/ps.w.org\/plugincity-product-expiry-dates\/assets\/screenshot-6.png?rev=3720678","caption":"The two sentences a customer reads are yours to write, and %s is where the products get named."}],"raw_content":"<!--section=description-->\n<p>Some things should not be sold after a certain date: food has a best-before date, a licence or a warranty covers a fixed period, and an event ticket is worthless the morning after.<\/p>\n\n<p>WooCommerce has no way to say so. PluginCity Product Expiry Dates adds an <strong>Expiry<\/strong> tab to every product, with one box on it: the date it can no longer be sold after. When that moment passes the product comes off sale on its own, without anybody having to remember.<\/p>\n\n<p>The date is enforced in both places it has to be: a product past its date cannot be added to a basket, and a basket that already held one cannot be checked out \u2014 a basket easily outlives the date it was filled before. The customer is told which product to take out, by name.<\/p>\n\n<h4>What you get<\/h4>\n\n<ul>\n<li>One expiry date per product, on an Expiry tab just below Inventory<\/li>\n<li>An Expires column on the products list, showing what has stopped selling<\/li>\n<li>The product taken off sale once the date passes, with a sentence on the page saying why<\/li>\n<li>Baskets that outlived the date refused at the checkout, naming the product to remove<\/li>\n<li>Notices on the cart, checkout and mini-cart, in the classic checkout and the blocks<\/li>\n<li>PayPal express buttons refused too, so a one-tap order cannot get past the date<\/li>\n<li>A shortcode, <code>[pexp_message]<\/code>, to put the message anywhere<\/li>\n<li>Settings import and export, to copy a configuration to another shop or keep a backup<\/li>\n<li>High-Performance Order Storage compatibility<\/li>\n<\/ul>\n\n<p>The free version is permanent. It does not expire, needs no licence key, and never contacts PluginCity.<\/p>\n\n<h4>Pro<\/h4>\n\n<p>Not every product goes off all at once, and not everyone who buys from you is a retail customer. <a href=\"https:\/\/www.plugincity.net\/plugins\/product-expiry-dates-for-woocommerce\">Pro<\/a> is for shops that need the exceptions: trade accounts that may still buy cleared stock, a shelf life that dates products for you, dates per variation and in bulk, a warning before a date passes, and an automatic markdown as it approaches.<\/p>\n\n<p>Pro is a separate paid version, sold and distributed by PluginCity. It is not included in this plugin and is not downloaded or installed by it, and nothing described above depends on it. Your dates and settings carry over if you buy it.<\/p>\n\n<h3>Configuration<\/h3>\n\n<ol>\n<li>Turn expiry dates on.<\/li>\n<li>Edit a product, open its <strong>Expiry<\/strong> tab below Inventory, and type the date it can no longer be sold after.<\/li>\n<li>Write the message customers see, and choose whether it appears on the cart, at checkout, or both.<\/li>\n<\/ol>\n\n<!--section=installation-->\n<p>WooCommerce must be installed and active first.<\/p>\n\n<ol>\n<li>In WordPress, go to <strong>Plugins \u2192 Add New<\/strong>.<\/li>\n<li>Search for <strong>PluginCity Product Expiry Dates for WooCommerce<\/strong>.<\/li>\n<li>Click <strong>Install Now<\/strong>, then <strong>Activate<\/strong>.<\/li>\n<li>Go to <strong>WooCommerce \u2192 Product Expiry<\/strong>, or click <strong>Settings<\/strong> on the Plugins screen.<\/li>\n<\/ol>\n\n<p>From a downloaded ZIP instead: <strong>Plugins \u2192 Add New \u2192 Upload Plugin<\/strong>, choose the file and click <strong>Install Now<\/strong>. There is no need to unzip it.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"what%20happens%20when%20a%20date%20passes%3F\"><h3>What happens when a date passes?<\/h3><\/dt>\n<dd><p>The product comes off sale: the buy button goes and the page says it is no longer available, in your words. Anybody holding it in a basket is asked to remove it before ordering. Orders already placed are untouched.<\/p><\/dd>\n<dt id=\"my%20theme%20still%20shows%20an%20add%20to%20cart%20button.%20what%20now%3F\"><h3>My theme still shows an Add to cart button. What now?<\/h3><\/dt>\n<dd><p>Nothing can be bought through it: the date is checked again when anything is added to a basket, rather than trusted from the page. The button belongs to your theme, and a buy form drawn in place of WooCommerce's own is hidden too, so in practice it goes. If yours is still there, tell us the theme and we will look at it.<\/p><\/dd>\n<dt id=\"why%20is%20the%20expired%20product%20still%20sitting%20in%20the%20customer%27s%20basket%3F\"><h3>Why is the expired product still sitting in the customer's basket?<\/h3><\/dt>\n<dd><p>Because being told what to do about it is more use than finding it gone. WooCommerce would take it straight out and say only that it can no longer be purchased, which reads as a fault in your shop. This plugin leaves the row in place, explains it in your words, and refuses the order until the customer removes it.<\/p><\/dd>\n<dt id=\"is%20an%20expired%20product%20hidden%2C%20or%20marked%20out%20of%20stock%3F\"><h3>Is an expired product hidden, or marked out of stock?<\/h3><\/dt>\n<dd><p>Neither. It stays listed, so a customer who followed a link lands on a page that explains itself rather than a 404, and nothing can be bought from it. It is not marked out of stock either: stock is how many you have, and writing it down as nil would tell your reports, feeds and back-in-stock emails something untrue.<\/p><\/dd>\n<dt id=\"can%20i%20set%20a%20time%20as%20well%20as%20a%20date%3F\"><h3>Can I set a time as well as a date?<\/h3><\/dt>\n<dd><p>Yes. Leave the time empty and the product sells to the end of the day you typed, which is how a best-before date reads. Fill it in and it stops at that minute, for an event or a deadline.<\/p><\/dd>\n<dt id=\"what%20time%20zone%20are%20the%20dates%20in%3F\"><h3>What time zone are the dates in?<\/h3><\/dt>\n<dd><p>Yours, the one set in <strong>Settings \u2192 General<\/strong>. A date you have typed stays the moment you meant even if you later move your shop's time zone.<\/p><\/dd>\n<dt id=\"can%20an%20expired%20product%20be%20hidden%20or%20unpublished%20instead%20of%20just%20unbuyable%3F\"><h3>Can an expired product be hidden or unpublished instead of just unbuyable?<\/h3><\/dt>\n<dd><p>Not in the free version, which leaves it in the shop and refuses the sale. Pro can hide it from your listings or move it to draft instead. The <a href=\"https:\/\/www.plugincity.net\/plugins\/product-expiry-dates-for-woocommerce\">PluginCity product page<\/a> lists the Pro features in full.<\/p><\/dd>\n<dt id=\"can%20different%20types%20of%20product%20have%20different%20shelf%20lives%3F\"><h3>Can different types of product have different shelf lives?<\/h3><\/dt>\n<dd><p>Not in the free version. Pro dates products for you from one figure for the shop, or a different number of days for each category \u2014 days for salad, years for tins.<\/p><\/dd>\n<dt id=\"can%20i%20discount%20something%20automatically%20as%20its%20date%20gets%20closer%3F\"><h3>Can I discount something automatically as its date gets closer?<\/h3><\/dt>\n<dd><p>Not in the free version, which leaves your prices alone. Pro can take a percentage off as the date approaches \u2014 20% in the last week, 50% in the last two days \u2014 so stock clears instead of being thrown away. Nothing is written onto the product, so extending a date puts the full price back.<\/p><\/dd>\n<dt id=\"can%20i%20be%20warned%20before%20a%20date%20passes%2C%20rather%20than%20finding%20out%20afterwards%3F\"><h3>Can I be warned before a date passes, rather than finding out afterwards?<\/h3><\/dt>\n<dd><p>Not in the free version, which says nothing beforehand. Pro adds a dashboard panel listing what stops selling in the next few days, and can email you the same list each morning.<\/p><\/dd>\n<dt id=\"can%20i%20set%20dates%20on%20a%20lot%20of%20products%20at%20once%3F\"><h3>Can I set dates on a lot of products at once?<\/h3><\/dt>\n<dd><p>Not in the free version, which gives you one date box per product. Pro adds Quick Edit, Bulk Edit and expiry dates in WooCommerce's own product CSV export and import. See the <a href=\"https:\/\/www.plugincity.net\/plugins\/product-expiry-dates-for-woocommerce\">PluginCity product page<\/a> for full details.<\/p><\/dd>\n<dt id=\"do%20variations%20have%20their%20own%20dates%3F\"><h3>Do variations have their own dates?<\/h3><\/dt>\n<dd><p>Not in the free version, where every variation is held to the product's one date. Pro dates each variation separately, and tells a customer who picks one whose date has passed.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20the%20block%20cart%20and%20checkout%3F\"><h3>Does it work with the block cart and checkout?<\/h3><\/dt>\n<dd><p>Yes. A basket holding something past its date is reported through WooCommerce's Store API, so the block cart and checkout refuse to proceed and show the same message.<\/p><\/dd>\n<dt id=\"can%20i%20change%20the%20wording%3F\"><h3>Can I change the wording?<\/h3><\/dt>\n<dd><p>Yes, both sentences: the one on the basket and the one on the product. Bold, italics and links are allowed; anything else is stripped before it reaches the storefront.<\/p><\/dd>\n<dt id=\"can%20i%20change%20how%20the%20message%20looks%3F\"><h3>Can I change how the message looks?<\/h3><\/dt>\n<dd><p>The free version draws it one way: a panel with a coloured band and a small clock, taking its type and size from your theme, and it can be restyled with your own CSS. Pro gives you the controls instead \u2014 colour, box, mark, weight, size and alignment \u2014 with a preview as you choose.<\/p><\/dd>\n<dt id=\"can%20i%20show%20the%20basket%20message%20somewhere%20else%20on%20my%20site%3F\"><h3>Can I show the basket message somewhere else on my site?<\/h3><\/dt>\n<dd><p>Yes. The shortcode <code>[pexp_message]<\/code> prints the same sentence wherever you put it, and shows nothing while the basket is fine.<\/p><\/dd>\n<dt id=\"can%20a%20customer%20get%20past%20it%20with%20a%20one-tap%20payment%20button%3F\"><h3>Can a customer get past it with a one-tap payment button?<\/h3><\/dt>\n<dd><p>No. The buttons stay on the cart, so a customer can read why the order is not going through, but the order itself is refused while the basket holds something past its date. A PayPal express button is stopped the moment it is pressed, before the customer is sent out to PayPal, and any other flow that builds its order through WooCommerce's checkout is refused there too.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20high-performance%20order%20storage%3F\"><h3>Does it work with High-Performance Order Storage?<\/h3><\/dt>\n<dd><p>Yes. Nothing is written to orders, so HPOS shops are fully supported.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20i%20deactivate%20woocommerce%3F\"><h3>What happens if I deactivate WooCommerce?<\/h3><\/dt>\n<dd><p>The plugin steps aside and shows a notice. It does not fatally error, and your dates and settings are waiting when WooCommerce comes back.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>First public release.<\/li>\n<\/ul>","raw_excerpt":"Give a product a date it can no longer be sold after. It comes off sale when that date passes, and a basket still holding it cannot be checked out.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/376584","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=376584"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/plugincitywp"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=376584"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=376584"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=376584"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=376584"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=376584"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=376584"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}