< Back to blog

Integrating Shippo as a custom shipping option at the checkout

Commerce.js is on a mission to give power to both the developer and the business at the checkout. Our latest milestone has been the introduction of a new update checkout API that can be used to customize requirements during the checkout process. Currently, the update checkout API only supports introducing your own shipping methods, but we’re working to expand its coverage to tax, and other areas that impact the total order value of the checkout.

Solving the Shipping cost problem

Providing realtime shipping costs is an essential part of any checkout experience in 2021. Customers want to know exactly how much it will cost to ship their product to them. The same goes for businesses who need to communicate a competitive and realistic cost of shipping to the customer. Using a Shipping API that can calculate live shipping rates at the checkout solves this problem for both business and customer.

To provide a clear example of how the update checkout API works, we will integrate a Shipping API at the checkout that will give customers the freedom to choose a shipping method that is best value for them. This also allows the merchant (me in this case) to control what shipping options are available from the Shipping API's dashboard, with the confidence that money will not be lost by charging only an estimated shipping cost, rather than the true cost provided by the carrier.

For this example, we’ll be integrating Shippo as the “Shipping API” . Shippo interfaces directly with shipping carriers around the world, and can integrate with these carriers to print labels for packages in real time. With this, we could also provide immediate tracking numbers with order confirmations (depending on support with the carrier), and provide realistic estimates on shipping times for our customers.

Let’s get started

To start, create a copy of the open source ChopChop demo store using the Chec CLI:

$> chec login
$> chec demo-store commercejs-chopchop-demo chopchop-shippo
✔ Downloaded commercejs-chopchop-demo to /Users/guymarriott/projects/tmp/chopchop-shippo

chopchopmarketing

We now have a store, and products that make sense for physical fulfillments. Now, in the Chec dashboard, add the shipping zones we want to ship to. This is an important step as we still want to use Commerce.js to provide valid destination countries. Next, create a single zone with the Chec Dashboard called “Valid Shippo destinations”, and add a single rate called “unused” (priced at $0.00). You’ll see why we’ve named this “unused” later.

Edit Shipping Zones

Finally, ensure that this rate is enabled on each product that requires a delivery.

Set shipping options

Configuring shipping costs with Shippo

Next, let’s look at the requirements for calculating shipping costs with Shippo. Looking at their API reference, they have a create a new shipment API that provides the information we need. The response provides us shipping rates, with carrier names and estimated shipping dates. We can then eventually use this shipment to manage the label and interaction with the carrier.

We need a few things to power this API; the origin address, the destination address, and details on the packages we wish to send. Our destination address is easy, the customer must provide that anyway. The origin address is information that is entered into the Chec dashboard, and can be fetched with Commerce.js. The details required for the parcels is a little more involved. Each product will have its own attributes. Luckily, the Chec API allows us to add arbitrary attributes to our products using the meta attribute on any resource. We can specify our package dimensions and weights with this API:

$> curl -X PUT "https://api.chec.io/v1/products/prod_8XO3wpgq4lYAzQ" \
    -H "Content-Type: application/json" \
    -H "X-Authorization: sk_abc123" \
    -d "{
          \"product\": {
            \"meta\": {
              \"shipping\": {
                \"height\": 3,
                \"width\": 5,
                \"length\": 36,
                \"weight\": 550,
                \"distance_unit\": \"cm\",
                \"mass_unit\": \"g\"
              }
            }
          }
        }"

In this case, we are setting the dimensions and weight for the “Walnut Cook's Tools” product. We can do the same thing for each product being sold.

Connecting to the update checkout API

Now that we have configured the Shippo API, we now need to tie it into the existing ChopChop store using Commerce.js and the update checkout API. The update checkout API we’ve developed is a secret key API. It allows you to take control of specific requirements of your checkout, which need to be fulfilled by the customer using the checkout. If this were a public API, a tech savvy user could update their own checkout in order to pay less — a security hole for sure. The approach that we’ve taken here is to develop a serverless function that will be a drop-in replacement for Commerce.js’s get shipping methods API.

