Creating a Shipping Method in Magento 2 - Classy Llama
Creating a Shipping Method in Magento 2
Creating a Shipping Method in Magento 2

Creating a Shipping Method in Magento 2

Published November 30, 2017 in Classy Llama, Development
A look at CSS and Less in Magento 2
A Look at CSS and Less in Magento 2
October 17, 2017
Top 3 Tips for Making Holiday Shipping Easier
Top 3 Tips for Making Holiday Shipping Easier
December 6, 2017

There are existing extensions available for many of the shipping carriers that you may choose to utilize on your Magento 2 site, but what about a shipping method of your own? Adding a custom shipping method like this is a straightforward approach that requires only a handful of files in order to implement – five, to be exact.

Let’s create a ‘Customer Pickup’ shipping method that is used to provide customers who are local to our warehouse the option of picking up their order as opposed to paying for shipping.

Our new shipping method will get its own extension, and as with other custom extensions, it will reside within a vendor folder in our site’s app\code\ folder. We will be using the following path for our new extension:app\code\ClassyLlama\CustomerPickup For the remainder of this article, all file and path references will be in relation to the CustomerPickup folder.

We start by creating the two files that are required for all custom extensions: registration.php and module.xml. I will assume you are familiar enough with Magento 2 development to know what these two files are and why they are required, so I won’t go into depth about that here. If you are new to creating extensions in Magento 2, the DevDocs’ PHP Developer Guide is a must-read.

Configuration files

First, we have to tell Magento about our new shipping method’s existence; this is accomplished with the system.xml and config.xml files. The system.xml file will define the configuration settings available for our shipping method in the Magento 2 admin (in STORES > Configuration > SALES > Shipping Methods) and the config.xml file will set default values for those settings.

There are certain configuration settings for shipping carriers that are expected by Magento and thus should be included in all shipping methods:

  • active – This boolean value indicates whether this shipping method is active or not.
  • model – The path to the shipping method’s model.
  • title – The name of the shipping “carrier” that will be displayed in the frontend.
  • sallowspecific – This boolean value indicates whether this shipping method should be available for all countries or only those specified.
  • sort_order – This parameter tells Magento wherein the list of available shipping methods this method will display.

There are some additional settings we are including as well:

  • price – This shipping method will have a price of $0.00.
  • name – The name of this shipping method to be displayed to the customer.
  • showmethod – Whether or not to show this shipping method even when not applicable.

Our extension’s system.xml file has a default structure that should be followed:

  • Configuration elements must be created using the following node structure:
  • The <section> node must have an id value of "carriers".
  • The <group> node must have an id value equal to our new shipping code, in this case customerpickup.

By building the XML file in this manner, Magento knows where to place the configuration settings in the backend (in this case with the other shipping methods) and how to retrieve them when called.


Our extension’s config.xml (the file that defines the default values for the settings defined in system.xml) also has layout rules that must be followed:

  • Configuration elements must be created under the main node of <default> with a child node of <carriers> in a child node named with the shipping method code we’ve created, in this case <customerpickup>.


The Shipping Method Class

At this point, we’ve created the extension, but it doesn’t yet do anything for us. To get the extension working for us, we need to create the model at app\code\ClassyLlama\CustomerPickup\Model\Carrier\CustomerPickup.php.

There are some specific items worth noting when creating our custom shipping method’s class:

  • Every shipping method’s class in Magento 2 must extend \Magento\Shipping\Model\Carrier\AbstractCarrier and implement \Magento\Shipping\Model\Carrier\CarrierInterface.
  • Every shipping method’s class must include a minimum of two methods: getAllowedMethods and collectRates.
    • The method getAllowedMethods:
      • Must return an array of the available shipping options for our shipping method (e.g. ‘Standard Delivery”, ‘Expedited Delivery’).
      • Can include as few or as many shipping options as are applicable to the method. In our example case, there is only the one – ‘Customer Pickup’.
    • The method collectRates returns either:
      • A boolean false, which effectively disables the shipping method, excluding it from a list of shipping options.
      • An instance of \Magento\Shipping\Model\Rate\Result instantiated via a Magento factory.
        • If returning an instance of Result, it can have as many, or as few, methods appended to it as is applicable; each appended method is a factory-generated instance of \Magento\Quote\Model\Quote\Address\RateResult\Method. This model represents a shipping method and has its details set within it (e.g. Carrier code and title, method code and title, Price). In our example below, we are only attaching a single method, but the process can be repeated as many times as necessary.
  • The $_code variable in the class must be set to the unique shipping code chosen for our custom shipping method, in this case customerpickup.
  • The method $this->getConfigData is used to retrieve the configuration settings that are defined in the extension’s system.xml file (e.g. $this->getConfigData(‘name’) will return the value set for the method’s name).


