=== Diamond Sierra Loader for WooCommerce ===
Contributors: diamondsierra
Tags: woocommerce, performance, speed, plugin loading, mu-plugin
Requires at least: 6.0
Tested up to: 6.9
Requires PHP: 7.4
Requires Plugins: woocommerce
Stable tag: 1.1.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Loads WooCommerce and its add-ons only where the store needs them, so blog posts, docs and information pages stop paying for the whole store.

== Description ==

WordPress starts every active plugin on every request. On a site that sells a few things and publishes a lot of reading, that means WooCommerce, its payment gateways and its add-ons start up for every blog post and documentation page, even though nothing on them is for sale.

This plugin installs a small must-use plugin that leaves WooCommerce, and the active plugins that say they need it, out of a request when all of these are true:

* it is a logged-out GET or HEAD page view;
* the visitor has no cart or store session cookie;
* it is not wp-admin, the REST API, AJAX (including wc-ajax), cron, WP-CLI, XML-RPC or a login;
* it has no query arguments other than tracking tags such as utm_source (plugins use query arguments for add-to-cart, download links, links in emails, payment returns, previews and search);
* the address is not a store address.

Store addresses are read from WooCommerce's own settings (shop, cart, checkout, My account and terms pages, and the product, category and tag bases). Add any other page that shows prices, add-to-cart buttons or order lookups under Settings > Loader for WooCommerce.

The saved list of active plugins is never changed. If anything tries to save the plugin list or the rewrite rules during a request that left the store out, the store plugins and their rules are kept.

On diamondsierra.com, uncached logged-out requests for non-store pages went from a median of 296.5 ms to 171.4 ms of server time, with peak memory down from 46 MB to 20 MB, measured with the Paul Bunyan plugin. Read the case study: https://diamondsierra.com/woocommerce-only-where-needed/

== Installation ==

1. Upload the zip under Plugins > Add New > Upload Plugin and activate it. Activating copies the must-use file into wp-content/mu-plugins.
2. Open Settings > Loader for WooCommerce. Add any extra addresses that need the store.
3. Use "Check addresses" on your home page, a blog post, a few information pages and every store page. Each row says whether WooCommerce was left out or loaded, and flags error pages.
4. Clear your page cache if your caching plugin is not one the plugin clears for you (LiteSpeed Cache, WP Rocket, W3 Total Cache and WP Super Cache are cleared automatically).

If the mu-plugins folder cannot be written, the plugin says so; copy mu/ds-woo-loader-mu.php into wp-content/mu-plugins by hand.

== Frequently Asked Questions ==

= Will this break my store? =

The store loads in full for its own pages, for signed-in users and shoppers with a cart, and for every admin, REST API, AJAX, cron and webhook request. A theme or plugin that calls WooCommerce functions without checking that WooCommerce is loaded will show an error on a page where the store was left out. Use "Check addresses" after installing and add any such page to the list.

= I already use a page cache. Does this help? =

A page cache answers most logged-out visits without starting WordPress. Every cache miss still starts it: the first visit after a page changes, crawlers, links with unique query strings and pages that cannot be cached. Those requests get faster.

= Does anything stop working on non-store pages? =

WooCommerce's order attribution script only starts recording when a visitor reaches a store page, so a buyer who first arrived on a blog post may be recorded as a direct visit. Mini-cart widgets on non-store pages will not show for logged-out visitors without a cart.

= How do I switch it off at once? =

Untick "Leave the store out" in the settings, deactivate the plugin, or add define( 'DS_WOO_LOADER_OFF', true ); to wp-config.php.

= How can I see it working? =

Skipped pages send the response header "X-DS-Woo-Loader: skipped". The free Paul Bunyan plugin shows each plugin's cost per request before and after.

== Developer filters ==

* "ds_woo_loader_keep_paths" (array of addresses) adds store addresses.
* "ds_woo_loader_plugins" (array of plugin files) changes which plugins are left out.
* "ds_woo_loader_ignored_args" (array) lists query arguments that do not keep the store; a trailing * matches a prefix.
* "ds_woo_loader_skip" (bool, path) for any other rule.

Filters must be added from a must-use plugin, because the decision is made before normal plugins load.

== Changelog ==

= 1.1.1 =
* Any query argument other than a tracking tag now keeps the store, so links that plugins send by email or use for downloads keep working.

= 1.1.0 =
* Store addresses read from WooCommerce settings.
* Plugins that declare they need WooCommerce are left out with it.
* Settings screen with extra addresses, extra plugins and an address checker.

= 1.0.0 =
* First release, used on diamondsierra.com.
