Shipping Method for WooCommerce Development Tutorial

  1. Home
  2. /
  3. Coding
  4. /
  5. Shipping Method for WooCommerce Development Tutorial

Recently, I was learning about WooCommerce development, The problem which I found during that period is the lack of tutorials. What I really don’t appreciate about WooCommerce is its documentation. It’s not that bad, but sometimes it’s a little vague and you can’t manage to completely understand what is going on.

When I started developing Australia Post Shipping Method, I found out that I have to read the code of other shipping methods in order to get all the things right.

Today, I will explain how to develop a simple shipping method for WooCommerce step by step and I will make the plugin files available for download.

What is WooCommerce Extension?

WooCommerce extension is simply an ordinary WordPress plugin, The only difference is WooCommerce extension is built to extend the functionality of WooCommerce. For example, it could be a payment gateway or a shipping method. Also, it could add new features to WooCommerce such as invoicing, checkout page customizations, login with facebook …etc

What are we trying to achieve?

Let’s assume that there is a company called “Fast Delivery Inc.”, Fast Delivery depends on the weight and the dimensions of the package to calculate the shipping rates. The following table is explaining exactly how the rates are calculated.

Weight Dimensions ( WxHxL ) Cost
Less than 1Kg Less than 1000 cube cm 3$
Less than 1Kg More than 1000 cube cm 4$
1-3 kg Less than 3000 cube cm 10$
3-10 kg Less than 5000 cube cm 25$
3-10 kg More than 5000 cube cm 50$
More than 10kg Any Dimension Not Available


In real life, the calculations are much more complex, and many factors get involved with it, especially the destination. But for the sake of simplicity, we will stick with that table.

As you see in the table, Fast Delivery does not support packages that weight more than 10kg, so our shipping method won’t be available for products that weigh more than 10kg.


Create the main file of the shipping method

Ok, let’s start the real deal and write some code. The first thing we have to do is to create a new folder in the “plugin” folder, let’s name it woocommerce-fast-delivery-shipping-method”. Inside this folder create a new PHP file and name it “fast-delivery-shipping-method.php”.  This file will be the main file of the plugin, that’s where we have to put the WordPress plugin header.

Plugin Name: WooCommerce Fast Delivery Shipping Method
Plugin URI:
Description: WooCommerce calculator for Fast Delivery Inc.
Version: 1.0.0
Author: Waseem Senjer
Author URI:

I’m assuming that you have an experience in WordPress plugins development, so this header should be familiar to you.

[alert_box style=”info” close=”no” ]It’s always preferable to start the name of WooCommerce extensions with “woocommerce” prefix, that will give a straight idea to the user or other developers that this plugin is a WooCommerce extension.[/alert_box]

Ask if WooCommerce is installed and activated

Now, we must ask if WooCommerce is installed and activated on the website because if it’s not, then our plugin is useless. Furthermore, it will generate a lot of errors if WooCommerce is not activated. This is how we do that.

 * Check if WooCommerce is active
