Chat with us, powered by LiveChat

This website uses cookies

Our website, platform and/or any sub domains use cookies to understand how you use our services, and to improve both your experience and our marketing relevance.

Our Magento Customers Get 1-Click Hosting and 0.37ms Load Time. Get FREE $20 Credit with Promo Code 'BOOSTMAG.' Join Now!

How To Create A Magento 2 Shipping Extension

Updated on October 1, 2018

4 Min Read
Reading Time: 4 minutes

A Magento 2 shipping extension defines the medium of delivery for the purchased product. It determines the shipping charge that the customer pays during checkout. The shipping fee can be fixed at $5 flat rate on any order, or a dynamically calculated cost through a real-time shipping service. This is based on the details of the order and shipment like weight, origin, destination, etc.

Magento 2 already has many built-in shipping methods, but if you need to create a custom Magento shipping extension, then this guide is for you. Today, I am going to show you how to create a Magento 2 shipping extension using best practices.

Magento Managed Cloud hosting

Let’s start by creating a custom module in Magento 2. If you are not familiar with it, check out this guide on Create Module in Magento 2.

First of all, create a configuration and registration file of the Magento 2 shipping module. Create module.xml in Magento2Root/app/code/Cloudways/Shippingmodule/etc and paste the following code:

<?xml version="1.0"?>
	<config xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
		<module name="Cloudways_Shippingmodule" setup_version="1.0.1"></module>

Cloudways Magento Hosting For Developers

Create a registration.php in app/code/Cloudways/Shippingmodule with the following code:


Now, create a class which will handle the Shipping Method. Keep in mind that the shipping method should be defined in Cloudways/Shippingmodule/etc/config.xml file. Without this file, the method in Magento 2 shipping extension won’t work.

Bonus Tip: Ecommerce stores that use cloud hosting see a 50% increase in page speed. Don’t get left out. Move to best Magento 2 hosting today.

In the config.xml file, the parent node is <default>, and its child node is <carriers> which further defines the property with the same name as the $_code in shipping class. It also has a <model> node that defines the shipping class Cloudways\Shippingmodule\Model\Carrier\Shippingmodule.

Create a config.xml file and add the following code:

<?xml version="1.0"?>
	<config xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
					<name>Shipping Module</name>
					<title>Cloudways Shipping Module</title>
					<specificerrmsg>This shipping method is not available. To use this shipping method, please contact us.</specificerrmsg>

As we all know, every shipping method should have configuration options in the admin panel. Let’s add shipping method options through the system.xml file that can be created in Cloudways\Shippingmodule\etc\adminhtml directory with the following code:

<?xml version="1.0"?>
	<config xmlns:xsi="" xsi:noNamespaceSchemaLocation="../../../../Magento/Config/etc/system_file.xsd">
			<section id="carriers" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
				<group id="cloudways_shippingmodule" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
					<label>Cloudways Shipping Module</label>
					<field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0">

					<field id="title" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">

					<field id="name" translate="label" type="text" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1">
						<label>Method Name</label>

					<field id="price" translate="label" type="text" sortOrder="4" showInDefault="1" showInWebsite="1" showInStore="0">
						<label>Shipping Cost</label>
						<validate>validate-number validate-zero-or-greater</validate>

					<field id="specificerrmsg" translate="label" type="textarea" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="1">
						<label>Displayed Error Message</label>

					<field id="sallowspecific" translate="label" type="select" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="0">
						<label>Ship to Applicable Countries</label>

					<field id="specificcountry" translate="label" type="multiselect" sortOrder="91" showInDefault="1" showInWebsite="1" showInStore="0">
						<label>Ship to Specific Countries</label>

					<field id="showmethod" translate="label" type="select" sortOrder="92" showInDefault="1" showInWebsite="1" showInStore="0">
						<label>Show Method if Not Applicable</label>

					<field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0">
						<label>Sort Order</label>

