Practical WordPress guide

Keep Local Pickup with Free Shipping for WooCommerce: safe setup, failure cases, and rollback

A plain-language guide for nontechnical site owners. It separates what the parent plugin really knows from what a helper plugin should never guess.

Reviewed July 20, 2026Official-source links includedNo invented performance claims

Direct answer

To show Free Shipping and Local Pickup together, let WooCommerce calculate the valid rates first. When the returned package contains Free Shipping, keep the existing Free Shipping and Pickup rates and omit only the other delivery rates from that package's visible list.

Do not create a pickup method, force a free rate, recalculate shipping, or edit zone settings during checkout. If Free Shipping is absent or any rate is malformed, return the complete original list unchanged.

Keep Local Pickup with Free Shipping for WooCommerce follows that fail-passive model. Free applies one store-wide display rule. Pro can limit it to named zones and keep a bounded set of additional existing methods.

Why the conflict appears

Many stores want a simple policy:

  • below the threshold, show normal paid delivery and pickup;
  • above the threshold, show Free Shipping and pickup;
  • hide the paid delivery choices only after Free Shipping exists.

Public support reports show how often that expectation becomes confusing. Merchants ask to show local pickup when Free Shipping appears, report that WooCommerce does not honor the expected shipping order, describe a Local Pickup and Free Delivery conflict, ask to keep Free Shipping and pickup from the store, or see shipping choices reset when Free Shipping becomes available.

These threads do not establish one universal defect. Rate visibility can be affected by zones, coupons, thresholds, package splitting, extensions, blocks, themes, caches, and custom snippets. They do establish a clear user task: when free delivery is valid, do not remove the customer's pickup choice.

Filter after WooCommerce calculates rates

WooCommerce owns shipping-zone matching, package construction, method instances, taxes, costs, and rate calculation. Its current WC_Shipping source shows the core calculation boundary.

A narrow display rule should receive the rate list after that calculation and answer only:

  1. Is this a valid bounded list of shipping rate objects?
  2. Does at least one rate use the free_shipping method?
  3. Which existing rates are Free Shipping, Local Pickup, or a pickup location?
  4. Is the filtered result safe to return?

It should not ask whether the cart ought to qualify. WooCommerce already answered that by returning or not returning a Free Shipping rate.

The unchanged-list fallback protects checkout

Shipping is a purchase-critical surface. Hiding the wrong rate can strand a shopper or silently alter delivery expectations. The safest uncertain-state behavior is therefore the original complete list.

Return every rate unchanged when:

  • the feature is off;
  • WooCommerce is unavailable;
  • the package contains no Free Shipping rate;
  • the rate container is not the expected bounded array;
  • a rate is not a recognized rate object;
  • a method ID cannot be read safely;
  • a selected Pro zone cannot be resolved;
  • the Pro service or license is unavailable.

This is fail-passive behavior. It favors native WooCommerce checkout over enforcing a cosmetic preference on bad input.

Do not confuse a method type with a method instance

WooCommerce can have several instances of the same method type in different zones. A returned rate ID can include an instance suffix, while its method ID remains a stable type such as:

  • free_shipping;
  • local_pickup;
  • pickup_location;
  • flat_rate.

The Free rule keeps every returned Free Shipping and Pickup instance. It does not assume there is only one.

Pro can let a merchant select additional method types by their WooCommerce names. That is safer than asking a beginner to copy internal IDs into a text box. It also keeps the list bounded and reviewable.

Configure the source methods before adding a filter

Use this sequence:

  1. Configure the target shipping zone in WooCommerce.
  2. Add and enable Free Shipping.
  3. Set its real coupon, minimum amount, or other supported condition.
  4. Add and enable Local Pickup or the supported pickup-location method.
  5. Test a destination and cart without StoreFixKit.
  6. Confirm both source rates can appear.
  7. Enable the StoreFixKit display rule.

If Local Pickup does not exist in the calculated list, a filter cannot keep it. If Free Shipping does not exist, a filter must not manufacture it.

WooCommerce also sells a broader Conditional Shipping and Payments extension and publishes its rule documentation. That confirms demand for shipping controls, but a general rule builder has a much larger configuration and testing surface than this one outcome.