$active_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ) );
if ( in_array( 'woocommerce/woocommerce.php',  $active_plugins) ) {

  // The rest of our plugin's code goes here.

First, we need to get a list of the currently activated plugins, WordPress saves a list of the activated plugins in the database via the Options API, They use the key “active_plugins”, so we simply get this list by

get_option( 'active_plugins' );

This line will return an array of strings with this format “{plugin_folder_name}/{main_plugin_file}.php” , then if we want to check if WooCommerce whether installed or not, we need to search the array for “woocommerce/woocommerce.php”, “woocommerce” is the folder of WooCommerce in the plugins folder, and “woocommerce.php” is the main WooCommerce plugin file. We searched the array using a PHP function “in_array”. If this function returned true, then we will write our plugin code into the “if” block.

Add your shipping method to the default methods of WooCommerce

After we made sure that WooCommerce is activated, we will start writing the core code of our plugin, We will add our shipping method to the default WooCommerce shipping methods by using the filter “woocommerce_shipping_methods” which is provided by WooCommerce.

add_filter( 'woocommerce_shipping_methods', 'add_fast_delivery_shipping_method' );
  function add_fast_delivery_shipping_method( $methods ) {
    $methods[] = 'WC_Fast_Delivery_Shipping_Method';
    return $methods;

This filter takes the default shipping methods array as a parameter, we will add our own shipping method by adding a new element to that array which is the class name of our shipping method (We will write this class next). Finally, do not forget to return the modified array.


Include the shipping method class

The last remaining thing to do in the main file of the plugin is to include the class file of the shipping method. We will use a WooCommerce action hook called “woocommerce_shipping_init”, This action will be executed when WooCommerce actually needs to call the shipping methods.

add_action( 'woocommerce_shipping_init', 'fast_delivery_shipping_method_init' );

function fast_delivery_shipping_method_init(){
   require_once 'class-fast-delivery-shipping-method.php';

Now the main file of our plugin looks like this:

Plugin Name: WooCommerce Fast Delivery Shipping Method
Plugin URI:
Description: WooCommerce calculator for Fast Delivery Inc.
Version: 1.0.0
Author: Waseem Senjer
Author URI:

 * Check if WooCommerce is active
$active_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ) );
if ( in_array( 'woocommerce/woocommerce.php', $active_plugins) ) {

 add_filter( 'woocommerce_shipping_methods', 'add_fast_delivery_shipping_method' );
 function add_fast_delivery_shipping_method( $methods ) {
   $methods[] = 'WC_Fast_Delivery_Shipping_Method';
   return $methods;

 add_action( 'woocommerce_shipping_init', 'fast_delivery_shipping_method_init' );
 function fast_delivery_shipping_method_init(){
   require_once 'class-fast-delivery-shipping-method.php';


The Shipping Method Class

The main code in any shipping method is its class, let’s create a file and name it “class-fast-delivery-shipping-method.php”. Open this file and write the following:

class WC_Fast_Delivery_Shipping_Method extends WC_Shipping_Method{


You should give an attention to two things. First, The class name must match the name that we gave it to the “woocommerce_shipping_methods” filter in the main file of the plugin. Second, The class file name should also match the file name that we required in the “woocommerce_shipping_init” action.

The class must extend the “WC_Shipping_Method” class which is an abstract class provided by WooCommerce to implement the shipping method functionalities.

These are the minimum methods that you have to implement in order to the shipping method to work properly.

class WC_Fast_Delivery_Shipping_Method extends WC_Shipping_Method{

  public function __construct(){}
  public function init_form_fields(){}
  public function is_available( $package ){}
  public function calculate_shipping($package){}


The constructor

The first thing to start with is the constructor. In the constructor, we will write some lines of codes to initialize the shipping method.

public function __construct(){

  $this->id = 'fast_delivery_shipping_method';
  $this->method_title = __( 'Fast Delivery Shipping Method', 'woocommerce' );

  // Load the settings.

  // Define user set variables
  $this->enabled	= $this->get_option( 'enabled' );
  $this->title 		= $this->get_option( 'title' );
  add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );


Let’s divide the code and walk through it.

$this->id = 'fast_delivery_shipping_method';

This is a unique id that we give it to our shipping method, it will work as a reference to the shipping method.

$this->method_title = __( 'Fast Delivery Shipping Method', 'woocommerce' );

This is the method title which will appear to the admin in the Dashboard.


Here, we call “init_form_fields()” which we will implement it later, This method is responsible for creating the settings fields for the admin. I will explain it later.


This method is inherited from the Settings API class of WooCommerce which it gets inherited by WC_Shipping_Method class. It’s mainly responsible for retrieving the settings values from the database and load them into the settings field in the settings page of the shipping method settings page.

$this->enabled = $this->get_option( 'enabled' );

I’m getting the value of “enabled”, this attribute is inherited from the abstract class, and it stores whether the shipping method is enabled or disabled by the admin.

$this->title = $this->get_option( 'title' );

This is also an inherited attribute from the abstract class, The “title” stores the title of the shipping method which will appear to the visitor on the checkout page.

add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );

The last line is very important, it’s responsible for processing the admin options of the shipping method and saves them in the database. We add an action hook “woocommerce_update_options_shipping_” and appending the shipping method id. Then, “process_admin_options” will be called when the admin clicks on “Save Changes” button, this method is also inherited from the Settings API class of WooCommerce.

Settings Fields

As I said in the constructor part, we have to implement the “init_form_fields” method. This method uses the Settings API of WooCommerce.  Here we set the fields that we want to provide to the admin so he can control the shipping method. As you see in the implementation below, I assigned an associative array to the attribute “form_fields”, This attribute is coming from the Settings API class, The array represents the form fields of the admin page of the shipping method. Please, read about the possible options for this array in Settings API of WooCommerce documentation, it’s short and useful.

public function init_form_fields() {

  $this->form_fields = array(
    'enabled' => array(
      'title' 		=> __( 'Enable/Disable', 'woocommerce' ),
      'type' 			=> 'checkbox',
      'label' 		=> __( 'Enable Fast Delivery Shipping', 'woocommerce' ),
      'default' 		=> 'yes'
    'title' => array(
      'title' 		=> __( 'Method Title', 'woocommerce' ),
      'type' 			=> 'text',
      'description' 	=> __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
      'default'		=> __( 'Fast Delivery Shipping', 'woocommerce' ),



If we want to make the shipping method not available for specific conditions, and as our example of Fast Delivery which they do not ship packages that weigh more than 10kg. That means when the visitor purchases a product that weighs more than 10kg, our shipping method won’t appear to him. We will implement that by implementing the “is_available” method.

public function is_available( $package ){

  foreach ( $package['contents'] as $item_id => $values ) {
      $_product = $values['data'];
      $weight =	$_product->get_weight();
      if($weight > 10){
      	return false;

  return true;


As you see, “is_available” method takes one parameter $packacge, This is an array that contains information about the products of the order. We can access the order items by using $package[‘contents’]. If you want to access the address of the package, you can use $package[‘destination’]. I advise printing the $package parameter to know what exactly it looks like. It will give you a complete image of the possibilities of this parameter.
Now to return to our table of rates, the shipping method must be not available if one of the products is weighing more than 10kg. When we are looping the package contents, you can get the current product object by $_product = $values['data'];

And to get the weight of the product, I used the method get_weight(). After that, I asked if the weight is more than 10kg If so, I  made the method to returned false. That’s it, you do your conditions and simply return true or false, this will reflect the shipping method availability. If you returned false, the shipping method will not appear on the checkout page.

Calculate Shipping Rate

Finally, we will implement the most important part of any shipping method, the rate calculations. To calculate the rates, you have to implement the abstract method “calculate_shipping”, and similar to “is_available” it also takes the $package parameter.  This is how the implementation looks like.

public function calculate_shipping($package){

    //get the total weight and dimensions
    $weight = 0;
    $dimensions = 0;
    foreach ( $package['contents'] as $item_id => $values ) {
      $_product  = $values['data'];
      $weight =	$weight + $_product->get_weight() * $values['quantity'];
      $dimensions = $dimensions + (($_product->length * $values['quantity']) * $_product->width * $_product->height);
    //calculate the cost according to the table
    switch ($weight) {
        case ($weight < 1):
          switch ($dimensions) {	
            case ($dimensions <= 1000):
            $cost = 3;
            case ($dimensions > 1000):
            $cost = 4;
        case ($weight >= 1 && $weight < 3 ):
          switch ($dimensions) {	
            case ($dimensions <= 3000):
            $cost = 10;
        case ($weight >= 3 && $weight < 10):
          switch ($dimensions) {	
            case ($dimensions <= 5000):
            $cost = 25;
            case ($dimensions > 5000):
            $cost = 50;

    // send the final rate to the user. 
    $this->add_rate( array(
      'id' 	=> $this->id,
      'label' => $this->title,
      'cost' 	=> $cost

Let’s walk through that code.

//get the total weight and dimensions
    $weight = 0;
    $dimensions = 0;
    foreach ( $package['contents'] as $item_id => $values ) {
      $_product  = $values['data'];
      $weight =	$weight + $_product->get_weight() * $values['quantity'];
      $dimensions = $dimensions + (($_product->length * $values['quantity']) * $_product->width * $_product->height);

Here, I calculated the total weights and dimensions of all the products of the order, but you should notice that we must pay attention if the user ordered more than one quantity from the product. We have to multiply the weight and the length by the quantity. Width and height do not change corresponding to the quantity.

After the weight and dimensions calculations, I wrote a switch statement that represents the Fast Delivery Inc rates table and calculated the final cost according to it.

// send the final rate to the user. 
    $this->add_rate( array(
      'id' 	=> $this->id,
      'label' => $this->title,
      'cost' 	=> $cost

After calculating the cost, we have to add it by using “add_rate” method. It will take an array as a parameter. This array contains the ID of the shipping method, the title of the shipping method and the final cost of the shipping. Then, WooCommerce will take care of the rate and shows it to the visitor.


Final Result
Final Result

I explained the most simple form of a shipping method. Usually, the shipping method will be more complicated. For example, you won’t find a shipping method with simple rules like this, and to resolve this problem, shipping companies provide an API to their services. Developers can interact with these APIs and calculate the shipping rate directly from the shipping company.

Every company has different rules and to develop a shipping method for them you must read their documentation of their API. In WordPress, you can interact with different APIs by using the ‘wp_remote_get‘ function.

In my opinion, the best way to learn how to implement a shipping method or a payment gateway is to read other developers code. You’ll examine how they solve common problems with these extensions and to know a lot of information that the WooCommerce official docs don’t provide.

Please do not hesitate to ask me any question, I will try my best to answer you. Also, If you liked this tutorial, you can subscribe to my newsletter to get the next posts immediately into your email.

Download the Extension Files


Update: Supporting Shipping Zones in WooCommerce 2.6+

WooThemes introduced Shipping Zones in WooCommerce 2.6. In the new shipping structure, you can create multiple shipping zones and assign different shipping zones to them. Each shipping method which is assigned to a zone will have different settings. This will help customers to customize each zone differently. Our concern as developers is that your shipping method will be used as an instance whenever it’s assigned to a zone.

To support shipping zones in your shipping method, you need to do some minor changes to the previous code. Let’s go through these changes and explain them.

The constructor.

  1. We will add $instace_id to the constructor. The constructor declaration should be public function __construct( $instance_id = 0 ){
  2. Inside the constructor, we need to assign the passed $instance_id. Adding this line will do it. $this->instance_id = absint( $instance_id );
  3. Then, we declare the support of shipping zones.
    $this->supports  = array(

This all what we need to change in the constructor of our method.

The settings form fields.

In the method “init_form_fields”, one simple line need to be changed, instead of $this->form_fields, we need to use $this->instance_form_fields

The calculate_shipping method.

Also, a minor change here, we should assign the $package parameter to a default value, so the calculate_shipping method declaration should be public function calculate_shipping( $package = array() ){

The main plugin’s file.

When you use the “woocommerce_shipping_methods” filter, replace this line

$methods[] = 'WC_Fast_Delivery_Shipping_Method';


$methods['fast_delivery_shipping_method'] = 'WC_Fast_Delivery_Shipping_Method';

fast_delivery_shipping_method‘ is the $id attribute value in the shipping method class we assigned in the constructor method.

Please, let me know if you have any questions regarding shipping zones support.

ABOUT THE AUTHOR: Waseem Founder and Lead Developer of WPRuby.

68 thoughts on “Shipping Method for WooCommerce Development Tutorial

  1. Hello,

    Thanks for sharing this tutorial, its very helpful.

    I have implemented your code. But, its not showing the plugin under the shipping box like you shown above. Please let me know what is the problem?

    1. Hello Vishal.
      Please, make sure that both shipping and the Shipping method itself are both enabled.

      You can enable “Shipping” in “WooCommerce -> Settings”

  2. i need to know how call this method again when a dropdown (city) change and then calculate again, please its urgent

    1. Hi Rodrigo,
      When you change the city dropdown, WooCommerce should automatically re-calculate the shipping rate. In this case, it will also call the same “calculate_shipping()” method in your shipping method class.

  3. THANK YOU SO MUCH! This was very helpful. I’m writing a plugin to allow customers to put in their own Fedex #’s and this was a great education.

  4. Thank you for this great tutorial! I have just one problem implementing it; it seems that the option “Enable Fast Delivery Shipping” does not have any effect. The shipping method is always available.

          1. Hi Waseem, thanks for checking it out. I uploaded the original Fast delivery shipping method-plugin to another site and got the same effect; the delivery method was still available even though i disabled it from Woocommerce’s shipping methods. I installed Extra flat rate plugin and with it I was able to enable/disable the option. Strange, can’t figure out what’s causing this 🙂

          1. I’m using localhost. So my localhost URL is wordpress.localhost. I have tried it but it is not working.

            Did you try using localhost?
            Is it affected by localhost?

            Thank you

  5. Great article!

    I am looking into the best way to add several methods for one carrier. Imagine that a carrier company has just one setting in the admin part but has several methods. Can this be done? It seems that there must be a class for each method but I would only like one setting in the backend since the top menu will otherwise be very long.

    Thank you.

    1. Why would you that?
      You can repeat the add_rate() line so you can add other options.

      For example, if the shipping company has a regular and an express services with different prices, you can simply add two rates with different prices and title in the same shipping class.

      1. Hi

        Thats is correct, but this would only create one carrier. If you for example were to change the shipping methods in the backend once the order has been placed, then you can only choose in a dropdown of carriers, not shipping methods (multiple shipping methods per carrier). Does it make sence?

  6. Hello and thank you for this very helpful blog about WooCommerce plugins. I am a new junior developer who has just left university, and I am very interested in improving my coding abilities as it will greatly enhance my opportunities when searching for employment.

    I agree with your comments about the WooCommerce documentation not being comprehensive enough, well at least for a novice coder such as myself. I get the impression that some previous coding knowledge and experience is required to fully understand the WooCommerce documentation, so your post to make things more clear has definitely helped me.

    I wanted to have a go at creating my own shipping plugin which will need to be compatible with WooCommerce, so I downloaded your source files. I noticed there were only 2 files and I realised immediately that the rest of the files which would enable me to create a working plugin were not available.

    I was wondering if you actually wrote the complete plugin with all the relevant php files, or was this just done as an exercise? If you have wrote the complete plugin would it be possible for you to make them available for me to have a look at so I can attempt to create my own fully working plugin from scratch?

    I just want to add that the plugin I want to make is for educational purposes only and will not be used commercially in any way shape or form. I hope to hear from you soon, and again I would like to thank you for taking the time to post your comments and files on the web for new learners such as myself.

    Best Wishes, Jack.

    1. Hello Jack,
      I’m very glad that you found my website useful.
      Actually, The files are a fully functioning wordpress plugin, no other PHP files needed.
      You just uplload the folder into the `plugins` directory and activate the plugin and it should work.
      Let me know if you have any further questions.
      Best Luck.

      1. Hello Waseem,
        And thanks for your speedy reply. I am amazed that a plugin can be so simple, I was sure there must have been more files needed. I am currently in the middle of following your tutorial to complete my own version of your plugin, I don’t just want to use your source files or I will not learn anything.

        Thanks again for your reply, and for this tutorial which I hope I can get working by using my own files. I will leave a comment when I have finished to let you know how I get on.

        Best Wishes, Jack.

      2. Hey Waseem,

        I got side-tracked yesterday so I was unable to finish the tutorial for the Fast Shipping Method tutorial. Fortunately I was able to complete it today, without any issues, and install it into my WordPress plugin section.

        I have to say it worked great and I was able to play around with dummy orders and tested out using the Fast Delivery Option. This has given me some insight into how to create a plugin as a new php developer.

        Thanks again for this great little tutorial, and if you have any others you think may be beneficial to me then feel free to point them out to me.

        Best Wishes, Jack

          1. Hey Waseem,

            Sorry for my delayed reply, been snowed under at my internship learning new back-end and php skills. This tutorial looks pretty useful, I will give it a go when I get chance 🙂

  7. Hi Waseem,

    Your post is very useful and easy to understand. I can implement new shipping method in woocommerce within 30 minutes after read your post. Awesome work!. Thank you.

    Best Wishes,

  8. This was the code i exactly wanted…Thanks
    Although i would like to know how to attach the Taxable option in the settings similar to the others methods like flat rate.
    Best wishes

    1. Hello Johnross,
      You’re welcome.
      You can add the tax option by appending the `$this->form_fields` array in the `init_form_fields()` method

      ‘tax_status’ => array(
      ‘title’ => __( ‘Tax Status’, ‘woocommerce’ ),
      ‘type’ => ‘select’,
      ‘class’ => ‘wc-enhanced-select’,
      ‘default’ => ‘taxable’,
      ‘options’ => array(
      ‘taxable’ => __( ‘Taxable’, ‘woocommerce’ ),
      ‘none’ => _x( ‘None’, ‘Tax status’, ‘woocommerce’ )

      And add this line in the constructor method:
      $this->tax_status = $this->get_option( ‘tax_status’ );

  9. I tried adding a new field called Extra in the admin side….But i cant update the default value even after i removed the default part from the code….

    ‘Extra Grams’ => array(

    ‘title’ => __( ‘Extra Grams to be added ‘, ‘woocommerce’ ),

    ‘type’ => ‘text’,

    ‘description’ => __( ‘This controls the title which the user sees during checkout.’, ‘woocommerce’ ),

    //’default’ => __( ‘200’, ‘woocommerce’ ),

    This is the code….i commented the default part….but it still shows 200 …How to change it??

    1. Hi Johnross,
      First, you need to change the array key from “Extra Grams” to “extra_grams”.
      Then you must initialize that option in the constructor like this.
      $this->extra_grams = $this->get_option( ‘extra_grams’ );

      1. Hi Waseem,

        What would be a good way to access these values from within the order?

        It doesn’t seem to be added to the order via “WC_Order_Item_Shipping”.

        Thanks for your help.

        1. Hi Mr Alexander
          WC_Order_Item_Shipping is not supposed to hold these values. You need to use the instance_id of the class object and use to initiate the shipping method object and get these values from it.

  10. I have created a table which contains countries and the corresponding price for each country…. i would like to fetch the country selected from the checkout form and compare with the database in my shipping code…..but i dont know how to fetch the chosen country from the checkout form(billing form)..Could you help??

    1. Hi Johnross,
      You can get the `destination` country by using the `$package` parameter in `calculate_shipping` method.

      Use this index $package[‘destination’][‘country’]

  11. Hi Waseem,

    good to hear that you survived all wars! 🙂

    Is there any way to add the shipping rates in the checkout “on the fly”?

    I have a shop with several vendors who can create products with individual shipping options/costs (even per variable produkt). I am calculating these options in the cart and checkout (which is working fine), but I am having trouble adding the calculated costs to the order object. I want to use add_rate (e.g. in review-over.php) with the costs that I have manually calculated in the same file.

    My failed approach:

    $rate = array(
    ‘id’ => ‘waa_product_shipping’,
    ‘label’ => ‘Shipping’,
    ‘cost’ => $shipping_costs,
    ‘calc_tax’ => ‘per_order’

    $shipping = new waa_WC_Shipping();
    $shipping->add_rate( $rate );

    Or is there an even easier way (e.g. hidden input like ?

  12. Hi Waseem excellent article! I have a small doubt. On the admin panel i need to put a only number textbox… How i can do this? Thanks a lot

  13. Waseem, huge thanks for this tutorial! I needed to create a custom shipping method that calculates total shipping costs by sending the SKUs and quantities of each item in the cart to an external API, but I as struggling because the WooCommerce docs for the overall shipping process are pretty bad. Apparently the next update, 2.6, will make big changes to shipping, but in the meantime I’m so thankful your walkthrough showed me the way! Thanks, again.

  14. Thank you for another informative website. Where else could I get that kind of info written in such a perfect way? I’ve a project that I’m just now working on, and I have been on the look out for such info.

  15. Waseem – heads up that the update to WooComm 6.x+ seems to have broken plugins that are coded in this way. At the very least, mine is no longer working 🙁 Going to try to work through and fix it today. Not upgrading is not an option for me because I need to use the WooComm REST API that is included in version 6.0+. So today I am going to try to make some corrections and get this thing running again. Thanks again for your help!

    1. Yes, WooCommerce introduced Shipping Zones in 2.6.0. I will try my best to update the tutorial as soon as possible.
      Thank you on the notice.

      1. I still have the same problem. The shipping method appears in the dropdown, but when the “Add shipping method” button is clicked in the modal window, all I get is a spinner then nothing.

        I’m running
        – WordPress 4.6.1
        – WC 2.6.4

        Something else might be missing?

  16. Hi Waseem,

    I tried adding the code for shipping zones support on a plugin I was developing.
    The shipping method is shown on the “add shipping method” select box but when I select it and press
    add shipping method it is not showing as a method for that particular shipping zone. Nothing happens.

    Do you have any idea why? Is it possible that there are some more steps that might be needed to add support for shipping zones besides the code you gave?

    By the way. Nice article. 🙂


    1. Thanks Jayson.
      You were right, one more step was missing. I just updated the tutorial, please see the last step in the main plugin’s file.

  17. Hi,

    First of all, i give you 5 stars to the post/tutorial.

    Now, my question!

    The actual shipping zones workflow allow shop owners to define the shipping price by shipping classes in Zones tab but in this tutorial this prices was defined in the plugin code.
    How can I add this “price per shipping class” fileds?

    Thanks in advance.

    Keep the good work!

  18. Hello!

    I’m trying to learn… Studying Your code with the friendly guide of Your comments.
    But I’m stuck at the beginning, wondering if I’m doing everything correctly, looking at the empty space in the admin area where the method should appear.
    Actually… The plugin, as it is when downloaded, shows in the admin panel, but when updated with Your last suggestions, it stops showing. I guessed that the big problem is with this:
    $this->supports = array(‘shipping-zones’, ‘instance-settings’, ‘instance-settings-modal’,);
    Taking that row away has the effect of showing the menu in the admin area, with the title and the save button, but nothing inside,
    Any suggestions on how is this possible and any way to proceed to the next step?

    Thank You!

  19. Thanks Waseem for this great tutorial.
    I am wondering if this can be used to add an additional local pickup shipping method? I need to have 2 local pickup options, metro pickup with a list of metro branches for pickup and Regional pickup with a list of regional stockists for pickup. The user will select their pickup location from a dropdown in each case.

    The user will be directed to either metro or regional via a list of postcodes which we already have working using shipping zones.

    Any advice on this would be greatly appreciated.

  20. Hi Waseem,

    this is a great article.
    I have a problem I hope you can help me with.

    I have a store that I have setup and I have added a fee for “packing and handling” via the functions.php

    add_action( ‘woocommerce_cart_calculate_fees’,’handling_fee’ );
    function handling_fee() {
    global $woocommerce;

    if ( is_admin() && ! defined( ‘DOING_AJAX’ ) )

    $fee = 7.00;
    $woocommerce->cart->add_fee( ‘Packaging and Handling’, $fee, true, ‘standard’ );

    however now I want to add a local pickup function for my customers, but when they select “local pickup” the added fee is still visible.

    how can i tell if the local pickup option has been selected and to skip the add_fee

    Thanks & Regards,


  21. Hello ,
    Very usefull tutorial sir.
    I want to give two shipping options from the same plugin , is it possible??
    And how can i give different rates for different vendors of products in same cart.?

  22. After searching for days on the internet, this tutorial points out some important parts of developing a custom shipping method.

    Thank you WPRuby!


Your email address will not be published.