27 Ways to Improve Woocommerce Store

If you take a look around here on my site you’ll find ca 250 different Woocommerce related hacks. In this post I’ll show you 27 of my favorite Woocommerce cart page, checkout page and my account page related hacks. So, let’s take a look at the 27 ways how to improve your Woocommerce store.

One thing you need to know beforehand, though. If you don’t know where to add those snippets here below, then add them either to your child theme’s functions.php file or better yet, use a snippet manager like Code Snippets

Video: 27 Ways How to Improve Woocommerce Store

How to set Minimum Order Amount in WooCommerce?

With the help of this snippet here below we will set a minimum order amount in Woocommerce to 1000 euros and will display an error message on the cart and checkout pages if the conditions are not met (see the screenshot). Just replace the amount inside the code accordingly.

27 Ways to Improve Woocommerce Store
// Set Minimum Order Amount in WooCommerce
add_action( 'woocommerce_checkout_process', 'wc_minimum_order_amount' );
add_action( 'woocommerce_before_cart' , 'wc_minimum_order_amount' );
 
function wc_minimum_order_amount() {
    
    $minimum = 1000; // Set this variable to specify a minimum order value

    if ( WC()->cart->total < $minimum ) {

        if( is_cart() ) {
            wc_print_notice( 
                sprintf( 'Your current order total is %s — you must have an order with a minimum of %s to place your order ' , 
                    wc_price( WC()->cart->total ), 
                    wc_price( $minimum )
                ), 'error' 
            );
        } else {
            wc_add_notice( 
                sprintf( 'Your current order total is %s — you must have an order with a minimum of %s to place your order' , 
                    wc_price( WC()->cart->total ), 
                    wc_price( $minimum )
                ), 'error' 
            );

        }
    }
}

How to show “XX to free shipping” notification in Woocommerce?

It is a good idea to motivate your users to buy a bit more in order to get free shipping. This snippet here below will add this text to your cart “Buy XX€ worth products more to get free shipping”

How to show "XX to free shipping" notification in Woocommerce?
// Show "XX to free shipping" notification in Woocommerce
add_action( 'woocommerce_before_cart_table', 'cart_page_notice' );
 
function cart_page_notice() {
	$min_amount = 1000; //This is the amount of your free shipping threshold. Change according to your free shipping settings
	$current = WC()->cart->subtotal;
	if ( $current < $min_amount ) {
	$added_text = '<div class="woocommerce-message"><strong>Buy  ' . wc_price( $min_amount - $current ) . ' worth products more to get free shipping</strong>'; // This is the message shown on the cart page
	$return_to = wc_get_page_permalink( 'shop' );
	$notice = sprintf( '%s<a class="button" href="%s">%s</a>', $added_text, esc_url( $return_to ), 'Continue shopping</div>' ); // This is the text shown below the notification. Link redirects to the shop page
	echo $notice;
	}
}

How to display custom message to Woocommerce cart page?

Maybe you need to warn your customers that shipping is delayed or you need something elso to communicate. If so, then use this snippet and replace text accordingly.

How to add custom message to Woocommerce cart page?
// Add custom message to Woocommerce cart page
add_action( 'woocommerce_before_cart_table', 'shop_message', 20 );
function shop_message() {
echo '<p class="woocommerce-message">Estimated delivery time: 2 weeks</p>'; // Change this text
}

How to Update WooCommerce Cart on Quantity Change?

Next snippet is also a nice one. This allows you to hide Update cart button and it will update your cart amount every time you update product quantities. So, if you need to update WooCommerce cart on quantity change then use this snippet here below.

// Update WooCommerce Cart on Quantity Change

add_action('wp_head', function(){
    
    $css_code = <<<CSS
    <style>
    .woocommerce-notices-wrapper div.woocommerce-message[role=alert] {
        display: none;
    }
    
    .woocommerce button[name="update_cart"] {
        display: none !important;
    }
    </style>
CSS;
    $js_code = <<<JS
        <script type="text/javascript">
        jQuery(document).ready(function(){
            var wpcbScrollToNotices;
        
            jQuery(document).ajaxComplete(function (e) {
                jQuery.scroll_to_notices = wpcbScrollToNotices;
            });
            
            jQuery('.woocommerce').on('change', 'input.qty', function(){
            
                wpcbScrollToNotices = jQuery.scroll_to_notices;
                jQuery.scroll_to_notices = function( scrollElement ) {
                    return false;
            	};
            	
            	setTimeout(function(){
            	    jQuery('button[name="update_cart"]').trigger('click');    
            	}, 200);
                
            
            });
        });
        </script>
JS;
    echo $css_code;
    echo $js_code;
});

How to change Woocommere “Return to shop” URL?

Take a look at the URL /about-us/ in the snippet and if you want to change your Woocommerce “Return to shop” url then replace it with your own URL.

// Change Woocommere "Return to shop" URL
add_filter( 'woocommerce_return_to_shop_redirect', 'return_to_shop_url' );
function return_to_shop_url() {
	return '/about-us/'; // Change your url
}

How to add Woocommerce backorder notification in cart page?

I have had customers who complain that they did not realize that they ordered a product which was not in stock and was available on backorder. Therefore, this snippets adds Woocommerce backorder notification in cart page.

As you see from the screenshot below it outputs this message styled as error message. If you want it to show as default Woocommerce message notification then replace ‘error’ with ‘notice’

How to add Woocommerce backorder notification in cart page?
// Add Woocommerce backorder notification in cart page
add_action( 'woocommerce_before_cart_table', 'show_backordered_items_cart_notice' );
function show_backordered_items_cart_notice() {
    $found = false;
    foreach( WC()->cart->get_cart() as $cart_item ) {
        if( $cart_item['data']->is_on_backorder( $cart_item['quantity'] ) ) {
            $found = true;
            break;
        }
    }
    if( $found ) {
// Change this text here. If you want it to show as default Woocommerce message notification then replace 'error' with 'notice'
        wc_print_notice( __("<strong>You have products in the cart that are available only in backorder.</strong><br> For those products estimated delivery time is 2-3 weeks.", "woocommerce"), 'error' ); 
    }
}

