Delivery profiles migration guide

Delivery profiles are a new feature that provides shops with the ability to create shipping rates per product variant and per location. As delivery profiles become available to merchants, it’s important to understand the potential impact to your app. This document covers changes to the REST Admin API, and helps you transition to delivery profiles using the GraphQL Admin API.

For a more thorough explanation on new concepts introduced for delivery profiles in the GraphQL Admin API, see Getting started with delivery profiles.

Is my app affected by delivery profiles?

Your app might be impacted if you interact with the CarrierService or ShippingZone resources.

Single-origin shipping

In order to preserve the functionality of existing apps, the old way of determining shipping costs is preserved as single-origin shipping. Shops using single-origin shipping don’t have the delivery profiles structure, and instead have only shipping zones and rates. In contrast, merchants using delivery profiles can set up shipping methods for specific product variants based on where they're shipping from and where they're shipping to.

As part of the migration to delivery profiles, if a shop has a carrier service app, then it will remain in legacy mode until the merchant creates a new shipping profile from Shopify admin.

Changes to data structures

Using single-origin shipping, the data structure includes shipping zones and rates:

Profiles diagram

By comparison, delivery profiles include location groups, delivery zones and rates, enabling rates to be applied based on locations and zones. This is illustrated in the following diagram, where separate delivery profiles have been created for heavy items, fragile items, and all other items. The applicable rates are defined through the location groups and delivery zones.

Profiles diagram

Changes to Shopify resources

The delivery profiles feature impacts the following resources:

ShippingZone

The ShippingZone resource continues to return all zones defined within the shop’s shipping settings. When you retrieve shipping zones, the individual zones within the array will now return the following properties:

  • profile_id: The ID of the zone’s delivery profile
  • location_group_id: The ID of the zone’s location group
  • admin_graphql_api_id: The zone’s ID for use with the GraphQL Admin API

With single-origin shipping, shops have only one set of rates for a country, defined within a zone. Customers within that zone receive those rates. With delivery profiles, as demonstrated in the example, it’s possible for multiple zones to define rates for the same country.

View example

POST https://{shop}.myshopify.com/admin/api/2019-07/shipping_zones.json

Response

{
    "shipping_zones": [
        {
            "id": 322236742,
            "name": "Domestic",
            "profile_id": "gid://shopify/DeliveryProfile/4227128",
            "location_group_id": "gid://shopify/DeliveryLocationGroup/3014712",
            "admin_graphql_api_id": "gid://shopify/DeliveryZone/9961528",
            "countries": [
                {
                    "id": 368352006,
                    "name": "Canada",
                    "tax": 0.05,
                    "code": "CA",
                    "tax_name": "GST",
                    "shipping_zone_id": 9961528,

                }
            ],
            "weight_based_shipping_rates": [
                {
                    "id": 24739896,
                    "name": "Standard Shipping",
                    "price": "8.00",
                    "shipping_zone_id": 9961528,
                    "weight_low": 0,
                    "weight_high": 5
                },
                {
                    "id": 24772664,
                    "name": "Heavy Goods Shipping",
                    "price": "18.00",
                    "shipping_zone_id": 9961528,
                    "weight_low": 5,
                    "weight_high": 20
                }
            ],
            "price_based_shipping_rates": [],
            "carrier_shipping_rate_providers": [
                {
                    "id": 24805432,
                    "carrier_service_id": 11499078,
                    "flat_modifier": "0.0",
                    "percent_modifier": 0,
                    "service_filter": {
                        "*": "+"
                    },
                    "shipping_zone_id": 9961528
                }
            ]
        },
        {
            "id": 415649030,
            "name": "US ",
            "profile_id": "gid://shopify/DeliveryProfile/4227128",
            "location_group_id": "gid://shopify/DeliveryLocationGroup/3014712",
            "admin_graphql_api_id": "gid://shopify/DeliveryZone/9994296",
            "countries": [
                {
                    "id": 544907398,
                    "name": "United States",
                    "tax": 0,
                    "code": "US",
                    "tax_name": "Federal Tax",
                    "shipping_zone_id": 9994296,

                }
            ],
            "weight_based_shipping_rates": [
                {
                    "id": 24870968,
                    "name": "my weight based rate",
                    "price": "6.00",
                    "shipping_zone_id": 9994296,
                    "weight_low": 2,
                    "weight_high": 5
                }
            ],
            "price_based_shipping_rates": [
                {
                    "id": 24838200,
                    "name": "my price based rate",
                    "price": "10.00",
                    "shipping_zone_id": 9994296,
                    "min_order_subtotal": "10.0",
                    "max_order_subtotal": null
                }
            ],
            "carrier_shipping_rate_providers": []
        },


        {
            "id": 14286904,
            "name": "Canada",
            "profile_id": "gid://shopify/DeliveryProfile/7372856",
            "location_group_id": "gid://shopify/DeliveryLocationGroup/6094904",
            "admin_graphql_api_id": "gid://shopify/DeliveryZone/14286904",
            "countries": [
                {
                    "id": 368352006,
                    "name": "Canada",
                    "tax": 0.05,
                    "code": "CA",
                    "tax_name": "GST",
                    "shipping_zone_id": 14286904,
                    "provinces": []
                }
            ],
            "weight_based_shipping_rates": [],
            "price_based_shipping_rates": [],
            "carrier_shipping_rate_providers": [
                {
                    "id": 35684408,
                    "carrier_service_id": 11499078,
                    "flat_modifier": "0.0",
                    "percent_modifier": 0,
                    "service_filter": {
                        "*": "-"
                    },
                    "shipping_zone_id": 14286904
                }
            ]
        },
        {
            "id": 14614584,
            "name": "Canada",
            "profile_id": "gid://shopify/DeliveryProfile/7897144",
            "location_group_id": "gid://shopify/DeliveryLocationGroup/6619192",
            "admin_graphql_api_id": "gid://shopify/DeliveryZone/14614584",
            "countries": [
                {
                    "id": 368352006,
                    "name": "Canada",
                    "tax": 0.05,
                    "code": "CA",
                    "tax_name": "GST",
                    "shipping_zone_id": 14614584,
                    "provinces": []
                }
            ],
            "weight_based_shipping_rates": [],
            "price_based_shipping_rates": [],
            "carrier_shipping_rate_providers": [
                {
                    "id": 36044856,
                    "carrier_service_id": 11499270,
                    "flat_modifier": "0.0",
                    "percent_modifier": 0,
                    "service_filter": {
                        "*": "-"
                    },
                    "shipping_zone_id": 14614584
                }
            ]
        },
        {
            "id": 14647352,
            "name": "United States",
            "profile_id": "gid://shopify/DeliveryProfile/7929912",
            "location_group_id": "gid://shopify/DeliveryLocationGroup/6651960",
            "admin_graphql_api_id": "gid://shopify/DeliveryZone/14647352",
            "countries": [
                {
                    "id": 544907398,
                    "name": "United States",
                    "tax": 0,
                    "code": "US",
                    "tax_name": "Federal Tax",
                    "shipping_zone_id": 14647352,
                    "provinces": []
                }
            ],
            "weight_based_shipping_rates": [],
            "price_based_shipping_rates": [
                {
                    "id": 36077624,
                    "name": "conditional_rate",
                    "price": "20.50",
                    "shipping_zone_id": 14647352,
                    "min_order_subtotal": "100.0",
                    "max_order_subtotal": null
                }
            ],
            "carrier_shipping_rate_providers": []
        }
    ]
}

