Sign up ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm currently setting up a woocommerce driven shop.

I use the fedex shipping calc. extension to get the shipping costs calculated.

I wanna ship all items that are under 200$ for free. never mind if the cart total is above the 200$. Means you can add 4 or 6 or never mind how much items to the cart if each of the items is below the 200$ the shipping is free.

So what I did is I have set all that (below 200$)items up as "virtual" items. That way they skip the fedex shipping calc.

The problem is that I also wanna offer LOCAL PICKUP as a shipping option. But customers are not able to select that option if they have virtual items only in their cart.

Is there a way to enable the local pickup option anyway?

Or is there a smarter solution to get that idea done?


i have also tried to the following:

  1. I have created a special shipping class named it "free shipping".

  2. I have disabled the "virtual" option for one of the items wich has a price below the 200$. And i added that "special class "free shipping" to that item.

  3. I have then activated the FLAT RATE shipping method and set the shipping cost on that to 0.00

  4. I told that FLAT RATE shipping option to be active for my previously generated class (free shipping) only.

  5. I renamed the option from FLAT RATE to FREE SHIPPING so that it is listed as FREE SHIPPING on the checkout page

  6. So far so good, now if i add that item to the basket i see both options the FREE SHIPPING (the original flat rate i have renamed) and the "LOCAL PICKUP" option.

so far so good. that works fine ...

the problem is as soon as i add an another item to the cart with an price over 200$ fedex take affect and will calculate the shipping cost and a few fedex options are displayed.

i also see the local pickup BUT AND THAT IS THE PROBLEM I ALSO SEE THE FREE SHIPPING OPTION CUZ THE the item i have given the special class is still in the basket.

means people are able to select free shipping and that is not what i am looking for. As soon as a item with a price of over 200$ is in the basket the free shipping should be gone.


Here's a snippet colleted from some Gists out of a GitHub issue discussion linked by @Ewout in another answer. I added a var_dump(), so you can uncomment and check what exactly you want to remove.

$available_methods is an array of:

$available_methods as $method_id => $method
Compare against $method_id if you need more specific checks.

// Hide standard shipping option when free shipping is available
add_filter( 'woocommerce_available_shipping_methods',         'wpse90835_hide_standard_shipping_when_free_is_available' );
 *  Hide Standard Shipping option when free shipping is available
 * @param array $available_methods
function  wpse90835_hide_standard_shipping_when_free_is_available($available_methods )
// Developers!: Dump this to see what you can unset
# var_dump( $available_methods );

// remove standard shipping option
if ( 
    isset( $available_methods['free_shipping'] ) 
    AND isset( $available_methods['flat_rate'] )
    unset( $available_methods['flat_rate'] );

return $available_methods;

can somebody tell me how to use the "Compare against $method_id if you need more specific checks."

share|improve this question
I'm not an expert on shipping, but couldn't you create a special shipping class? Once you set the items as virtual, you're telling WooCommerce that they don't need to be shipped. – helgatheviking Nov 13 '13 at 11:58
The thing is as soon as you are set a item to "virtual" the option to assign it to a shipping class is not available anymore. i have also tried to the following: – Shorty05 Nov 13 '13 at 15:45
Right, so don't set the item as virtual. I just looked into it though and I can't (quickly) find a way to exclude items from the the API shipping calculation. I'm sure it is possible, but I can't think of anything off-hand. – helgatheviking Nov 13 '13 at 16:14

1 Answer 1

Well I dug a little deeper and found that in the abstract WC_Product class, there is the needs_shipping() method:

 * Checks if a product needs shipping.
 * @access public
 * @return bool
public function needs_shipping() {
    return apply_filters( 'woocommerce_product_needs_shipping', $this->is_virtual() ? false : true, $this );

and it is filterable, which means we can override the need for shipping costs on any product we like. Assuming you have a shipping class with the slug: shipping-class you can set any item with that class to not need shipping:

function wpa_123136_no_shipping( $needs_shipping, $product ){
  if( $product->get_shipping_class() == 'free-shipping' ){
    $needs_shipping = false;
  return $needs_shipping;
add_filter('woocommerce_product_needs_shipping','wpa_123136_no_shipping', 10, 2 );

or if you have a price-point and don't want to bother with the free shipping class:

function wpa_123136_no_shipping( $needs_shipping, $product ){
  if( $product->get_price() < 200 ){
    $needs_shipping = false;
  return $needs_shipping;
add_filter('woocommerce_product_needs_shipping','wpa_123136_no_shipping', 10, 2 );
share|improve this answer
thanks for looking into that ;) i will test it now and let you know if that works. – Shorty05 Nov 13 '13 at 18:04
it doesn't work. as soon as i unstick the "virtual" option i see the shipping tab and if i don't fill in any dimensions or weights i get an error at the cart: Product # is missing dimensions. Aborting. (it comes from the fedex plugin) which means the code gets ignored cuz fedex still tries to calculate shipping. – Shorty05 Nov 14 '13 at 13:46
Sorry. The solution must be in the shipping methods files (maybe in calculate_shipping()?) but I'm not familiar enough with the shipping classes and don't have the Fedex plugin to even look at. – helgatheviking Nov 14 '13 at 15:27
no problem helga, thanks for looking into it anyway! i am very thankful for all your infos. – Shorty05 Nov 14 '13 at 17:13

protected by Community Sep 14 at 3:06

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.