How to display backorder notification at Woocommerce checkout page

Some of my customer have complained that they did not realize that they ordered a product which was not in stock and was available only on backorder. Since I wanted to made it less confusing for them I added this snippet here below which shows backorder notification in Woocommerce checkout page. hence, I’m going to show you how to customize Woocommerce checkout page with this little hack.

As you see from the screenshot below it outputs this message styled as error message. If you want it to show as default Woocommerce message notification then replace ‘error’ with ‘notice’

How to add Woocommerce backorder notification in cart page?
// Show Woocommerce backorder notification in checkout page
add_action( 'woocommerce_before_checkout_form', 'show_backorder_checkout_notice' );
function show_backorder_checkout_notice() {
    $found = false;
    foreach( WC()->cart->get_cart() as $cart_item ) {
        if( $cart_item['data']->is_on_backorder( $cart_item['quantity'] ) ) {
            $found = true;
            break;
        }
    }
    if( $found ) {
// Change this text here. If you want it to show as default Woocommerce message notification then replace 'error' with 'notice'
        wc_print_notice( __("<strong>You have products in the cart that are available only in backorder.</strong><br> For those products estimated delivery time is 2-3 weeks.", "woocommerce"), 'error' ); 
    }
}

How to auto-expand coupon field on Woocommerce checkout page? No need to click on “Have a coupon?” link

Let’s be honest: it’s a bit annoying to click on a “Have a coupon?” link on your Woocommerce chekcout page. Therefore, let’s auto-expand the coupon field and remove one more unnecessary click.

