Shipping and Delivery Overview
Overview of the concepts related to shipping and delivery of Orders in your Composable Commerce Project.
Shipping versus Delivery
We differentiate conceptually between the shipping addresses of the Cart and the delivery addresses of the Order.
- The shipping addresses captured during checkout represent the request of the customer as to where the individual items should be shipped.
- The delivery information captured for the Order represent how the Order is actually fulfilled.
Therefore, the delivery information is not automatically set on the Order based on which shipping addresses are set on the Cart. To map a shipping address to delivery information, use the Add Delivery update action.
Shipping addresses
If you are using the default ShippingMode Single
, you must set a shippingAddress
for the Cart before it can be converted into an Order.
The address stored in the shippingAddress
field of the Cart determines the following:
- The Shipping Methods that are available and their shipping rates
- The Tax Rate applied to each (Custom) Line Item and the shipping rate
For more information on how Composable Commerce calculates tax using the shippingAddress
field, see Cart tax rate selection.
Ship to a single address
To ship all (Custom) Line Items of the Cart to the same address using the same fulfillment method, use a single Shipping Method.
To ship all (Custom) Line Items of the Cart to the same address, using more than one fulfillment method, use multiple Shipping Methods.
Ship to multiple addresses
To ship individual items to different addresses while using a single Shipping Method, set the Cart's ShippingMode to Single
on CartDraft. Once set, the ShippingMode
field can not be changed.
The shippingAddress
field of the Cart is used for taxation purposes and must be set in the CartDraft or with the Set Shipping Address update action.
Any address that is bound to a Line Item or sub-quantity of a Line Item must be added to the itemShippingAddresses
field, which contains the complete set of addresses available for use by the Cart.
If a Line Item, or quantity of a Line Item is associated with an address listed in itemShippingAddresses
, this address can not be deleted. To delete the address, you must first update the Line Item shipping details and remove the reference.
Each address that you provide must have a key
that is unique to the Cart. The key
is required when assigning the respective shipping address to a Line Item in the ItemShippingTarget (used with the
Set LineItem ShippingDetails update action).
Shipping sub-quantities to different addresses
You can also ship sub-quantities of a Line Item to different addresses.
For example, if you have a Cart that contains 100
paper bags that must be shipped to three point-of-sale locations, you can specify the sub-quantities of the LineItem quantity
for each address.
Shipping address | Sub-quantity |
---|---|
address_1 | 10 |
address_2 | 40 |
address_3 | 50 |
{"id": "e38a6110-fc74-4095-bde5-9898375e6904","productId": "ed7f5333-6f5d-4d07-a44f-2a24885bae0c","name": {"en": "Branded paper bag"},"variant": {"id": 1,"sku": "sku_4002"},"price": {"value": {"currencyCode": "USD","centAmount": 4200},"id": "278af989-688a-4b60-a26f-bee2a2e40920"},"quantity": 100,"priceMode": "Platform","totalPrice": {"currencyCode": "USD","centAmount": 630000},"lineItemMode": "Standard","shippingDetails": {"targets": [{"addressKey": "address_1","quantity": 10},{"addressKey": "address_2","quantity": 40},{"addressKey": "address_3","quantity": 50}],"valid": true}}
When you set the Line Item shipping address, there is no enforcement that the sum of the shipping address quantities equals the LineItem quantity
. This allows the shipping addresses to be gathered and added to the Cart in a piecemeal way. However, to ensure data integrity, a boolean field called valid
exists to determine whether the sum of the shipping address quantities equal the LineItem quantity
.
A Cart is still considered valid even if valid
is false
. However, during Order creation, all valid
flags must be true
, otherwise the Order creation will be rejected.
To learn more, see our tutorial about multiple shipping addresses.
Shipping Methods
Shipping Methods model the fulfillment option that delivers your goods to the customer. For example, this could include shipping services like standard postal service, express delivery, or other options such as in-store collection.
You can define a default Shipping Method for a Project by setting the isDefault
boolean inside an individual Shipping Method. During the checkout process, you can check whether an available Shipping Method has isDefault
set to true, and if so, pre-select the option for the Customer.
You can set the shipping rates and the geographical area(s) covered by a Shipping Method using Zones.
Single Shipping Method
To ship all of the items in the Cart using a single Shipping Method, and therefore also the same tax rate selection criteria, set the Cart's ShippingMode to Single
on CartDraft. Once set, the ShippingMode
field can not be changed.
When using ShippingMode Single
, tax is calculated and applied to the contents of the Cart based on the address in the shippingAddress
field.
Multiple Shipping Methods
To ship individual items of an Order using different Shipping Methods, use ShippingMode Multiple
on CartDraft. For example, a customer wants to collect some items in person and have the rest sent by express delivery.
To add and assign Shipping Methods, do the following:
Specify any shipping addresses to be used by the Line Items in your Cart. For new Carts, you can specify addresses in the
itemShippingAddresses
field on CartDraft. For existing Carts, you can use the Add ItemShippingAddress update action, which adds the addresses to theitemShippingAddresses
field. TheitemShippingAddresses
field is the complete set of addresses available for use by the Cart.Use the Add Shipping Method or Add Custom Shipping Method (for externally managed Shipping Methods) update action to add Shipping Methods to a Cart. In the update action, you need to specify a
shippingAddress
for the Shipping Method. We recommend that you provide akey
for theshippingAddress
that matches thekey
of the corresponding address listed initemShippingAddresses
. TheshippingAddress
is used later to calculate tax for any associated (Custom) Line Item(s), or sub-quantities of a (Custom) Line Item.
- Assign a Shipping Method to each Line Item using the Set LineItemShippingDetails update action.
You can also ship items (or sub-quantities of an item) to different addresses located in other states, countries, or regions using multiple Shipping Methods, however, the following applies:
- The LineItem's or CustomLineItem's
perMethodTaxRate
field contains the individual Tax Rates applied within a single Line Item together with the Shipping Methods assigned to it. This field is equivalent to thetaxRate
field when using the default ShippingModeSingle
. - The LineItem's or CustomLineItem's
taxedPricePortions
field contains individual taxed prices of each Shipping Method. This is automatically calculated whenperMethodTaxRate
is set.
To learn more, see our multiple Shipping Methods tutorial and our Shipping Methods self-learning module.
Predicates
Predicates allow you define rule-based logic to determine which Shipping Methods are eligible for a Cart during checkout. To do this, add your predicate text to the predicate
field directly on each Shipping Method.
For example:
- Shipping Method "Express" should only be offered for Carts with Line Items that are eligible for express shipping.
- Shipping Method "Overnight" should not be offered to a certain segment of the customers.
- Shipping Method "Ground" is the only method available for Carts with bulky items weighing more than 10 kg.
- Shipping Method "Scandinavia" is the only method available for Carts in the Store for Sweden.
// matches a cart when at least one Line Item has the custom field attribute "eligible_for_express_shipping" set to TRUElineItemExists(attributes.eligible_for_express_shipping = true)// matches a cart for all customer group except onecustomerGroup.id != "f6a19a23-14e3-40d0-aee2-3e612fcb1bc7"// matches a cart when at least one Line Item has the custom field attribute "bulky" set to TRUE and when at least one Line Item has the custom field attribute "weightInKilograms" set to a value greater than 10lineItemExists(attributes.bulky = true) and lineItemExists(attributes.weightInKilograms > 10)// matches a cart with Store key "sweden-store"store.key = "sweden-store"
Shipping predicates take into account the entire scope of the Cart, regardless of associations to Line Items. For example, a Shipping Method with a predicate totalPrice > "100.00 USD"
will be applicable even if only $10 worth of goods is associated with it, so long as total Cart price satisfies the predicate. Similarly, this also applies to the Shipping Method's freeAbove
price.
The predicate language contains a list of logical operators and functions that can be used to express the conditions of a Shipping Method rule.
The evaluation of each predicate occurs during checkout, when you call Get ShippingMethods for a Cart. This method retrieves only the Shipping Methods which are valid, based on the rules of the predicate, for a particular Cart.
If you use the Set ShippingMethod update action with a Shipping Method that does not match the conditions of the Cart, the call will be perceived as an invalid operation and be rejected.
If the Cart is updated and its conditions no longer match the criteria of the selected Shipping Methods, the parameter shippingMethodState
found under the Cart's ShippingInfo changes from MatchesCart
to DoesNotMatchCart
. If you attempt to create an Order from a Cart that has ShippingMethodState with DoesNotMatchCart
, the Order creation will be rejected.
Shipping Rates
A shipping rate is the price that you charge customers for a Shipping Method. Shipping rates are defined in the Shipping Method's Zones.
Fixed shipping rates
A fixed shipping rate is a rate assigned to a Shipping Method that never changes, even if the content or the conditions of a Cart is modified.
Tiered shipping rates
The alternative to fixed shipping rates is tiered shipping rates. This allows you to set shipping rates that increase or decrease, based on the tiers that you define. For example, you might want the shipping rate to decrease based on the Cart value, meaning the more money the customer is spending, the cheaper the shipping becomes.
You can enable tiered shipping rates by setting the optional parameter ShippingRateInputType in Project Settings.
The ShippingRateInputType parameter requires one of three ShippingRatePriceTiers:
- CartValueType: the shipping rate maps to the sum of all Line Item totals and Custom Line Item totals (after discounts have been applied).
- CartClassificationType: the shipping rate maps to an abstract Cart categorization expressed through a string (for example,
Light
,Medium
,Heavy
). - CartScoreType: the shipping rate maps to an abstract Cart categorization expressed through an integer (for example, a cart score or weight range).
When you create a Cart, you can set the parameter shippingRateInput
on CartDraft which is used as look-up value to determine the shipping rate according to the defined tiers. If no value is set, or there is no tier for the value, the default shipping rate is used. An exception to this is when the ShippingRateInputType is set to CartValueType. In this case, the shipping rate is determined by the sum of all Line Item totals and Custom Line Item totals (via the totalPrice
field) after discounts have been applied.
Defining shipping tiers
After you set the ShippingRateInputType parameter, specify the tiers and the shipping rate they should map to. To do this, define the array called tiers
within the ShippingRate object.
The following examples illustrate tiered shipping rates for each input type.
CartValueType
In this example, the shipping rate gradually decreases until it becomes free of charge when the Cart value exceeds $100.
Shipping Rate Tier | Shipping Rate |
---|---|
Default | $4 |
> $50 | $3 |
> $75 | $2 |
> $100 | $0 |
CartClassificationType
In this example, if you don't provide a classification for a given Cart during checkout, the shipping rate defaults to $10. If you classify the Cart as Medium, the shipping rate is $25.
Shipping Rate Tier | Shipping Rate |
---|---|
Default | $10 |
Medium | $25 |
Heavy | $50 |
CartScoreType
In this example, the score represents the total weight of the Cart expressed in grams. A Cart with a combined weight of 50 grams or less, will have a shipping rate of $1.75. As the weight increases, the shipping rate increases.
Shipping Rate Tier | Shipping Rate |
---|---|
Default | $1.75 |
> 50 | $2.50 |
> 100 | $4.75 |
> 500 | $7.25 |
> 1000 | $10.50 |
In the following example, we'll use CartScoreType again, but we'll express the shipping rate as a linear PriceFunction. When a score is 35 or less, the shipping rate increases in set intervals. For scores higher than 35, the shipping rate is calculated based on the defined function. For example, a cart score of 40 results in a shipping rate of $10.
Shipping Rate Tier | Shipping Rate |
---|---|
Default | $2 |
> 5 | $3 |
> 15 | $6 |
> 25 | $8 |
> 35 | x - 30 |
Free shipping
To offer free shipping, use one of the following methods:
Free above: This option creates the discount at the Shipping Method level. This means that each Shipping Method can have a unique threshold amount. This is useful when you have multiple Shipping Methods with different cost structures. For example, if you have a Shipping Method for Express shipping, you can define a higher threshold amount since the costs are higher.
The Free above option is only available with fixed shipping rates.
To enable this option, set a freeAbove
value on ShippingRateDraft. Alternately, you can set this value inside individual Shipping Methods using the Merchant Center.
Free shipping is applied if the totalPrice
of the Cart (minus any previously added shipping costs) equals or exceeds the freeAbove
price.
- If the (Custom) Line Items' prices do not include taxes, the
totalPrice
value is calculated from the net total price of the (Custom) Line Items. - If the (Custom) Line Items' prices include taxes, the
totalPrice
is calculated from the gross total price of the (Custom) Line Items.
Cart discounts: This option applies the same free shipping threshold amount across all Shipping Methods by default. However, it is possible to restrict a Cart Discount to only certain Shipping Methods using Cart Predicates. To use this method, set the target
property of the CartDiscountDraft to CartDiscountShippingCostTarget.
We strongly recommend that you choose only one of these methods and not use both at the same time.
Shipping rate calculation
The shipping rate is calculated when at least one of the following occurs:
- The
shippingRateInput
field on the Cart is updated. - The
shippingMethod
is updated on ShippingInfo. - The ShippingRateInputType is CartValueType and the total price of the Cart changes.
- The
freeAbove
free shipping threshold value exists and the total price of the Cart changes.
Tax calculation
The TaxMode of the Cart determines how Composable Commerce applies tax.
Platform tax mode
When only one Shipping Method is used on the Cart, the address specified in the Cart's shippingAddress
field is used for determining the eligible Shipping Methods and their shipping rates, as well as the tax rates that are applied to (Custom) Line Items and shipping rate.
When a Cart contains multiple Shipping Methods, its taxedShippingPrice
field represents the sum of taxed prices across all Shipping Methods.
Individual Shipping Method prices are contained within their respective ShippingInfo objects under shipping
.
External tax mode
TaxModes External
and ExternalAmount
require the tax rate/amount to be manually set on each (Custom) Line Item and Shipping Method.
This requirement also applies to Carts with ShippingMode Multiple
, with the added constraint that the rates/amounts must be present for each Shipping Method associated with a given (Custom) Line Item. Update actions SetLineItemTaxRate, SetLineItemTaxAmount, SetCustomLineItemTaxRate, and SetCustomLineItemTaxAmount contain a shippingKey
parameter that you can use to define which method/address combination the rate is referring.