CarrierService

In the legacy implementation, Shopify makes a single request to a carrier service at checkout. In this request, the origin is always the location that's selected as the shop's shipping origin in the shop's shipping settings. With delivery profiles, the origin location is the location where the item is stocked.

For carts that contain items shipping from different locations or using different profiles, this can result in multiple calls to the carrier service.

Changes to shipping concepts

The new delivery profiles approach has implications for order routing, and the way rates are calculated and displayed.

Order routing

Within a cart or individual delivery profile, a line item can be delivered in more than one way. For example, the same product variant can be setup to ship to the same zone from different locations. In the example diagram, heavy items can be shipped to the Canada shipping zone from Location group 1 or Location group 2. In cases like this, Shopify determines priority based on inventory levels.

Cart splitting

With single-origin shipping, rates are determined using the zone of the customer’s location. With delivery profiles, carts can contain items that require different rates. In the example diagram, an order including both anvils and mirrors results in multiple rates and a split cart. In these cases, Shopify checks the appropriate zones for rates separately, which can result in multiple calls to carrier services.

Cart splitting also results in rate consolidation, where Shopify sums rates with identical names and displays them as a single value to the customer at checkout. For more information, see Rate consolidation.

Rate consolidation

With delivery profiles, carts can contain items that require different rates. When this happens Shopify simplifies the rates that are presented to the customer by performing rate consolidation. Rates with identical names (for example, Canada Post Express) are summed and displayed as a single value.

For example, suppose that the the delivery profiles for heavy and fragile items both define a delivery method called Standard. For heavy items, the rate is $50, and for fragile items it's $10. A cart that has one heavy item and one fragile item will show the Standard shipping method with a consolidated rate of $60. This is demonstrated in the following examples:

Profiles diagram

The cart displays the consolidated total to the customer:

Profiles diagram

FAQ

What happens if I don't migrate my app to support delivery profiles?

The array data structure returned by the ShippingZone resource has changed so that each zone contains new properties. If you don't change your app to account for these properties you might encounter unexpected behavior.

Also, under certain circumstances, carrier services will receive multiple requests for rates for a cart. This happens when a cart contains items that require different rates. For more information, see Cart splitting.

How can I tell if a store is using delivery profiles?

The ShippingZone resource from the REST Admin API will include the new delivery profile properties. Stores that don't opt-in to delivery profiles will be kept in legacy mode and won't return these properties.

You can also use the the following query to determine if the feature has been enabled for the shop:

query {
  shop {
    features {
      deliveryProfiles
    }
  }
}

How can I get help?

If you have questions about delivery profiles or you have trouble updating your app, then visit the Shopify Community forums to get help from the Shopify community.

Sign up for a Partner account to get started.

Sign up