// Auto-expand coupon field on Woocommerce checkout page
add_action( 'wp_footer', 'wpsh_display_coupon_field', 99 );
function wpsh_display_coupon_field() {
echo '
<script type="text/javascript">
jQuery(document).ready(function($) {
$(\'.checkout_coupon\').show();
});
</script>
';
}

How to change Woocommerce coupon field location on checkout page v.1?

If you like the styling and layout of the previous hack and you would like to display it also on a Woocommerce checkout page (under the Place order button), then use this snippet here below (and don’t forget to add CSS from the previous snippet).

// Move Woocommerce coupon field location in checkout page
remove_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_coupon_form', 10 );
add_action( 'woocommerce_review_order_after_submit', 'move_checkout_coupon_field', 1 );

function move_checkout_coupon_field() {
   ?> 
      <form class="woocommerce-coupon-form" action="<?php echo esc_url( wc_get_checkout_url() ); ?>" method="post">
         <?php if ( wc_coupons_enabled() ) { ?>
            <div class="coupon under-proceed">
               <input type="text" name="coupon_code" class="input-text" id="coupon_code" value="" placeholder="<?php esc_attr_e( 'Coupon code', 'woocommerce' ); ?>" style="width: 100%; margin-top: 10px;" /> 
               <button type="submit" class="button" name="apply_coupon" value="<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>" style="width: 100%"><?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?></button>
            </div>
         <?php } ?>
      </form>
   <?php
}

How to change Woocommerce coupon field location on checkout page v.2?

There’s also another way to move your Woocommerce coupon field location on checkout page. Here’s the end result.

How to change Woocommerce coupon field location on checkout page?

So, to make it work like that, just use this snippet.

// Change Woocommerce coupon field location in cart page?
remove_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_coupon_form', 10 );
add_action( 'woocommerce_review_order_after_submit', 'wpsh_move_coupon_button', 1 );
 
function wpsh_move_coupon_button() {
  echo '<hr/';
   woocommerce_checkout_coupon_form();
}

How to remove “Ship to adifferent address” if Local Pickup is selected?

There is no need for “ship to a different address” section if customer has chosen Local pickup as a shiping method. Therefore, let’s “ship to different address” if Local Pickup is selected.

// Remove "ship to a different address" if Local Pickup is selected

add_action( 'woocommerce_after_checkout_form', 'wpsh_remove_ship_to_section' );
  
function wpsh_remove_ship_to_section( $available_gateways ) {
    
   $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
   $chosen_shipping = $chosen_methods[0];
   if ( 0 === strpos( $chosen_shipping, 'local_pickup' ) ) {
   ?>
      <script type="text/javascript">
         jQuery('#customer_details .col-2 .woocommerce-shipping-fields').fadeOut();
      </script>
   <?php  
   } 
   ?>
      <script type="text/javascript">
         jQuery('form.checkout').on('change','input[name^="shipping_method"]',function() {
            var val = jQuery( this ).val();
            if (val.match("^local_pickup")) {
                     jQuery('#customer_details .col-2 .woocommerce-shipping-fields').fadeOut();
               } else {
               jQuery('#customer_details .col-2 .woocommerce-shipping-fields').fadeIn();
            }
         });
      </script>
   <?php
  
}

How to disable Woocommerce shipping methods for a specific shipping class?

Now, there are two things you would need to do beforehand:

  • Add a shipping class. Go to Woocommerce >> Settings >> Shipping >> Shipping classes and add one. For example: “Courier only”
  • Write down the shipping class slug because you will need it later. Where to get the slug? See the screenshot below.
  • Add shipping class to the needed product. Open your product and see under Shipping tab.
How to Hide Woocommerce shipping methods for specific shipping classes?

Next, go to Snippets >> Add new and paste this snippet here below inside your code box. Pay attention though that you need to change the shipping class slug on line 4 accordingly.

So, if in this example I have a “Courier only” shipping class with a slug “courier-only”, then replace the slug in the code accordingly with the correct one.

One more thing, on line 12 there is a shipping method that you are hiding (Flat rate). Change the shipping method name and ID as needed. How to find your shipping ID number? Well, take a look at the video above (see the 3min 44sec mark).

/* Hide Woocommerce shipping method for a specific shipping class */
function hide_flat_rate_shipping( $rates, $package ) {
    // shipping class IDs that need the method removed
    $shipping_classes = array('courier-only'); // Here goes your shipping class slug
    $if_exists = false;
 
    foreach( $package['contents'] as $key => $values ) {
        if( in_array( $values[ 'data' ]->get_shipping_class(), $shipping_classes ) )
            $if_exists = true;
    }
 
    if( $if_exists ) unset( $rates['flat_rate:2'] ); // Here goes your shipping method that needs to be hidden. Don’t forget to add correct one here
 
    return $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_flat_rate_shipping', 10, 2 );

If you would like to know how to hide Woocommerce multiple shipping methods using shipping classes, then see my previous post here.

How to Hide Woocommerce Checkout Fields When Local Pickup is Selected?

One of the most annoying things with the Woocommerce shiping system is that if Local Pickup shipping method is chosen then you still need to fill in all the address and postcode fields. But what if you could automatically hide those fields if Local pickup method is chosen?

/* This piece of code will hide fields for the chosen method.
.hide_pickup {
    display: none !important;
}
*/
 
// Hide Local Pickup shipping method
add_filter( 'woocommerce_checkout_fields', 'hide_local_pickup_method' );
function hide_local_pickup_method( $fields_pickup ) {
    // change below for the method
    $shipping_method_pickup ='local_pickup:2';
    // change below for the list of fields. Add (or delete) the field name you want (or don’t want) to use
    $hide_fields_pickup = array( 'billing_company', 'billing_country', 'billing_postcode', 'billing_address_1', 'billing_address_2' , 'billing_city', 'billing_state');
 
    $chosen_methods_pickup = WC()->session->get( 'chosen_shipping_methods' );
    $chosen_shipping_pickup = $chosen_methods_pickup[0];
 
    foreach($hide_fields_pickup as $field_pickup ) {
        if ($chosen_shipping_pickup == $shipping_method_pickup) {
            $fields_pickup['billing'][$field_pickup]['required'] = false;
            $fields_pickup['billing'][$field_pickup]['class'][] = 'hide_pickup';
        }
        $fields_pickup['billing'][$field_pickup]['class'][] = 'billing-dynamic_pickup';
    }
    return $fields_pickup;
}
// Local Pickup - hide fields
add_action( 'wp_head', 'local_pickup_fields', 999 );
function local_pickup_fields() {
    if (is_checkout()) :
    ?>
    <style>
        .hide_pickup {display: none!important;}
    </style>
    <script>
        jQuery( function( $ ) {
            if ( typeof woocommerce_params === 'undefined' ) {
                return false;
            }
            $(document).on( 'change', '#shipping_method input[type="radio"]', function() {
                // change local_pickup:4 accordingly
            $('.billing-dynamic_pickup').toggleClass('hide_pickup', this.value == 'local_pickup:2');
            });
        });
    </script>
    <?php
    endif;
}

Now, pay attention that the snippet above works only with one Local Pickup Shipping method. If you have multiple Local Pickup selections, then the code above works only with one of them and then you should use this snippet here below

How to Hide Woocommerce Checkout Fields Based on Shipping Methods?

This one here is a bit tricky one and will do this:

  • If Local pickup (local_pickup:2) is selected, Billing country, postcode, address 1, address 2 and city fields are disabled.
  • If Local Pickup 2 (local_pickup:8) is selected, Billing country, postcode, address 1, address 2 and city fields are disabled.
  • If Local pickup (multiparcels_smartpost_pickup_point:7) is selected, Billing country, postcode, address 1, address 2 and city and phone fields are disabled.

If you would like to use this snippet, then take a look at line 30 for changing your shipping ID. Line 33 contains fields to be hidden. And line 70 should once again contains your shipping method. So, everything between lines 25 and 76 contains code for Local pickup method. Lines 78-130 is used for Local pickup 2 and lines 132-182 are for SmartPost shipping method.

In a similar way you can add (or remove) your own additional shipping methods.

/* CSS classes for hiding fields
.hide_local {
    display: none !important;
}
.hide_local2 {
    display: none !important;
}
.hide_smartpost {
    display: none !important;
}

AVAILABLE BILLING FIELDS
billing_company = COMPANY
billing_country = COUNTRY
billing_postcode = POSTCODE
billing_address_1 = ADDRESS 1
billing_address_2 = ADDRESS 2
billing_city = CITY
billing_last_name = LAST NAME
billing_first_name = FIRST NAME
billing_phone = PHONE
billing_state = STATE
*/


// Hide local pickup fields
add_filter( 'woocommerce_checkout_fields', 'wpsh_hide_local_pickup_fields' );
function wpsh_hide_local_pickup_fields( $fields_itella ) {
    
  // Add your own shipping method ID
    $shipping_method_itella ='local_pickup:2'; 
  
    // change below for the list of fields
    $hide_fields_itella = array( 'billing_company', 'billing_country', 'billing_postcode', 'billing_address_1', 'billing_address_2' , 'billing_city' );

    $chosen_methods_itella = WC()->session->get( 'chosen_shipping_methods' );
    // uncomment below line and reload checkout page to check current $chosen_methods
    // print_r($chosen_methods);
    $chosen_shipping_itella = $chosen_methods_itella[0];

    foreach($hide_fields_itella as $field_itella ) {
        if ($chosen_shipping_itella == $shipping_method_itella) {
            $fields_itella['billing'][$field_itella]['required'] = false;
            $fields_itella['billing'][$field_itella]['class'][] = 'hide_local';
        }
        $fields_itella['billing'][$field_itella]['class'][] = 'billing-dynamic_itella';
    }
    return $fields_itella;
}

// Local pickup Ajax

add_action( 'wp_head', 'wpsh_local_pickup_ajax', 999 );
function wpsh_local_pickup_ajax() {
    if (is_checkout()) :
    ?>
    <style>
        .hide_local {display: none!important;}
    </style>
    <script>
        jQuery( function( $ ) {

            // woocommerce_params is required to continue, ensure the object exists
            if ( typeof woocommerce_params === 'undefined' ) {
                return false;
            }

            $(document).on( 'change', '#shipping_method input[type="radio"]', function() {
			  
               // Add your own shipping method ID
            $('.billing-dynamic_itella').toggleClass('hide_local', this.value == 'local_pickup:2');  
            });
        });
    </script>
    <?php
    endif;
}

// // Hide local pickup 2 fields

add_filter( 'woocommerce_checkout_fields', 'wpsh_hide_local_pickup2_fields' );
function wpsh_hide_local_pickup2_fields( $fields_omniva ) {
  
// Add your own shipping method ID
    $shipping_method_omniva ='local_pickup:8'; 
  
    // change below for the list of fields
    $hide_fields_omniva = array( 'billing_company', 'billing_country', 'billing_postcode', 'billing_address_1', 'billing_address_2' , 'billing_city' );

    $chosen_methods_omniva = WC()->session->get( 'chosen_shipping_methods' );
    // uncomment below line and reload checkout page to check current $chosen_methods
    // print_r($chosen_methods);
    $chosen_shipping_omniva = $chosen_methods_omniva[0];

    foreach($hide_fields_omniva as $field_omniva ) {
        if ($chosen_shipping_omniva == $shipping_method_omniva) {
            $fields_omniva['billing'][$field_omniva]['required'] = false;
            $fields_omniva['billing'][$field_omniva]['class'][] = 'hide_local';
        }
        $fields_omniva['billing'][$field_omniva]['class'][] = 'billing-dynamic_omniva';
    }

    return $fields_omniva;
}

// Local pickup 2 Ajax
add_action( 'wp_head', 'wpsh_hide_local_pickup2_ajax', 999 );
function wpsh_hide_local_pickup2_ajax() {
    if (is_checkout()) :
    ?>
    <style>
        .hide_local2 {display: none!important;}
    </style>
    <script>
        jQuery( function( $ ) {

            // woocommerce_params is required to continue, ensure the object exists
            if ( typeof woocommerce_params === 'undefined' ) {
                return false;
            }

            $(document).on( 'change', '#shipping_method input[type="radio"]', function() {
			  
                // Add your own shipping method ID
            $('.billing-dynamic_omniva').toggleClass('hide_local2', this.value == 'local_pickup:8');   
            });
        });
    </script>
    <?php
    endif;
}

// Hide SmartPost fields
add_filter( 'woocommerce_checkout_fields', 'wpsh_hide_smartpost_fields' );
function wpsh_hide_smartpost_fields( $fields_pickup ) {
  
   // Add your own shipping method ID
    $shipping_method_pickup ='multiparcels_smartpost_pickup_point:7'; 
  
    // change below for the list of fields
    $hide_fields_pickup = array( 'billing_company', 'billing_country', 'billing_postcode', 'billing_address_1', 'billing_address_2' , 'billing_city', 'billing_phone' );

    $chosen_methods_pickup = WC()->session->get( 'chosen_shipping_methods' );
    // uncomment below line and reload checkout page to check current $chosen_methods
    // print_r($chosen_methods);
    $chosen_shipping_pickup = $chosen_methods_pickup[0];

    foreach($hide_fields_pickup as $field_pickup ) {
        if ($chosen_shipping_pickup == $shipping_method_pickup) {
            $fields_pickup['billing'][$field_pickup]['required'] = false;
            $fields_pickup['billing'][$field_pickup]['class'][] = 'hide_smartpost';
        }
        $fields_pickup['billing'][$field_pickup]['class'][] = 'billing-dynamic_pickup';
    }

    return $fields_pickup;
}
// Samrtpost Ajax
add_action( 'wp_head', 'wpsh_hide_smartpost_fields_ajax', 999 );
function wpsh_hide_smartpost_fields_ajax() {
    if (is_checkout()) :
    ?>
    <style>
        .hide_smartpost {display: none!important;}
    </style>
    <script>
        jQuery( function( $ ) {

            // woocommerce_params is required to continue, ensure the object exists
            if ( typeof woocommerce_params === 'undefined' ) {
                return false;
            }

            $(document).on( 'change', '#shipping_method input[type="radio"]', function() {
			  
               // Add your own shipping method ID
            $('.billing-dynamic_pickup').toggleClass('hide_smartpost', this.value == 'multiparcels_smartpost_pickup_point:7'); 
            });
        });
    </script>
    <?php
    endif;
}

How to display Woocommerce store address for Local pickup shipping method?

The first thing you need to do is you need to find out your Local pickup ID number.

If you don’t know how to do that then go to Woocommerce >> Settings >> Shipping >> Open your shipping zone.

Now hover on the Local pickup method and see the link. It is something like this:
https://yoursite.com/wp-admin/admin.php?page=wc-settings&tab=shipping&instance_id=2

See the ID=2, this is your shipping method ID.

Now add this piece of CSS inside Appearace >> Customizer >> Additional CSS code box.

#shipping_method_0_local_pickup2:checked + label[for=shipping_method_0_local_pickup2]::after {
    display: block;
    content: "London, Buckingham palace";
	color: red;
	font-weight: 600;
}

How to hide all shipping rates when free shipping is available, but keep “Local pickup?

Let’s tweak this solution I showed in previous chapten and hide all shipping rates when free shipping is available, but keep “Local pickup” method.

// Hide all shipping rates when free shipping is available, but keep "Local pickup" method
function wpsh_hide_free_keep_local( $rates, $package ) {
	$new_rates = array();
	foreach ( $rates as $rate_id => $rate ) {
		// Only modify rates if free_shipping is present.
		if ( 'free_shipping' === $rate->method_id ) {
			$new_rates[ $rate_id ] = $rate;
			break;
		}
	}
	if ( ! empty( $new_rates ) ) {
		//Save local pickup if it's present.
		foreach ( $rates as $rate_id => $rate ) {
			if ('local_pickup' === $rate->method_id ) {
				$new_rates[ $rate_id ] = $rate;
				break;
			}
		}
		return $new_rates;
	}
	return $rates;
}
add_filter( 'woocommerce_package_rates', 'wpsh_hide_free_keep_local', 10, 2 );

How to add Custom Woocommerce Checkout Message?

Now let’s take a look how to customize Woocommerce checkout page with the custom message.

This snippet here below adds custom Woocommerce checkout message on top of the checkout page. Just replace the message content (“Estimated delivery time: 2 weeks”) accordingly.

// Add Custom Woocommerce Checkout Message
add_action( 'woocommerce_before_checkout_form', 'shop_message', 20 );
function shop_message() {
echo '<p class="woocommerce-message">Estimated delivery time: 2 weeks</p>'; // Replace your message here
}

How to Give a Discount if Woocommerce Local Pickup shipping method is selected?

There are two main reasons why you should consider giving a discount for those who select Local pickup as their shipping method.

  1. You have a small shop and therefore you have no time to hassle with the shipments all the time. Therefore, it would be much easier for you if the customer would come to the shop to pick the product up. Because…
  2. …this way you can offer the customer up-sells, cross-sells etc. It is a handy method to make your customer to visit your shop.

So, to motivate your customers to choose a local pickup shipping method you may want to consider give them a small discount.

// Give a 15% Discount if Woocommerce Local Pickup shipping method is selected
function local_pickup_discount( $cart ) {
  $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
  $chosen_shipping_no_ajax = $chosen_methods[0];
  if ( 0 === strpos( $chosen_shipping_no_ajax, 'local_pickup' ) ) {
    $discount = $cart->subtotal * 0.15; // Set your percentage. This here gives 15% discount
    $cart->add_fee( __( 'Discount added', 'yourtext-domain' ) , -$discount ); // Change the text if needed
  }
}
add_action( 'woocommerce_cart_calculate_fees', 'local_pickup_discount');

How to move Woocommerce email to top at checkout page?

// Move Woocommerce email to top at checkout page
add_filter( 'woocommerce_checkout_fields', 'move_email_field_to_top' );

function move_email_field_to_top( $checkout_fields ) {
	$checkout_fields['billing']['billing_email']['priority'] = 4;
	return $checkout_fields;
}

How to remove Woocommerce checkout fields?

Here below are all the fields you can remove.

// Remove checkout fields
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );

