Shipping Groups for Split Shipping
This guide explains how to implement shipping groups in your Elastic Path storefront for complex shipping scenarios. Shipping groups provide a structured approach when you need to split orders into multiple shipments with different addresses, delivery methods, or pricing.
Creating Shipping Groups
async function createShippingGroup(cartId, shippingData) {
try {
const response = await fetch(
`https://euwest.api.elasticpath.com/v2/carts/${cartId}/shipping-groups`,
{
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
data: {
type: "shipping_group",
name: shippingData.name,
description: shippingData.description,
shipping_address: shippingData.shipping_address,
delivery_instructions: shippingData.delivery_instructions,
// Shipping pricing
shipping_price: {
amount: shippingData.price_amount,
currency: "USD",
},
},
}),
},
);
const shippingGroup = await response.json();
return shippingGroup.data;
} catch (error) {
console.error("Failed to create shipping group:", error);
throw error;
}
}
Retrieving Shipping Groups
async function getCartShippingGroups(cartId) {
try {
const response = await fetch(
`https://euwest.api.elasticpath.com/v2/carts/${cartId}/shipping-groups`,
{
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
},
);
const shippingGroups = await response.json();
return shippingGroups.data;
} catch (error) {
console.error("Failed to retrieve shipping groups:", error);
throw error;
}
}
Updating Shipping Groups
async function updateShippingGroup(cartId, shippingGroupId, updateData) {
try {
const response = await fetch(
`https://euwest.api.elasticpath.com/v2/carts/${cartId}/shipping-groups/${shippingGroupId}`,
{
method: "PUT",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
data: {
type: "shipping_group",
...updateData,
},
}),
},
);
const updatedGroup = await response.json();
return updatedGroup.data;
} catch (error) {
console.error("Failed to update shipping group:", error);
throw error;
}
}
Split Shipping Example
Here's a complete example for handling split shipping to multiple addresses:
async function setupSplitShipping(cartId, cartItems) {
try {
// Group 1: Electronics to home address
const electronicsGroup = await createShippingGroup(cartId, {
name: "Electronics Shipment",
description: "Gaming console and accessories",
shipping_address: {
first_name: "John",
last_name: "Doe",
line_1: "123 Home St",
city: "New York",
region: "NY",
postcode: "10001",
country: "US",
},
delivery_instructions: "Leave at front door",
price_amount: 1500, // $15.00 express shipping
});
// Group 2: Gifts to office address
const giftGroup = await createShippingGroup(cartId, {
name: "Gift Shipment",
description: "Birthday gifts for colleague",
shipping_address: {
first_name: "John",
last_name: "Doe",
company_name: "Tech Corp",
line_1: "456 Office Blvd",
city: "New York",
region: "NY",
postcode: "10002",
country: "US",
},
delivery_instructions: "Deliver to reception",
price_amount: 500, // $5.00 standard shipping
});
// Associate items with shipping groups
await associateItemsWithShippingGroups(
cartId,
cartItems,
{
electronics: electronicsGroup.id,
gifts: giftGroup.id,
},
accessToken,
);
return {
electronicsGroup,
giftGroup,
};
} catch (error) {
console.error("Failed to setup split shipping:", error);
throw error;
}
}
async function associateItemsWithShippingGroups(
cartId,
cartItems,
groupMapping,
accessToken,
) {
for (const item of cartItems) {
// Determine which shipping group this item belongs to
const groupKey = item.group; // e.g., 'electronics', 'gifts', etc.
const shippingGroupId = groupMapping[groupKey];
if (!shippingGroupId) continue; // Skip if no group mapping
try {
const response = await fetch(
`https://euwest.api.elasticpath.com/v2/carts/${cartId}/items/${item.id}`,
{
method: "PUT",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
data: {
type: "cart_item",
shipping_group_id: shippingGroupId,
},
}),
},
);
if (!response.ok) {
throw new Error(
`Failed to update item ${item.id}: ${response.statusText}`,
);
}
console.log(
`Item ${item.id} associated with shipping group ${shippingGroupId}`,
);
} catch (error) {
console.error("Error associating item with shipping group:", error);
}
}
}
Combining Custom Items and Shipping Groups
You can use both approaches together for maximum flexibility:
import { addCustomItemToCart } from "@epcc-sdk/sdks-shopper";
async function hybridShippingApproach(cartId, shippingRequirements) {
// Use shipping groups for split deliveries
if (shippingRequirements.hasMultipleAddresses) {
await setupSplitShipping(cartId, shippingRequirements.addressGroups);
}
// Add custom items for additional fees
if (shippingRequirements.hasInsurance) {
await addCustomItemToCart({
path: { cartID: cartId },
body: {
data: {
type: "custom_item",
name: "Shipping Insurance",
sku: "SHIP-INSURANCE",
description: "Package protection coverage",
quantity: 1,
price: { amount: 299 }, // $2.99
},
},
});
}
if (shippingRequirements.hasHandlingFee) {
await addCustomItemToCart({
path: { cartID: cartId },
body: {
data: {
type: "custom_item",
name: "Special Handling",
sku: "SHIP-HANDLING",
description: "Fragile item handling fee",
quantity: 1,
price: { amount: 500 }, // $5.00
},
},
});
}
}
Next Steps
- Manage Shipping Options - For simple shipping with custom cart items
- Order Confirmation
- Customer Checkout