If you're selling physical products on your store, you'll need a way to ship those products to your customers. Thankfully, Simple Commerce has an easy way to create custom shipping methods for your store.

Every store can have any number of shipping methods. For example, you could use one shipping method for 1st Class mail and others for 2nd and 3rd class mail.


Shipping Methods can be configured on a site-by-site basis, helpful for if you have different version of your store for different countries.

1'sites' => [
2 'default' => [
3 ...
5 'shipping' => [
6 'methods' => [
7 \DoubleThreeDigital\SimpleCommerce\Shipping\StandardPost::class => [],
8 ],
9 ],
10 ],

The methods array should contain an array of Shipping Method classes, with the ::class syntax. You may also specify a configuration array as the second parameter.

Default shipping method

Normally, a shipping total isn't calculated until you've added a Shipping Method to the order. This is usually done after the customer has entered their shipping address and they're then offered an option as to which Shipping Method to use.

However, there are some cases where you may need to calculate Shipping costs before a Shipping Method has been selected on an order. You may also want it for stores where there's only one shipping method available.

In these cases, you may configure a default Shipping Method which will be used when calculating order totals if no Shipping Method has already been set.

1'sites' => [
2 'default' => [
3 ...
5 'shipping' => [
6 'default_method' => \DoubleThreeDigital\SimpleCommerce\Shipping\StandardPost::class,
8 'methods' => [
9 \DoubleThreeDigital\SimpleCommerce\Shipping\StandardPost::class => [],
10 ],
11 ],
12 ],


Simple Commerce will not check if the default method is 'available' for the customer before using it.

Third-party Shipping Methods


During the cart/checkout flow, you'll want to do 2 things: first, let the customer enter their shipping address for the order and secondly, let the customer select the shipping method you want to use for the order.

Let's start with the letting the user enter their shipping address. In our starter kit, we have this on the initial cart page.

1{{ sc:cart:update }}
2 <input type="text" name="shipping_name" placeholder="Name" value="{{ old:shipping_name }}">
3 <input type="text" name="shipping_address" placeholder="Address" value="{{ old:shipping_address }}">
4 <input type="text" name="shipping_city" placeholder="City" value="{{ old:shipping_city }}">
5 <input type="text" name="shipping_region" placeholder="Region" value="{{ old:shipping_region }}">
6 <select name="shipping_country" value="{{ old:shipping_country }}">
7 {{ sc:countries }}
8 <option value="{{ iso }}">{{ name }}</option>
9 {{ /sc:countries }}
10 </select>
11 <input type="text" name="shipping_zip_code" placeholder="Postal Code" value="{{ old:shipping_zip_code }}">
13 <button type="submit">Update Shipping Address</button>
14{{ /sc:cart:update }}

When submitted, that form will fill in the appropriate address fields.

Hot Tip

You can also do billing_name, billing_address, billing_city etc to allow the user to update their billing address.

After the customer has entered their address we can find available shipping methods for them and allow them to select which one they'd like to use. Again, we can use the {{ sc:cart:update }} tag to manage this. We also do this on our starter kit.

1{{ sc:cart:update }}
2 <p>Please select a shipping method for your order.</p>
4 <select name="shipping_method" value="{{ old:shipping_method }}">
5 <option value="" disabled selected>Select a Shipping Method</option>
6 {{ sc:shipping:methods }}
7 <option value="{{ handle }}">{{ name }} - {{ cost }}</option>
8 {{ /sc:shipping:methods }}
9 </select>
11 <button type="submit">Select Shipping Method</button>
12{{ /sc:cart:update }}

After the customer has submitted that form, Simple Commerce will use that shipping method and update the order totals.

Marking an order as shipped

As of Simple Commerce v2.4, you may now mark an order as 'Shipped'. You can either do this programatically or via the Control Panel.

Marking an order as shipped will dispatch an event which you can use to send notifications to customers.


If you want to mark an order as Shipped from your own code, you may use the markAsShipped method available on Order objects.

1use DoubleThreeDigital\SimpleCommerce\Facades\Order;
3$order = Order::find(123);

Via the Control Panel


This will only show if you're using Collections & Entries for your orders. You'll need to build this yourself for custom content drivers.

In the Control Panel listing table for orders, find the order you wish to mark as shipped, click the three dots on the right, and select the 'Mark as Shipped' option.

The action will only be available for order which have already been marked as paid.

Mark as Shipped

Creating a shipping method

Simple Commerce doesn't come with any shipping methods out of the box so you'll need to write your own. We do, however have a command you can use to generate the boilerplate for a shipping method.

1php please make:shipping-method YourNewShippingMethod

That command will create a Shipping Method class in your app\ShippingMethods folder. It'll look something like this:

3namespace App\ShippingMethods;
5use DoubleThreeDigital\SimpleCommerce\Contracts\Order;
6use DoubleThreeDigital\SimpleCommerce\Contracts\ShippingMethod;
7use DoubleThreeDigital\SimpleCommerce\Data\Address;
8use DoubleThreeDigital\SimpleCommerce\Shipping\BaseShippingMethod;
10class FirstClass extends BaseShippingMethod implements ShippingMethod
12 public function name(): string
13 {
14 return 'Name of your shipping method';
15 }
17 public function description(): string
18 {
19 return 'Description of your shipping method';
20 }
22 public function calculateCost(Order $order): int
23 {
24 return 0;
25 }
27 public function checkAvailability(Order $order, Address $address): bool
28 {
29 return true;
30 }

Here's a quick explanation of what each method does.

  • name: Should return the name of your shipping method (will be shown to customers)
  • description: Should return a description for your shipping method
  • calculateCost: This method should be where you return the cost of the shipping, based on the order's entry data.
  • checkAvailability: This method is where an Address object is passed in and you should return a boolean of whether or not you ship to that location.

Using config settings

As mentioned earlier, you may let users of your shipping method specify a configuration array which is accessible inside the Shipping Method itself. If you'd like to do this, you may access the config like so:

1// app/ShippingMethods/FirstClass.php