function custom_override_checkout_fields( $fields ) {
 // remove billing fields
    unset($fields['billing']['billing_first_name']); // Billing First name
    unset($fields['billing']['billing_last_name']); // Billing Last name
    unset($fields['billing']['billing_company']); // Billing company
    unset($fields['billing']['billing_address_1']); // Billing Address 1
    unset($fields['billing']['billing_address_2']); // Billing Address 2
    unset($fields['billing']['billing_city']); // Billing city
    unset($fields['billing']['billing_postcode']); // Billing postcode
    unset($fields['billing']['billing_country']); // Billing country
    unset($fields['billing']['billing_state']); // Billing state
    unset($fields['billing']['billing_phone']); // Billing phone
    unset($fields['billing']['billing_email']); // Billing email
   
    // remove shipping fields 
    unset($fields['shipping']['shipping_first_name']); // Shipping first name  
    unset($fields['shipping']['shipping_last_name']); // Shipping last name  
    unset($fields['shipping']['shipping_company']); // Shipping company  
    unset($fields['shipping']['shipping_address_1']); // Shipping address 1
    unset($fields['shipping']['shipping_address_2']); // Shipping address 2
    unset($fields['shipping']['shipping_city']); // Shipping city 
    unset($fields['shipping']['shipping_postcode']); // Shipping postcode
    unset($fields['shipping']['shipping_country']); // Shipping country
    unset($fields['shipping']['shipping_state']); // Shipping state
    
    // remove order comment fields
    unset($fields['order']['order_comments']); // Order comments
     return $fields;
}

