Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

Woocommerce: Hide a shipping method depending on category WordPress



I have 3 shipping methods activated out of the 5 that comes with Woocommerce.

I wish to hide one of the methods on checkout when certain categories are bought.

In more detail:

I sell Used and New products. The Used products are eligible for Free and Local. The New products are eligible for Flat, Free and Local.

Therefore I want to hide the Flat method when the category is Used.

I know there are plugins, but would prefer to use code in functions.php to keep my site lean.


Answers (3)


Arnav Joy answers:

please try this

function my_free_shipping( $is_available ) {
global $woocommerce;
// set the product ids that are ineligible
$ineligible = array( '14009', '14031' );
// get cart contents
$cart_items = $woocommerce->cart->get_cart();
// loop through the items looking for one in the ineligible array
foreach ( $cart_items as $key => $item ) {
if( in_array( $item['product_id'], $ineligible ) ) {
return false;
// nothing found return the default value
return $is_available;
add_filter( 'woocommerce_shipping_free_shipping_is_available', 'my_free_shipping', 20 );


Francisco Javier Carazo Gil answers:

You have to use this filter: woocommerce_package_rates

I am going to prepare a piece of code for you now.

Francisco Javier Carazo Gil comments:

You have to know which slug has each shipping method but take this code:

add_filter( 'woocommerce_package_rates', 'hide_shipping_method' , 10, 2 );

function hide_shipping_method( $rates, $package ) {
global $woocommerce;

$excluded_categories = array( 'here categories ids' );

$cart_items = $woocommerce->cart->get_cart();

foreach ( $cart_items as $key => $item ) {
$categories = get_the_terms( $item['product_id'], 'product_cat' );
foreach ($categories as $category) {
$product_cat_id = $category->term_id;

if( in_array( $product_cat_id, $excluded_categories ) ) // delete the shipping method
unset( $rates['shipping_method_to_delete'] );

return $rates;


Romel Apuya answers:

try this.

function filter_gateway_flatrate($gateways){

$payment_NAME = 'flat_rate';
$category_ID = '20'; // <-- changed this to category ID of Used

global $woocommerce;

foreach ($woocommerce->cart->cart_contents as $key => $values ) {
$terms = get_the_terms( $values['product_id'], 'product_cat' );
foreach ($terms as $term) {

if($term->term_id == $category_ID){

return $gateways;