Google says Search Console AI reports are now worldwide, and John Mueller weighs in on recovery timing, markdown for AI crawlers, and sitemap cache-busting.
This release is now available for download. Review the highlights below, follow the update guide, and check the full changelog before updating production sites.
WooCommerce 11.1 is here! This release includes a number of performance improvements for variable products and block registration, more accurate refund details in API endpoints, improvements to product CSV imports, and experimental support for videos in product galleries. Here’s a few more highlights:
Introducing variation image galleries
Variation galleries are now enabled for all stores in WooCommerce 11.1 and WooCommerce Additional Variation Images is being retired. That means you no longer need a separate extension to add image galleries to your product variations — it’s a native WooCommerce feature available to every store, for free. There’s nothing to switch on: the experimental toggle is now gone from the Features screen, and a database update (11.1.0-1) enables the feature even on stores that had previously opted out. (#67884)
Right of order withdrawal for EU customers
Disabled by default, stores that need to conform to EU guidelines can enable the order withdrawal form for their customers. This feature creates a new screen in the My Account page for users to submit an order withdrawal request. The request is logged and the merchant is notified via email and the dashboard. Because each store is unique and the process may differ, withdrawing and potentially refunding an order remains a manual process.
Cleaner admin orders for virtual products
Orders that don’t need fulfillment no longer show a shipping address in the admin order summary. Store API checkout retains billing-derived shipping data for compatibility, so virtual-only orders were displaying an address that meant nothing; that read-only address and its implicit phone fallback are now hidden. Physical, mixed, and unresolved orders keep their details. (#66488, refined by #66627).
Video support in product gallery (beta)
WooCommerce 11.1 introduces experimental support for videos in both classic and block-based product galleries. The initial release supports locally uploaded videos only. The feature is disabled by default and can be enabled under WooCommerce → Settings → Advanced → Features → Product gallery videos. As an experimental feature, it may change in future releases. Share your feedback in the GitHub discussion. (#65396)
Developer updates
Unified block editor assets A new experimental feature replaces WooCommerce’s per-block editor scripts and styles with shared JavaScript and CSS bundles, cutting the number and total size of editor asset requests. It’s disabled by default in 11.1; with it off, existing handles and per-block assets behave exactly as before, and frontend assets are unchanged either way. (#66200)
Changes to order item deletion WC_Abstract_Order::remove_order_items() now records which item IDs existed when removal was requested, so replacement items an extension adds before $order->save() are no longer deleted by accident. Most extensions won’t require a change, but if you maintain a custom order data store, review your get_item_ids() and delete_items_by_ids() implementations.
Block registration skips non-rendering requests WooCommerce 11.1 no longer registers block types and patterns on requests that can’t render or edit blocks, making Store API and REST requests 30–42% faster. If your extension renders WooCommerce blocks during one of those requests, opt back in with the new woocommerce_should_register_blocks filter. Product and variation descriptions are handled on demand and need no action.
Retiring stable WooCommerce Admin feature flags A set of stable WooCommerce Admin features now load directly instead of through the feature configuration pipeline. No functionality is removed, and deprecated shims keep Features::is_enabled() and window.wcAdminFeatures returning compatibility values, but they now emit deprecation warnings, so audit your extensions and remove those gates before the shims go.
WooCommerce is old enough that its most important string values (order statuses, product types, stock states, tax modes) predate almost every modern PHP convention. Across the WooCommerce codebase, and in many extensions, every one of those comparisons was written against a raw string literal:
if ( 'completed' === $order->get_status() ) { // hope you spelled it right!
Over the last few years, WooCommerce has begun shipping a family of enum classes under Automattic\WooCommerce\Enums. These are named, documented constants for order statuses, product types, stock states, settings values, and more.
The enum classes are considered a public API, and extension developers are encouraged to use them. This post covers what’s available, why we built classes of string constants instead of native PHP enums, and what shipping them taught us about load order and backward compatibility.
The price of a “magic string”
String literals might feel easier to write or more simple than classes, but the come with tradeoffs. Spread across a codebase the size of WooCommerce and the many extensions, magic strings tax you four ways:
Silent errors. Linters, autoloaders, and tests may not catch an error like typing 'complete' instead of 'completed'.
Abiguity. WordPress stores post-prefixed order statuses as wc-completed, while most WooCommerce APIs expect the un-prefixed completed, something a developer may only discover the hard way.
Discoverability. An agent searching 'simple' to find product-type logic returns half the codebase. Grepping for ProductType::SIMPLE should return a much narrower, accurate set of results.
Documentation. The definition for a status like on-hold will now live in a docblock next to its declaration.
Enum classes have the added benefit of clarifying empty strings based on intent. For example, woocommerce_default_customer_address treats '' as “no default”, which is unguessable without a named constant.
Why not native PHP enums
PHP has had enum support since 8.1, but for a few reasons, it wasn’t a viable solution for WooCommerce. Primarily, WooCommerce’s minimum supported PHP version is 7.4 which doesn’t include support for native enums.
There’s also an architectural difference.These values are already stored as plain strings in millions of databases, and thousands of extensions expect them to stay that way. Native PHP enums would turn those strings into objects, which could break existing code. String constants avoid this problem. OrderStatus::COMPLETED still produces the same 'completed' string, so developers can use the clearer name without changing how WooCommerce works. Existing code continues to work, and extensions can adopt the new constants when they are ready.
final class OrderStatus {
/**
* Order fulfilled and complete.
*/
public const COMPLETED = 'completed';
// ...
}
These constants are intentionally a publicly discoverable API, with explicit public visibility, docblocks, and developer docs. Extension developers are welcome to rely on them.
use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Enums\ProductType;
if ( OrderStatus::COMPLETED === $order->get_status() ) {
// ...
}
$products = wc_get_products( array( 'type' => ProductType::SIMPLE ) );
Two things to check before adopting them:
Your minimum supported WooCommerce version. The classes landed incrementally: OrderStatus in WooCommerce 9.5, the product classes around 9.7 and 9.8, the settings-value classes across the 10.x releases. If you support older versions, keep the literal or guard usage with class_exists().
Which string WooCommerce expects.OrderStatus::COMPLETED is completed; OrderInternalStatus::COMPLETED is wc-completed. Most WooCommerce functions take the un-prefixed form; database-level and post_status contexts use the prefixed one.
New vocabularies in core should now get an enum class by default. WooCommerce still contains many string values that deserve names, and contributions are welcome.