No Add to cart button in WooCommerce? Check the price
A product with no price has no Add to cart button. One priced at 0.00 has one, and it works. Either can be an accident — or a deliberate gift or voucher.
The symptom
Two different states that come from the same field — usually by accident, sometimes on purpose.
No price at all. The product page loads, the photo is there, the description is there, and
where the price and the Add to cart button should be there is nothing. WooCommerce hides the button
when _price is empty — silently, because from its point of view a product without a price is not
purchasable and that is a valid state.
Priced at zero. The button is there, it works, and the order comes through for 0.00. Usually after an import where a currency column was empty, or a bulk edit that touched the wrong field.
The price is there and the button still is not? Then it is not this check. In the shop list an out-of-stock product gets Read more instead of Add to cart; a variable product gets Select options, and a variation with no price has its own check, A6. A catalogue-mode or request-a-quote plugin, or the theme itself, can also remove the button.
What it costs
The no-price case costs you every visit the product receives. It ranks, it sits in categories, it goes into feeds — and it converts at exactly zero, because there is no way to buy it. It is the purest form of wasted traffic in a catalogue.
The zero-price case is worse, because it succeeds. Goods ship, shipping is paid, packaging is used, and the order total is nothing. On a store with free shipping thresholds it can also drag other items along with it.
Both usually arrive in batches. A single hand-created product missing a price is rare; two hundred of them means an import mapped the wrong column, and the fix belongs in the import, not in the products.
How to check it yourself
Published, with no price:
wp db query "SELECT p.ID, p.post_title
FROM wp_posts p
LEFT JOIN wp_postmeta pr ON pr.post_id = p.ID AND pr.meta_key = '_price'
WHERE p.post_type = 'product' AND p.post_status = 'publish'
AND (pr.meta_value IS NULL OR pr.meta_value = '')"
Published and priced at zero:
wp db query "SELECT p.ID, p.post_title
FROM wp_posts p
JOIN wp_postmeta pr ON pr.post_id = p.ID AND pr.meta_key = '_price'
WHERE p.post_type = 'product' AND p.post_status = 'publish'
AND pr.meta_value + 0 = 0 AND pr.meta_value <> ''"
One trap worth knowing: for a variable product, _price holds the lowest price among its
variations. A variable parent with an empty _price usually means none of its variations has a
price either, which is a different and larger problem than a simple product with a blank field.
How to fix it
- Check whether it is deliberate. A free gift added to orders, a voucher, a donation, “price on request” — then there is nothing to fix. Hide the finding; it stays hidden.
- Find the batch, not the product. Sort the results by date created. If they cluster, you are looking at one import run, and the mapping is what needs fixing.
- Set prices, or if a product genuinely has no price yet, take it out of the catalogue while it waits — draft, or hidden from the catalogue. Published-and-unbuyable is the one state that helps nobody.
- For zero-priced products that sold, check the orders before changing anything. You may want to know who received what.
- For “price on request” catalogues, use a plugin built for it rather than an empty price field. An empty field renders as silence; a proper enquiry form renders as a next step.
When it is a false positive
- Free products by design — a gift added to orders above a threshold, samples, free downloads, a lead magnet, a donation with a custom amount. Zero is the correct price. Hide the finding; it stays hidden. The data cannot tell a gift from a mistake — a gift that ships with every order and a product zeroed by an import look exactly the same — so this decision stays with you.
- Gift cards and products out of stock — from version 0.3.5 Merchlint skips them. On a gift card the customer chooses the amount, and a product with no stock has usually been withdrawn.
- B2B catalogues with prices behind login. The price exists, it is just not stored in
_pricefor logged-out visitors. If you run role-based pricing, this check is not measuring the right field. - Products still being written, kept published because someone finds it convenient. Legitimate choice, but it is worth being deliberate about it.
How Merchlint finds it
Merchlint reads the price through WooCommerce — not from the lookup table, which a failed import can skip — together with the product’s status, stock status and type, and reports a published product whose price is empty or zero. From version 0.3.5 it skips products that are out of stock and gift cards, and the evidence names the state: no price (it cannot be added to the cart) or price 0 (anyone can order it for free). They are named apart because the fix is different and the urgency is different.
Confidence: F — fact from the database. A stored field is empty, or it is zero. No threshold, no interpretation. Whether a zero is a mistake or a gift is the one thing the data does not say.
The finding shows the value read, the product type and its publication status.
Disagrees with what you see in your store? Write to us — we read every message. contact@merchlint.com