Building a Shopify Carrier Service App

Rob Olmos
Vice President, CTO

This article will show you how relatively straight forward it is to build a Shopify Carrier Service that integrates with your store.

What is a Shopify Carrier Service?

Shopify is a managed e-commerce platform that allows integration via the use of Apps. Apps can have access to the Carrier Service API that allows Shopify stores to incorporate custom shipping methods. It does so by making an external API request to the app and retrieves the carrier/shipping descriptions and prices.

The Carrier Service allows for real-time accurate pricing of shipments at the time of checkout, or can also be a method for more advanced custom shipping quotes. Shopify’s marketplace has several carrier service apps available but if you use a carrier that Shopify doesn’t have an app for then this also allows you to incorporate them into your store.

The Carrier Service API is pretty straight forward. When a user initiates a checkout, Shopify will send a request to your app’s end point with the customer & cart details, and expects a response with one or more shipping options & costs. Eg, Next Day, Standard, etc. These options are combined into a list and displayed to the user to pick one. If the API end point doesn’t return a response then it doesn’t display any options for that Carrier Service.

Let’s get started!

Now that we have an understanding of the basics, let’s put a very simple Carrier Service app together using some JSON, a simple PHP script, a web server of some sort to host and execute the PHP, and the Carrier Service Shopify API docs. This example will be using a Private App for simplicity and skip over OAuth handling.

If you intend to build an app for multiple stores to utilize start with a Public App, even if it’s unlisted, so that later on you won’t have to deal with converting your app and clients won’t have to convert their store’s integration with your app.

In your store, create a private app and enable write permissions for Shipping. This will generate tokens that your app your will use to register a Carrier Service within the store. Here’s how to create create a private app via the Shopify docs.

With the private app created, Shipping permissions granted, and API credentials available let’s continue. Here’s the JSON we built to be used in the next cURL call. We saved this with the filename “carrier_service.json”:

{
    "carrier_service": {
    "name": "Endertech Carrier Demo",
    "callback_url": "http:\/\/shopify-sandbox.endertech.net/rates.php",
    "service_discovery": true
    }
}

Then the cURL call to create the Carrier Service within the store:

curl -X POST -d @carrier_service.json -H"Accept:application/json" -H"Content-Type:application/json" -H"X-Shopify-Access-Token:abc123efg456" https://endertech-sample-store.myshopify.com/admin/carrier_services

Execute the cURL code and you can then execute this next cURL call to see the service listed:

curl -X GET -H"Accept:application/json" -H"X-Shopify-Access-Token:abc123efg456" https://endertech-sample-store.myshopify.com/admin/carrier_services

You should see a JSON response with your Carrier Service listed. Now we’ll create a very simple rates.php file to parse Shopify’s JSON, calculate some shipping dates and rates, and return the proper response. Here it is:

<?php
// log the raw request -- this makes debugging much easier
$filename = time();
$input = file_get_contents('php://input');
file_put_contents($filename.'-input', $input);

// parse the request
$rates = json_decode($input, true);

// log the array format for easier interpreting
file_put_contents($filename.'-debug', print_r($rates, true));

// total up the cart quantities for simple rate calculations
$quantity = 0;
foreach($rates['rate']['items'] as $item) {
    $quantity =+ $item['quantity'];
}

// use number_format because shopify api expects the price to be "25.00" instead of just "25"

// overnight shipping is 5.50 per item
$overnight_cost = number_format($quantity * 5.50, 2, '', '');
// regular shipping is 2.75 per item
$regular_cost = number_format($quantity * 2.75, 2, '', '');

// overnight shipping is 1 to 2 days after today
$on_min_date = date('Y-m-d H:i:s O', strtotime('+1 day'));
$on_max_date = date('Y-m-d H:i:s O', strtotime('+2 days'));

// regular shipping is 3 to 7 days after today
$reg_min_date = date('Y-m-d H:i:s O', strtotime('+3 days'));
$reg_max_date = date('Y-m-d H:i:s O', strtotime('+7 days'));

// build the array of line items using the prior values
$output = array('rates' => array(
    array(
        'service_name' => 'Endertech Overnight',
        'service_code' => 'ETON',
        'total_price' => $overnight_cost,
        'currency' => 'USD',
        'min_delivery_date' => $on_min_date,
        'max_delivery_date' => $on_max_date
    ),
    array(
        'service_name' => 'Endertech Regular',
        'service_code' => 'ETREG',
        'total_price' => $regular_cost,
        'currency' => 'USD',
        'min_delivery_date' => $reg_min_date,
        'max_delivery_date' => $reg_max_date
    )
));

// encode into a json response
$json_output = json_encode($output);

// log it so we can debug the response
file_put_contents($filename.'-output', $json_output);

// send it back to shopify
print $json_output;

Time to test

Now let’s test it out! In your demo store that you created the private app, if you don’t already have a product create one, then add it to your cart and initiate a checkout. Enter your shipping information and click “Continue to shipping method”. On the next page the “Shipping method” box will load the rates. At this point is when Shopify contacts your API, and if successful, you should see something like this screenshot (remember the rates will be different depending on the quantity):

Shopify Carrier Service shipping rates in a list form

Screenshot of a demo Shopify store’s shipping methods presented during checkout with our custom Carrier Service results included.

Did yours look similar? Congratulations on building your Shopify Carrier Service! Try it out some more by editing the quantity and initiating another checkout. The shipping rates should change as well. Watch out that Shopify caches the results so if your cart contents or shipping information doesn’t change then you’re likely to not see your shipping rates change.

Where do I go from here?

From this foundation you’ll likely further expand this integration, such as bridging with an actual carrier’s API, or adding custom logic such as loyalty rewards to give specific users free or discounted shipping.

Do you have an idea in mind or a Shopify store you’re looking to expand the functionality of? Let us help! Contact us today.

- Rob OlmosVice President, CTO | 

Filed under: <E-commerce>