You don’t have to paste all of them, instead use only these you need. For example, if you need to remove billing address 2, state and company fields then use this code here below.

// Remove checkout fields
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );

function custom_override_checkout_fields( $fields ) {
 // remove billing fields

    unset($fields['billing']['billing_company']); // Billing company
    unset($fields['billing']['billing_address_2']); // Billing Address 2
    unset($fields['billing']['billing_state']); // Billing state
   
     return $fields;
}

How to make Woocommerce checkout fields optional?

Pay attention that “true” =required and if you want the field to be optional then set it to “false”.

add_filter( 'woocommerce_default_address_fields' , 'optional_default_address_fields' );
 function optional_default_address_fields( $address_fields ) {
 	$address_fields['first_name']['required'] = true;	 
 	$address_fields['last_name']['required'] = true;
 	$address_fields['company']['required'] = false;
	$address_fields['address_1']['required'] = true;
	$address_fields['address_2']['required'] = false;
	$address_fields['country']['required'] = false;
 	$address_fields['postcode']['required'] = false;
 	$address_fields['city']['required'] = false;
 	$address_fields['state']['required'] = false;
 return $address_fields;
 }
// For billing email and phone fields
add_filter('woocommerce_billing_fields', 'optional_checkout_fields1', 1000, 1);
function optional_checkout_fields1( $fields ) {
    $fields['billing_email']['required'] = true;
    $fields['billing_phone']['required'] = false;
    return $fields;
}

And once more, if you need a only couple of fields to be optional then just paste the lines you need. For example, this snippet makes country and phone fields optional.

add_filter( 'woocommerce_default_address_fields' , 'optional_default_address_fields' );
 function optional_default_address_fields( $address_fields ) {
	$address_fields['country']['required'] = false;
 return $address_fields;
 }

// For billing email and phone fields
add_filter('woocommerce_billing_fields', 'optional_checkout_fields1', 1000, 1);
function optional_checkout_fields1( $fields ) {
    $fields['billing_phone']['required'] = false;
    return $fields;
}

How to add custom fields in Woocommerce checkout page?