Zone controls should remain explicit

A store may want the rule in one delivery region but not another. Pro can provide named zone checkboxes with two simple semantics:

  • no zone selected: apply the Free rule everywhere;
  • one or more zones selected: apply it only when WooCommerce resolves the current package to one of those zones.

The plugin should not rewrite zone records. If a merchant deletes and recreates a zone, they should reopen the Pro screen, select the new named zone, and test it again.

Additional methods need a hard cap

Some stores need Free Shipping, Local Pickup, and one appointment or freight choice. Pro can keep up to ten additional existing method types.

That limit prevents a focused tool from becoming an open-ended shipping rule engine. It also keeps the checkout result understandable: the merchant can name every method that remains visible.

Pro should still avoid:

  • price changes;
  • threshold changes;
  • postcode or city expression languages;
  • arbitrary PHP conditions;
  • rate creation;
  • package recalculation;
  • checkout-side API calls;
  • order mutations.

Test both sides of the threshold

One successful qualifying cart is not enough. Use a disposable cart and run this matrix for every relevant zone.

Test Expected result
Below Free Shipping condition Original rate list unchanged
Above Free Shipping condition Existing Free Shipping and Pickup remain
Above condition with paid delivery Paid delivery hidden unless Pro keeps its method
Coupon removed Original non-free choices return
Destination moved to another zone That zone's native result or selected Pro rule applies
Multiple packages Each package is evaluated independently
Malformed test rate Complete original package list returned
Pro unavailable Free store-wide rule continues locally
Plugins deactivated Complete native WooCommerce list returns

Repeat the result on desktop and mobile. Also change the shopper's selected method after the rate list changes and confirm WooCommerce still owns selection, totals, taxes, and order creation.

Security and data ownership

The settings screen should require manage_woocommerce and a nonce. Storefront requests do not need a new public endpoint, cookie, or token because the plugin reads only the current rate list inside WooCommerce's normal calculation path.

The plugin owns only three small option groups: Free settings, Pro rules, and the Pro license record. It does not own shipping zones, method instances, rates, costs, taxes, carts, addresses, orders, or customer records.

Default uninstall should preserve its settings. An explicit STOREFIXKIT_DELETE_DATA=true cleanup may remove only those StoreFixKit options.

Resource boundary

The rule can remain lightweight:

  • no custom table;
  • no cron or Action Scheduler job;
  • no historical cart or order scan;
  • no frontend CSS or JavaScript;
  • no telemetry;
  • no storefront StoreFixKit request;
  • one bounded pass over the rate list WooCommerce already calculated.

It should never trigger a second shipping calculation from inside the rate filter.

Rollback without changing shipping configuration

Record the test cart, destination, coupon state, subtotal, and native method list. Keep the current Free and Pro ZIPs plus a database backup.

Deactivate Pro, then Free. The full native list should return immediately because the plugins did not edit WooCommerce shipping configuration. Test the known baseline packages with the same cart, then return to the current release.

Compare zones, method instances, costs, tax settings, package contents, cart totals, and one disposable order before and after. Every WooCommerce-owned value should stay unchanged.

The Keep Local Pickup documentation contains real screenshots, exact setup, troubleshooting, rollback, uninstall ownership, and the support evidence to collect.

FAQ

How do I keep Local Pickup when Free Shipping is available?

Configure both methods in WooCommerce first. Then filter the already-calculated package rates so Free Shipping and Pickup remain while unrelated delivery rates are omitted.

Does the plugin create Local Pickup?

No. It can keep only a valid rate WooCommerce has already returned.

What happens below the Free Shipping threshold?

The complete original rate list stays unchanged.

Can I keep Flat rate too?

Pro can keep a bounded list of additional existing method types, including Flat rate, by selecting their WooCommerce names.

What happens when Pro expires?

The Free store-wide Free Shipping plus Pickup rule continues locally. Pro zone and additional-method choices turn off.

Focused plugin

Use the one-job implementation.

When WooCommerce has already calculated Free Shipping, keep its existing Free Shipping and Local Pickup choices while hiding the other calculated delivery rates.