Shipping methods are essential for each web store owner, and one of the most frequently asked questions about headless storefront is: 'Does PWA Studio (or VSF) support all of the shipping methods available in the Magento backend'. I did a small investigation, and I would like to show you how shipping methods are rendered on the PWA Studio storefront.
Magento 2 as an eCommerce platform offers good support for various shipping methods so typically you are able to find integration for the shipping methods you want. Until you want to build a headless storefront connected with Magento 2, the sentence above for sure, but how support for Magento 2 shipping methods looks when you want to:
-
build a PWA storefront using PWA Studio?
-
build a headless storefront using Vue Storefront?
-
build your own custom headless storefront?
I did a small investigation, and in this article, I would like to show you what is the support for shipping methods, and what options you have when you want to create your own custom shipping method.
Three default Magento 2 shipping methods
Magento 2 offers three simple shipping options:
-
flat rate - straightforward shipping method with fixed prices for each item.
-
table rates - the shipping rates in tables calculate shipping costs using conditions like Weight v. Destination, Price v. Destination, and Number of Items v. Destination. Data used for calculation came from a predefined spreadsheet that is imported to a store
-
free shipping - you can set free shipping based on minimum amount of an order, or set up a cart price rule that is applied when a set of conditions is me
How to configure Magento 2 shipping settings
To configure shipping methods you need to open an admin panel and go to Stores > Configuration > Sales > Delivery methods. You should see the shipping methods configuration:
Each shipping method has a similar set of configuration fields. Take a look at the flat rate shipping method:
Shipping methods configuration fields
-
enabled - determinates is shipping method is enabled for a specific scope
-
title - the name of the shipping method that is used on the Magento 2 checkout page
-
method name - the name of the method used next to the title on the checkout page. For example, the default phrase visible on the checkout page for the Flat rate shipping method is “Flat rate - fixed”
-
price - the price of the shipping method that you charge a customer
-
calculate handling fee - the way the handling fee is calculated if included. Options: Fixed / Percent
-
handling fee - the amount to be charged for a handling fee, based on the method you have chosen to calculate the amount (fixed or percent)
-
displayed error message - a message appears in the case when the method is not available
-
ship to applicable countries - thanks to this option you can specify for which countries shipping method is available
-
ship to specific countries - similar to the previous one, but here you can explicitly set countries
-
show method if not applicable - if this option is set to yes, a shipping method will be visible on checkout even is not applicable for some reason.
-
sort order - a number determines the position of this method in the delivery methods list visible on the checkout page
Configure shipping methods in Magento
Please follow these tutorials to configure default shipping methods in Magento:
When you complete and go to the Magento checkout page you should see something like this:
Magento 2 shipping methods in headless storefronts
In case when you wanted to build a headless storefront for Magento, you would have considered three options:
-
use PWA Studio
-
use Vue Storefront
-
build custom frontend
In either case, the Magento 2 GraphQL API is a source of data, so let’s take a look hwo to retreive information about shipping methods from GraphQL and which data is available.
Fetch shipping methods from Magento GraphQL API
Create empty Cart
Firstly, we have to create an empty cart. To do so, send this mutation to the API:
mutation {
createEmptyCart(input: {})
}
The mutation returns a new cart id like this:
{
"data": {
"createEmptyCart": "K9tlVNTGnyKk9b7Lw8xLnByORqQUhRGR"
}
}
Add product to cart
Once we have a new cart, we can add products to it. Before we do that, we fetch information about products from Magento.
Fetch products information
query {
products(search: "bag", pageSize: 5) {
items {
uid
name
}
}
}
The query above returns five products that pass to the “bag” search term. The SKU field is important to us because we will use it in the next step. Here we have our five bags:
{
"data": {
"products": {
"items": [
{
"sku": "24-MB01",
"name": "Joust Duffle Bag"
},
{
"sku": "24-WB01",
"name": "Voyage Yoga Bag"
},
{
"sku": "24-MB05",
"name": "Wayfarer Messenger Bag"
},
{
"sku": "24-WB04",
"name": "Push It Messenger Bag"
},
{
"sku": "24-UG03",
"name": "Harmony Lumaflex™ Strength Band Kit "
}
]
}
}
}
Add product to cart using addProductsToCartMutation
Once we know the cart ID, and some products IDs, we can add products to the cart:
mutation {
addProductsToCart(cartId: "K9tlVNTGnyKk9b7Lw8xLnByORqQUhRGR", cartItems: [{ sku: "24-MB01", quantity: 1 }]) {
cart {
total_quantity
items {
product {
sku
}
}
}
}
}
In the query above I added a product with SKU 24-Mb01 to the cart. Results:
{
"data": {
"addProductsToCart": {
"cart": {
"total_quantity": 1,
"items": [
{
"product": {
"sku": "24-MB01"
}
}
]
}
}
}
}
Set shipping address on the cart
The shipping address is the last missing thing that we have to add to see available shipping methods. To add the shipping address we need to use the setShippingAddressesOnCart mutation:
mutation {
setShippingAddressesOnCart(
input: {
cart_id: "K9tlVNTGnyKk9b7Lw8xLnByORqQUhRGR"
shipping_addresses: [
{
address: {
firstname: "Bob"
lastname: "Roll"
company: "Magento"
street: ["Magento Pkwy", "Main Street"]
city: "Austin"
region: "TX"
postcode: "78758"
country_code: "US"
telephone: "8675309"
save_in_address_book: false
}
}
]
}
) {
cart {
shipping_addresses {
firstname
lastname
company
street
city
region {
code
label
}
postcode
telephone
country {
code
label
}
}
}
}
}
When I send this mutation to the API, Magento will set the shipping address on the cart. Results:
{
"data": {
"setShippingAddressesOnCart": {
"cart": {
"shipping_addresses": [
{
"firstname": "Bob",
"lastname": "Roll",
"company": "Magento",
"street": ["Magento Pkwy", "Main Street"],
"city": "Austin",
"region": {
"code": "TX",
"label": "Texas"
},
"postcode": "78758",
"telephone": "8675309",
"country": {
"code": "US",
"label": "US"
}
}
]
}
}
}
}
Fetch available shipping methods from Magento 2 GraphQL API
We have everything to get information about shipping methods, so we can use this query:
query {
cart(cart_id: "K9tlVNTGnyKk9b7Lw8xLnByORqQUhRGR") {
shipping_addresses {
available_shipping_methods {
amount {
currency
value
}
available
carrier_code
carrier_title
error_message
method_code
method_title
price_excl_tax {
currency
value
}
price_incl_tax {
currency
value
}
}
}
}
}
Magento returns available shipping methods, and as you can see below, all three mentioned earlier shipping methods (flat rate, table rate, and free shipping) are available:
{
"data": {
"cart": {
"shipping_addresses": [
{
"available_shipping_methods": [
{
"amount": {
"currency": "USD",
"value": 0
},
"available": true,
"carrier_code": "freeshipping",
"carrier_title": "Free Shipping",
"error_message": "",
"method_code": "freeshipping",
"method_title": "Free",
"price_excl_tax": {
"currency": "USD",
"value": 0
},
"price_incl_tax": {
"currency": "USD",
"value": 0
}
},
{
"amount": {
"currency": "USD",
"value": 10
},
"available": true,
"carrier_code": "flatrate",
"carrier_title": "Flat Rate",
"error_message": "",
"method_code": "flatrate",
"method_title": "Fixed",
"price_excl_tax": {
"currency": "USD",
"value": 10
},
"price_incl_tax": {
"currency": "USD",
"value": 10
}
},
{
"amount": {
"currency": "USD",
"value": 15
},
"available": true,
"carrier_code": "tablerate",
"carrier_title": "Best Way",
"error_message": "",
"method_code": "bestway",
"method_title": "Table Rate",
"price_excl_tax": {
"currency": "USD",
"value": 15
},
"price_incl_tax": {
"currency": "USD",
"value": 15
}
}
]
}
]
}
}
}
Support for shipping methods in GraphQL API and headless storefronts
Thanks to Magento 2 GraphQL API you can fetch information about basic delivery methods and use them on your headless storefront. Summarizing - these shipping methods:
-
flat rate
-
table rate
-
free shipping
are available in Vue Storefront, and PWA Studio, and they are easy to implement in custom storefronts.
How about other shipping methods?
Magento has a few other shipping methods:
-
In-Store Delivery
-
UPS
-
USPS
-
FedEx
-
DHL
In-Store Delivery
The in-store delivery method allows choosing a pickup point when a customer wants to pick up an order. This feature is not supported in PWA STUDIO and Vue Storefront when I write this article.
Magento 2 GraphQL allows to set pickup point as a shipping address, and it’s possible to fetch pickup points by using the pickupLocations query so I assume that it’s possible to create custom code that covers this functionality in custom headless storefronts.
UPS, USPS, FedEx, DHL
No support in PWA Studio and Vue Storefront. Custom development is needed.
Custom shipping methods
What about custom shipping methods? You may ask: Is GraphQL return information about custom delivery methods among the default ones?
Just for test, I created a new delivery method called “Custom Delivery.”
You can find the Magento 2 module containing this delivery method on my Github.
It’s returned from API, and available in PWA Studio, and Vue Storefront as well.
Summary
Shipping methods are available for PWA Studio, Vue Storefront, and custom headless storefronts through GraphQL queries, and they are displayed on the storefront. Custom shipping methods also are shown as well. In-Store pickup and other methods than free shipping, flat rate, and table rate are not supported and custom development is needed. Anyway, for many clients, the default shipping methods are good enough and they can consider a headless storefront as a possible solution. I expect that in the future, the amount of supported shipping methods will be bigger, and maybe some extensions from external providers will be available.