This snipepts allows you to add custom fields in Woocommerce checkout page withut any plugin. It will add three text fields (Home, Entrance and Floor) in the billing section. Just rename the field names and placehodler text if needed and you’re good to go.

All the date will be added to the emails on order tables and what is especially good, is that all the data is editable. If you don’t need three fields then just remove the ones you don’t need from the code.

// Frontend: Display the custom billing fields (in checkout and my account)
add_filter( 'woocommerce_billing_fields' ,'add_custom_billing_fields', 20, 1 );
function add_custom_billing_fields( $fields ) {

    $fields['billing_address_3'] = array(
        'label' => __( 'Home', 'woocommerce' ),
        'placeholder'   => _x('Fill in your Home', 'placeholder', 'woocommerce'),
        'required'  => true,
        'class'     => array('form-row-wide'),
        'clear'     => true
    );

    $fields['billing_address_4'] = array(
        'label' => __( 'Entrance', 'woocommerce' ),
        'placeholder'   => _x('Fill in your Entrance', 'placeholder', 'woocommerce'),
        'required'  => true,
        'class'     => array('form-row-wide'),
        'clear'     => true
    );

    $fields['billing_address_5'] = array(
        'label' => __( 'Floor', 'woocommerce' ),
        'placeholder'   => _x('Fill in your Floor', 'placeholder', 'woocommerce'),
        'required'  => true,
        'class'     => array('form-row-wide'),
        'clear'     => true
    );

    return $fields;
}

// Save the custom billing fields (once order is placed)
add_action( 'woocommerce_checkout_create_order', 'save_custom_billingt_fields', 20, 2 );
function save_custom_billingt_fields( $order, $data ) {
    if ( isset( $_POST['billing_address_3'] ) && ! empty( $_POST['billing_address_3'] ) ) {
        $order->update_meta_data('_billing_address_3', sanitize_text_field( $_POST['billing_address_3'] ) );
        update_user_meta( $order->get_customer_id(), 'billing_address_3', sanitize_text_field( $_POST['billing_address_3'] ) );
    }
    if ( isset( $_POST['billing_address_4'] ) && ! empty( $_POST['billing_address_4'] ) ) {
        $order->update_meta_data('_billing_address_4', sanitize_text_field( $_POST['billing_address_4'] ) );
        update_user_meta( $order->get_customer_id(), 'billing_address_4', sanitize_text_field( $_POST['billing_address_4'] ) );
    }
    if ( isset( $_POST['billing_address_5'] ) && ! empty( $_POST['billing_address_5'] ) ) {
        $order->update_meta_data('_billing_address_5', sanitize_text_field( $_POST['billing_address_5'] ) );
        update_user_meta( $order->get_customer_id(), 'billing_address_5', sanitize_text_field( $_POST['billing_address_5'] ) );
    }
}

// Display in emails
add_action( 'woocommerce_email_after_order_table', 'display_new_checkout_fields_in_emails', 20, 4 );
function display_new_checkout_fields_in_emails( $order, $sent_to_admin, $plain_text, $email ) {
    if ( get_post_meta( $order->get_id(), 
	'_billing_address_3', true ) ) 
	  echo '<p><strong>Home:</strong> ' 
	  . get_post_meta( $order->get_id(), '_billing_address_3', true ) . '</p>';
  
   if ( get_post_meta( $order->get_id(), 
	'_billing_address_4', true ) ) echo '<p><strong>Entrance:</strong> ' 
	 . get_post_meta( $order->get_id(), '_billing_address_4', true ) . '</p>';
  
     if ( get_post_meta( $order->get_id(), 
	'_billing_address_5', true ) ) echo '<p><strong>Floor:</strong> ' 
	 . get_post_meta( $order->get_id(), '_billing_address_5', true ) . '</p>';
}

// Backend: Display editable custom billing fields
add_filter( 'woocommerce_admin_billing_fields' , 'order_admin_custom_fields' );
function order_admin_custom_fields( $fields ) {
    global $the_order;

    $fields['address_3'] = array(
        'label' => __( 'Home', 'woocommerce' ),
        'show'  => true,
        'wrapper_class' => 'form-field-wide',
        'style' => '',
    );

    $fields['address_4'] = array(
        'label' => __( 'Entrance', 'woocommerce' ),
        'show'  => true,
        'wrapper_class' => 'form-field-wide',
        'style' => '',
    );

    $fields['address_5'] = array(
        'label' => __( 'Floor', 'woocommerce' ),
        'show'  => true,
        'wrapper_class' => 'form-field-wide',
        'style' => '',
    );

    return $fields;
}

How to disable all Woocommerce payment gateways?

The reason you would need to disable all payment gateways is that maybe you need it just for some catalogue or ordering system. Hence, use this small piece of code.

// Disable all Woocommerce payment gateways
add_filter( 'woocommerce_cart_needs_payment', '__return_false' );

And this is the result.

How to Display Woocommerce Payment Methods Conditionally?

How to Disable Woocommerce payment gateways for specific user roles?

Let’s imagine that your shop has a bunch of user roles. For example, customer, Gold member, Silver package etc. This snippet here allows you to disable Woocommerce payment gateways for specific user roles.

Pay attention to line 8 for user role and lines 11-15 for payment gateways to be removed. In this example customer can use onluy BACS and all other gateways are removed.

// Disable Woocommerce payment gateways for specific user roles
add_filter('woocommerce_available_payment_gateways', 'wpsh_hide_payment_roles', 1);
  function wpsh_hide_payment_roles($gateways)
  {
      $current_user = wp_get_current_user();
      $role = $current_user->roles;
      global $woocommerce;
      // Here goes your user role
      if ($role[0] == 'customer') {
		  
		// Add payment gateways you need to disable. In this example only BACS is activated
        unset($gateways['cheque']); // Cheque
		unset($gateways['cod']); // Cash on delivery
		unset($gateways['paypal']); // Paypal
	//	unset($gateways['bacs']); // Direct bank transfer (BACS)
      }
      return $gateways;
  }