Our new shipping method can be customized however we need it to be. For example, we could check whether any items in the customer’s order are being drop shipped, and if so, not offer ‘Customer Pickup’ as an available shipping method; we could also disable our shipping method for orders placed from outside of specific regions.

Configure and test the shipping method

After enabling our new extension and clearing the cache, we can visit our site’s admin section (e.g. and head to the Shipping Methods section at STORES > Configuration > SALES > Shipping Methods. We should now see a page similar to the one below, with our new shipping method’s default configuration settings we defined earlier in the system.xml file.

To test our new shipping method, we just have to head to our store’s website like a customer would, create a qualifying order (don’t forget what rules you had previously put in place in the model), and head to the shopping cart. As you can see in the screenshot below, our new shipping method is available for us to choose.

If we proceed to checkout, we see in the screenshot below that we again have the option of Customer Pickup as our shipping method.


We have now completed the creation, configuration, and testing of a custom shipping method that allows our local customers to save on the cost of shipping and pick their qualifying orders up at our warehouse at their convenience.

This tutorial can be used to tailor your online store’s shipping logic to match what is right for you and your business, rather than being tied to native rate models that may not fit every scenario. Custom shipping methods can be a powerful tool; and since the creation process is straightforward, it makes for a handy tool in your Magento tool belt!


  1. Guilherme says:

    Great post, it’s been very useful!

    However, if a customer chooses to pickup his order, he shouldn’t need to fill up his Shipping Address during the checkout.

    And the order confirmation information should inform the pickup address (which could be set on Admin) as the delivery address.

    Is there a way to do that?

    • Guilherme,

      You bring up a good point. A savvy user may actually be able to circumvent sales tax by using a shipping address in a nontaxable region, but then selecting the option of picking up the order in person, which means the order should be taxed.

      I would imagine the solution would still require the customer to choose a shipping address, since this is necessary to display shipping methods, but if they were to select the “Customer Pickup” shipping method, continuing to the payment step would replace their shipping address with a taxable one (e.g. the merchant’s address). However, addressing that in detail is beyond the scope of this particular blog post.

  2. Neeraj says:

    I create a custom shipping module. My custom shipping module is working fine. it is showing the price that I filled in the admin on cart or checkout page.
    Now I need to change a shipping price based on the pin code that user fill or choose in available shipping in magento 2.

    Can you please help me how can I do this?

    • Richard Sisco says:


      It sound like you are looking for a custom table rate solution that will choose a shipping rate based on customer input. That would require creating a new database table to hold the rates with their identifying codes/pins (and optionally an interface to populate/update the table), adding a new input field to the checkout process, and some logic in the shipping extension to match the two up.

      This is achievable, but covering those steps is beyond the scope of this particular blog post.

  3. Deepak Shinde says:

    Nice Post, Richard. It’s very informative.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Most Recent PostsView all
November 4, 2021

How to prepare for holiday 2021: A winter shopping season like no other

With the holiday season comes a frenzy of online shopping activity. For retail businesses, this busy season is a critical period when an essential amount of […]
October 15, 2021

Classy Llama Wins 2021 Comparably Awards for Best Perks&Benefits, Best Work-Life Balance

Classy Llama, Springfield’s only full-service eCommerce agency, has been placed on the top 50 list for’s Best Perks&Benefits Award, as well as their Best Work-Life […]
September 15, 2021

Classy Llama Awarded #3 Best Place to Work by Biz417

Springfield, MO — Classy Llama has been awarded the number 3 spot on the Biz417 Best Places to Work Top 20 for 2021.  This award is […]