What it is
There’s one for your whole store. It’s virtual, so there’s nothing to ship by itself. It’s hidden from the catalogue, so it isn’t in shop pages or category listings, and it’s excluded from search and from your sitemap. It’s priced at zero, because every line that uses it overrides the price anyway. Customers never see it as a product. They see the cart line, which carries the custom item’s own name, price, description and image. It can’t be bought on its own. An?add-to-cart= link or a Store API request for it is refused with This item can only be bought as part of a preset., and so is a checkout if a bare carrier line reaches a cart some other way.
Setting one up
Under Settings → Carrier product. With no carrier linked, the card shows an empty slot, No carrier product yet, with two buttons:- Create carrier product makes one with the right flags set.
- Choose a product opens a picker, if you’d rather use a product you already have.
- Change opens the same picker to point at another product.
- Unlink detaches it without deleting the product. The slot comes back, and custom items can’t reach a cart until you create or choose a carrier again.
The picker
Choose a carrier product lists your published, virtual simple products, newest first. Search by name or ID. Each row shows the product’s ID and flags, and a product that’s visible in the shop is marked with a warning, because a carrier should be hidden. Pick one and press Use this product. Only a published, simple, virtual product can be a carrier. The picker offers nothing else, and saving refuses anything else too, with Only a published, simple, virtual product can carry custom preset items. So products that need shipping, drafts and other product types can’t be chosen.On the free version this card is locked, with a Pro tag, because free never adds a custom item. A carrier linked on Pro stays in place, so presets made with Pro keep working. The card stays visible so the Settings screen doesn’t change shape between tiers.
Several custom items at once
Two custom items in one cart are two lines on the same carrier product, priced and named independently. That works because each line gets its own copy of the product object before anything changes on it. WooCommerce can hand back the same object across calls, and editing a shared one would give both lines whichever name was written last.Shipping
A custom item that ships carries its own weight, dimensions and shipping class, set on the item. Those values are also stamped onto the order line at checkout, under_cartpresets_custom_* meta keys. Reading the order line back re-fetches the real carrier product, which is generic, virtual and weightless. The copy that carried the actual weight existed for one cart calculation and was never saved.
Without that snapshot, a packing-slip or shipping-label plugin reading a custom preset item gets nothing it can use. See Order line item meta.
If you delete it
Presets keep their custom items. Following one of those links refuses the custom line: skipped or blocking, depending on Settings → Cart behaviour → Unavailable items (Skip the item, or Refuse the preset). Each preset with a custom item shows a Health checks warning, “Custom items need a carrier product”, which links straight to this card. Re-link a carrier product and everything works again. Nothing is lost.Uninstalling
The carrier product isn’t deleted when you delete the plugin, unless you tick The carrier product under Settings → Data management → Delete on uninstall. Even then it’s only removed if it’s still virtual and hidden. If you pointed the carrier at one of your own products and made it visible, it’s left alone. Think twice before ticking it: past orders with custom items reference the carrier, and deleting it orphans those lines.For developers
cartpresets_carrier_product_id filters which product is used, and so which product can’t be bought on its own. cartpresets_carrier_product_created fires both when the plugin creates one and when you point it at an existing product. So a listener learns which product is the carrier, but not whether it was made from scratch.
cartpresets_custom_item_shipping_data filters the shipping values a custom item contributes, and is safety-clamped. See the hooks reference.