How to Disable Woocommerce payment gateways for specific user roles (alternative method)?

If for some reason previous method didn’t work out for you then use this snippet here below.

// Disable Woocommerce payment gateways for specific user roles
add_filter( 'woocommerce_available_payment_gateways', 'wpsh_disable:payment_for_roles' ); 
function wpsh_disable:payment_for_roles( $available_gateways ) {
	/* Here goes your user role */
	if( current_user_can( 'customer' ) ) {
	/* Here goes your payment gateway */
		if ( isset( $available_gateways[ 'paypal' ] ) ) {
			unset( $available_gateways[ 'paypal' ] );
		}
		/* If you don’t need to dsable more than one gateways, then delete next three rows. 
		If you need to add more gateways then just copy next three rows and replace your gateway name. */
	        if ( isset( $available_gateways[ 'bacs' ] ) ) {
			unset( $available_gateways[ 'bacs' ] );
		}
	}

	return $available_gateways;
}

How to Disable Woocommerce payment gateways for logged-out users?

Sometimes, if you would like to display WooCommerce payment methods conditionally, you need to set up some rules for your logged-out users.

For example, I have a customer who needed to hide direct bank payments (BACS) for logged-out users. So, if you need to disable some specific Woocommerce payment gateway for logged-out users then this snippet here helps you out.

Once again, pay attention to line 7 which defines roles that are allowed to use gateways. Other roles have no access to these gateways. In this example customer and administrator roles can use BACS and Check payments, all other user roles do not.

// Disable Woocommerce payment gateways for logged-out users
add_filter('woocommerce_available_payment_gateways', 'wpsh_disable_payment_for_logged_out_users', 90, 1); 
function wpsh_disable_payment_for_logged_out_users( $available_payment_gateways ) {
$user = wp_get_current_user();
  
	// Define roles that are allowed to use gateways. Other roles have no access to these gateways.
	$allowed_roles = array('customer', 'administrator');

	if (!array_intersect($allowed_roles, $user->roles )) {

	if (isset($available_payment_gateways['bacs'])) {
	unset($available_payment_gateways['bacs']);
	}
	if (isset($available_payment_gateways['cheque'])) {
unset($available_payment_gateways['cheque']);
		}
	}
	return $available_payment_gateways;
}

How to disable Woocommerce payment methods for a specific country?

Why would you need to disable Woocommerce payment methods for a specific country? Well, if my shop is in Europe, and you’re in USA then I don’t see any point to using Cash on delivery (COD) payment method.

Therefore, in this example, I will remove COD for USA (see line 12-15). Also, I will remove Paypal and Check payments for Estonia, Finland and Norway (see lines 19-24).

// Disable Woocommerce payment methods for a specific country

add_filter( 'woocommerce_available_payment_gateways', 'wpsh_hide_payment_for_countries', 10, 1 );

function wpsh_hide_payment_for_countries( $payment_gateways ) {
    if ( is_admin() ) return $payment_gateways;
	
    // Get country
    $customer_country = WC()->customer->get_shipping_country() ? WC()->customer->get_shipping_country() : WC()->customer->get_billing_country();
    
    // Hide COD for USA
    if ( in_array( $customer_country, array( 'US' ) ) ) {       
        // Hide Cash on delivery for United States
        if ( isset( $payment_gateways['cod'] ) ) {
            unset( $payment_gateways['cod'] );
        }
    } 
	 // Hide Paypal and Cheque payments for Estonia, Finland and Norway
	    if ( in_array( $customer_country, array( 'EE', 'FI', 'NO' ) ) ) {       
        if ( isset( $payment_gateways['paypal'] ) ) {
            unset( $payment_gateways['paypal'] );
        }
			if ( isset( $payment_gateways['cheque'] ) ) {
            unset( $payment_gateways['cheque'] );
        }
    } 
    return $payment_gateways;
}

How to add Payment Gateway Based Fees in Woocommerce?

Next part of our “How to display WooCommerce payment methods conditionally?” post is here. That means, I’ll show you how to add Payment Gateway Based Fees in Woocommerce. For example, let’s add two kinds of fees with the help of this code:

  • Fixed fee (2 euros) for using Cash on delivery fee (see line 15)
  • Percentage fee (5%) for using Paypal (see line 16).

Just add your own fees and payment methods, and you’re good to go.

How to add Payment Gateway Based Fees in Woocommerce?
// Add Payment Gateway Based Fees in Woocommerce
add_action( 'woocommerce_cart_calculate_fees', 'wpsh_add_handling_fee' );
function wpsh_add_handling_fee ( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;
    $chosen_payment_id = WC()->session->get('chosen_payment_method');

    if ( empty( $chosen_payment_id ) )
        return;

    $subtotal = $cart->subtotal;

    // Here you can set up your fees (fixed or percentage)
    $targeted_payment_ids = array(
        'cod' => 2, // Fixed fee
        'paypal' => 5 * $subtotal / 100, // Percentage fee
    );

    // Loop through defined payment Ids array
    foreach ( $targeted_payment_ids as $payment_id => $fee_cost ) {
        if ( $chosen_payment_id === $payment_id ) {
            $cart->add_fee( __('Handling fee', 'woocommerce'), $fee_cost, true );
        }
    }
}
// Update checkout on payment method change
add_action( 'woocommerce_checkout_init', 'wpsh_refresh_checkout_page' );
function wpsh_refresh_checkout_page() {
    wc_enqueue_js( "jQuery( function($){
        $('form.checkout').on('change', 'input[name=payment_method]', function(){
            $(document.body).trigger('update_checkout');
        });
    });");
}

How to add custom endpoints in Woocommerce?

Now, some explanations for the code below:

  • Take a look at the comments inside the code
  • You need to change your endpoint slug and title accordingly (see lines 8, 18 and 46)
  • Line 23 contains woocommerce_account_support_endpoint and you need to change it accordingly. That is, if your endpoint slug is your-courses then this line should look woocommerce_account_your-courses_endpoint
  • After saving and activating your snippet you need to go to Settings > Permalinks and just push “Save Changes” button. Otherwise you end up with “Oops, that page cannot be found” error