Last but not least, I have to create a Shipping Class as defined in the <model> node in the config.xml file. Create Shippingmodule.php file in Cloudways\Shippingmodule\Model\Carrier directory and add the following code to it:


namespace Cloudways\Shippingmodule\Model\Carrier;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\DataObject;
use Magento\Shipping\Model\Carrier\AbstractCarrier;
use Magento\Shipping\Model\Carrier\CarrierInterface;
use Magento\Shipping\Model\Config;
use Magento\Shipping\Model\Rate\ResultFactory;
use Magento\Store\Model\ScopeInterface;
use Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory;
use Magento\Quote\Model\Quote\Address\RateResult\Method;
use Magento\Quote\Model\Quote\Address\RateResult\MethodFactory;
use Magento\Quote\Model\Quote\Address\RateRequest;
use Psr\Log\LoggerInterface;

class Shippingmodule extends AbstractCarrier implements CarrierInterface
	protected $_code = 'cloudways_shippingmodule';
	protected $_isFixed = true;
	protected $_rateResultFactory;
	protected $_rateMethodFactory;

	public function __construct(
	ScopeConfigInterface $scopeConfig,
	ErrorFactory $rateErrorFactory,
	LoggerInterface $logger,
	ResultFactory $rateResultFactory,
	MethodFactory $rateMethodFactory,
	array $data = []

		$this->_rateResultFactory = $rateResultFactory;
		$this->_rateMethodFactory = $rateMethodFactory;
		parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);

	public function getAllowedMethods()
		return [$this->getCarrierCode() => __($this->getConfigData('name'))];

	public function collectRates(RateRequest $request)
		if (!$this->isActive())
			return false;

		$result = $this->_rateResultFactory->create();

		$shippingPrice = $this->getConfigData('price');
		$method = $this->_rateMethodFactory->create();
		return $result;

In this class, you can see I have added some Magento 2 rules. Every class in Magento 2 shipping extension extends \Magento\Shipping\Model\Carrier\AbstractCarrier and implements the \Magento\Shipping\Model\Carrier\CarrierInterface class. I have also defined a variable $_code with its value. This value is related to the config.xml file node structure.

Moreover, I have created two functions getAllowedMethods and collectRates. These methods are required by the abstract class and interface.

Function collectRates has a parameter $request which is the instance of RateRequest class. This Magento\Quote\Model\Quote\Address\RateRequest class contains all information about the items in the cart: quote, weight, shipping/billing address, etc. In this method, I have implemented all logic for shipping calculation.

That’s it, you’re all done! Now, to enable this Magento 2 shipping extension, connect to your Magento hosting server via SSH and run the following CLI command in the root directory of your Magento 2 store:

rm -Rf var/di/* var/generation/* var/cache/* var/log/* var/page_cache/* var/session/* var/view_preprocessed/* pub/static/*
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy -f
php bin/magento indexer:reindex
php bin/magento cache:clean
php bin/magento cache:flush

Now let’s check out the result! Log in to your Magento 2 Admin panel, navigate to STORES > Configuration, expand the SALES section from the left panel and click Shipping Methods.

Magento Manage Sales

Here, you’ll see that the new shipping Method has been added. Enable it and set the values according to your need.

Shipping Module Enable

If you have implemented everything as it is, your Magento 2 checkout page will have a shipping method.

Magento Review Payments

I hope you found this post useful 🙂 If you have any question or need help, I’d be happy to help you out. Feel free to get in touch by commenting in the box below.

Share your opinion in the comment section. COMMENT NOW

Fayyaz Khattak

Fayyaz is a Magento Community Manager at Cloudways - A Managed Magento Hosting Platform. His objective is to learn & share about PHP & Magento Development in Community. Fayyaz is a food lover and enjoys driving. You can email him at

Double Your Conversions with Magento Managed Cloud

Free SSL, Free Migration, Optimized Stack, Built-in Varnished Cache and much more.

Get Our Newsletter
Be the first to get the latest updates and tutorials.

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!