You can see the finished serverless function here: https://github.com/chec/shippo-integration-example/blob/master/pages/api/shipping.js

I’ve created a function, using the Next.js API routes feature, that takes the checkout token and delivery address for the checkout. We’ll use Commerce.js to fetch details about the products in the checkout, and at the same time, fetch details about the merchant so that I will have the origin address (where the package originates from). Once I have details on the line items in the checkout, we can fetch the specific details for each product in the checkout, including the dimension and weight data we attached to each product earlier. We can then use this information to create the shipment in Shippo.

The final step here is where the real power of the new API we’ve developed is shown. We can use this secret key API to completely replace the shipping options provided by Commerce.js. Normally when we use Commerce.js to fetch shipping methods, the zero dollar “unused” shipping rate will be returned as it’s the rate configured in the dashboard. What we can do instead is use the shipping rates provided by Shippo and update the checkout so that they are the only valid rates for shipping. In the serverless function that is being used, the update checkout API sets the shipping methods, and the response will give me the new state of the checkout after that change is applied. We can then return the valid shipping methods from the new API route.

What does this look like in practice? Well, now we can cURL the new API:

$> curl -X GET "http://localhost:3000/api/shipping?token=chkt_2JwrB4pbWgXjwP&address={\"name\":\"Guy\",\"street1\":\"301/318 Homer St\",\"city\":\"Vancouver\",\"zip\":\"V6B2V2\",\"state\":\"BC\",\"country\":\"CA\"}" \
    -H "Accept: application/json"

We’ve provided the checkout token and address, and the API route will use this information to:

  • Fetch the origin address from the merchant details
  • Pull the items chosen by the customer for the checkout
  • Generate a list of packages that will be sent to the customer should they complete the order
  • Use Shippo to get real quotes from carriers to deliver the packages
  • Update the Commerce.js checkout so the shipping options provided by Shippo are the only valid options
  • Return the shipping options

The response will look something like this:

[
  {
    "id": "40dae94b17664fafbf8e5eb544771439",
    "description": "USPS: Priority Mail International",
    "provider": "",
    "price": {
      "raw": 41.09,
      "formatted": "41.09",
      "formatted_with_symbol": "$41.09",
      "formatted_with_code": "41.09 USD"
    },
    "countries": [],
    "regions": []
  },
  {
    "id": "c0dae6ca4f7b4d8888ef5b0a8210fa85",
    "description": "USPS: Priority Mail Express International",
    "provider": "",
    "price": {
      "raw": 51.81,
      "formatted": "51.81",
      "formatted_with_symbol": "$51.81",
      "formatted_with_code": "51.81 USD"
    },
    "countries": [],
    "regions": []
  }
]

This output is exactly the same as the get shipping methods API provided by Commerce.js. The IDs listed here will also work with the rest of the shipping APIs provided by Commerce.js — so we don’t need to do anything further to make this work, all the existing functionality built into the ChopChop demo store will still work ✨!

Shipping integrated

What’s next

I didn’t dive into the details about what should happen after the order is completed, but Commerce.js allows you to attach attributes to orders as you capture the checkout, again using the meta attribute. The shipping method ID that was used will be available with the shipping information on the order. Then we can build another serverless function that is invoked by a webhook (when the order is created) to finalize the shipment with Shippo, and generate shipping labels if required.

Take a look at our blog on using webhooks with Twilio for more examples of using webhooks to automate your flows after the checkout.

What about other shipping providers?

While I’ve chosen Shippo in this example, the process of integrating any shipping provider is the same, and you can implement your custom business rules with your own serverless functions.

Resources and Community

Check out our documentation and community articles.

Join our community on Slack to connect with eCommerce developers from around the world. Share your projects with us, ask questions, or just hang out!

Join our community
Dev community image