// Add new tab to My Account menu

add_filter ( 'woocommerce_account_menu_items', 'wpsh_custom_endpoint', 40 );
function wpsh_custom_endpoint( $menu_links ){
 
	$menu_links = array_slice( $menu_links, 0, 5, true ) 
		// Add your own slug (support, for example) and tab title here below
	+ array( 'support' => 'Support' ) 
	+ array_slice( $menu_links, 5, NULL, true );
 
	return $menu_links;
 
}
// Let’s register this new endpoint permalink

add_action( 'init', 'wpsh_new_endpoint' );
function wpsh_new_endpoint() {
	add_rewrite_endpoint( 'support', EP_PAGES ); // Don’t forget to change the slug here
}

// Now let’s add some content inside your endpoint

add_action( 'woocommerce_account_support_endpoint', 'wpsh_endpoint_content' );
function wpsh_endpoint_content() {
 
	// At the moment I will add Learndash profile with the shordcode
	echo (
		'<h3>Send us an email</h3>
	<p>Lorem ipsum dolor sit amet consectetur adipiscing elit facilisis tincidunt, nisi sociosqu lacinia auctor inceptos libero conubia accumsan</p>'
		 );
	echo do_shortcode('');
}

// NB! In order to make it work you need to go to Settings > Permalinks and just push "Save Changes" button.

// If you need to change endpoint order then add your own order here

add_filter ( 'woocommerce_account_menu_items', 'wpsh_custom_endpoint_order' );
function wpsh_custom_endpoint_order() {
 $myorder = array(
        'dashboard'          => __( 'Dashboard', 'woocommerce' ),
        'orders'             => __( 'Your orders', 'woocommerce' ), 
        'edit-account'       => __( 'Account details', 'woocommerce' ),
	 	'edit-address'       => __( 'Edit address', 'woocommerce' ),
	 	'woo-wish-list'       => __( 'Wishlist', 'woocommerce' ),
	 	'support'    => __( 'Support', 'woocommerce' ), // Don’t forget to change the slug and title here
        'customer-logout'    => __( 'Log out', 'woocommerce' ),
    );
    return $myorder;
}

How to display products name and quantity in a new column on Woocommerce “My account” page orders table?

Take a look at the “How to add “Cancel” button to Woocommerce my account page?” section above. There’s a screenshot and you’ll see that in it I display products name and quantity in a new column on Woocommerce “My account” page orders table. So, if you would like to accomplish the same result, just use this snippet here below.

// Display How to display products name and quantity in a new column on Woocommerce "My account" page orders table

add_filter( 'woocommerce_my_account_my_orders_columns', 'wpsh_product_column', 10, 1 );
function wpsh_product_column( $columns ) {
    $new_columns = [];

    foreach ( $columns as $key => $name ) {
        $new_columns[ $key ] = $name;

        if ( 'order-status' === $key ) {
            $new_columns['order-items'] = __( 'Product | Qty', 'woocommerce' );
        }
    }
    return $new_columns;
}

add_action( 'woocommerce_my_account_my_orders_column_order-items', 'wpsh_product_column_content', 10, 1 );
function wpsh_product_column_content( $order ) {
    $details = array();

    foreach( $order->get_items() as $item )
        $details[] = $item->get_name() . ' × ' . $item->get_quantity();

    echo count( $details ) > 0 ? implode( '<br>', $details ) : '–';
}

Here are some of my favorite Wordpress tools

Thank you for reading this article. I hope you found it helpful as you build your own websites and e-commerce sites. Here are some tools I use as a Wordpress developer and enthusiast that I hope you’ll also find helpful.

These are affiliate links, so if you do decide to use any of them, I’ll earn a commission and this helps me create these tutorials and make Youtube videos. But in all honesty, these are the exact tools that I use and recommend to everyone, even my friends and family.

Themes: For the last couple of years I have two go-to themes which I use for every kind of projects. Those two themes are Blocksy theme and Kadence Theme. On this site and my Youtube channel you’ll see a lot of tutorials I have made about them. If you would like to get a 10% discount for both of them then:

Code Snippets manager: WPCodeBox allows you to add code snippets to your site. Also, it allows you to build and manage your WordPress Code Snippets library in the cloud. You can grab it with the 20% discount here (SAVE 20% Coupon: WPSH20).

Contact forms: There are hundreds of contact forms out there but Fluent Forms is the one I like the most. If you need a 20% discount then use this link (save 20% coupon is WPSH20).

Gutenberg add-ons: If I need a good Gutenberg blocks add-on then Kadence Blocks is the one I have used the most. You’ll get 10% discount with the coupon SIMPLEHACKS here.

Website migration: While building a website you probably need a good plugin that can help you with the migration, backups, restoration and staging sites. Well, WpVivid is the one I have used for the last couple of years. If you use this link along with the WPSH20 coupon you’ll get 20% discount.

Woocommerce extensions: There are a bunch of Woocommerce extensions that I really like but the one that stands really out is Advanced Dynamic Pricing. Once again, you’ll get a 20% discount if you use this link here (save 20% coupon is WPSH20)

Web Hosting: If you would like to have a really fast and easy to use managed cloud hosting, then I recommend Verpex Hosting (see my review here). Btw, this site is hosted in Verpex.)

To see all my of most up-to-date recommendations, check out this resource that I made for you!

Do you want to thank me and buy me a beer?

Every donation is entirely welcome but NEVER required. Enjoy my work for free but if you would like to thank me and buy me a beer or two then you can use this form here below.

Choose amount

Best selling plugins

Janek T.
Janek T.

I am a Wordpress enthusiast who has been making websites since 2011. In this site I am offering simple to follow tips on how to use Wordpress and Woocommerce.
If you want to be the first to be notified about the new tutorials then please subscribe to my Youtube channel here
Follow me in Twitter here

Articles: 95