Shopify Order Transform Scripts
The Shopify integration receives order data from Shopify and translates it into ShipStream Orders. The Order Transform Script lets you apply your own custom logic to this translation using JavaScript, just before the Order is created. Common uses include assigning incoming orders to different Brands, adjusting line items, overriding the shipping method, and skipping orders or items that should not be fulfilled by ShipStream.
The script is configured per subscription in the Order Transform Script field of the subscription's Plugin Configuration section — see the Shopify Integration guide. A transform script is optional; most stores do not need one.
Script Context
The variables defined in the context of the script are:
order- the new order data that will be submitted to create the ShipStream Order. Modify this object to change the resulting Order.shopifyOrder- the order and Fulfillment Order information received from Shopify. Treat this object as read-only reference data for your conditions.shopifyFulfillmentRequestMessage- the message entered by the merchant when requesting fulfillment, or an empty string.
Other methods available are:
print(message)- record a debug message. The collected output is saved as a comment on the created Order, soprintis the easiest way to confirm what your script did.
The 'order' Object
The order object contains the following properties:
| Property | Description |
|---|---|
store | The Brand's store code the Order will be created under. Defaults to null, which selects the Merchant's default Brand. Set this to assign the Order to a different Brand. |
items | The line items to be added to the Order. You may add, remove, or modify elements. |
address | The shipping address for the Order. |
options | All other order properties, such as the shipping method and order note. |
timestamp | A read-only timestamp of the current time, useful for time-based conditions. |
Example (product data abbreviated):
{
"store": null,
"items": [
{
"sku": "T0003",
"qty": 1,
"order_item_ref": "12055235999998",
"product": {
"sku": "T0003",
"name": "Example T-Shirt",
"weight_lb": 0.4,
"weight_kg": 0.18,
"goods_type": "NORMAL"
}
}
],
"address": {
"firstname": "Miguel",
"lastname": "Donoso",
"company": "",
"street1": "8020 N Coltrane Ln",
"street2": null,
"city": "Tucson",
"region": "Arizona",
"region_code": "AZ",
"postcode": "85743",
"country": "US",
"phone": "5209999999",
"email": "migueldonoso@example.com"
},
"options": {
"unique_id": "25543659999",
"order_ref": "#15551",
"shipping_method": "ups_03",
"source": "shopify:acme-inc-3:fo#25543659999t#notify",
"note": "A note can go here"
}
}
Notes:
items[*].qtyreflects only the remaining unfulfilled quantity, anditems[*].order_item_refcontains the Shopify line item ID (or a comma-separated list when multiple Shopify line items share the same SKU).items[*].productprovides the matching ShipStream Product data — including weight and dimensions in converted units such asweight_lbandweight_kg— for use in conditions. It is available only while the script runs and is not submitted with the order. See the order.items*.product section of Before Create Order Scripts for the available fields. An item added by the script has noproductdata.options.shipping_methodis the result of your Carrier Service Methods or Shipping Method Translation rules; the script may override it. The order will fail to import if it is empty after the script runs.- The script must return the
orderdata with itsstore,items,address, andoptionsproperties intact — removing any of them causes the import to fail with "The Order Transform Script did not return the data expected."
The 'shopifyOrder' Object
The shopifyOrder object combines the Shopify order with the Fulfillment Order being imported. The most useful properties for script conditions are tags, note, note_attributes, shipping_lines, app, order_line_items (with each item's SKU and custom attributes), and the monetary totals.
Example:
{
"id": "4803026399999",
"app": {
"id": "gid://shopify/App/4999999",
"name": "Amazon by Codisto"
},
"billing_matches_shipping": true,
"created_at": "2023-06-30T16:12:03Z",
"currency": "USD",
"customer_locale": null,
"discount_codes": [],
"duties_incoterm": null,
"financial_status": "PAID",
"fulfill_at": null,
"fulfill_by": null,
"fulfillment_order_id": 25543659999,
"fulfillment_request": {
"message": "Latest user-provided message",
"notify_customer": true
},
"name": "#15551",
"note": "A note can go here",
"note_attributes": [
{
"key": "Amazon Order Id",
"value": "114-9999999-9999999"
},
{
"key": "Amazon Account",
"value": "ACME Inc."
}
],
"presentment_currency": "USD",
"processed_at": "2023-06-30T16:12:03Z",
"reference": "114-9999999-9999999",
"tags": [
"Amazon-US",
"FBM"
],
"test": false,
"total_discounts": "0.0",
"total_duties": null,
"total_price": "399.98",
"subtotal_price": "399.98",
"total_shipping": "0.0",
"total_weight": "9979",
"updated_at": "2023-06-30T23:17:02Z",
"shipping_address": {
"id": 210568299999,
"address1": "8020 N Coltrane Ln",
"address2": null,
"city": "Tucson",
"company": "",
"country": "United States",
"country_code": "US",
"email": "migueldonoso@example.com",
"first_name": "Miguel",
"last_name": "Donoso",
"phone": "5209999999",
"province": "Arizona",
"province_code": "AZ",
"zip": "85743"
},
"shipping_lines": [
{
"title": "Amazon Standard",
"code": "AMZSTD",
"source": "amazon",
"carrier_identifier": null,
"custom": false
}
],
"line_items": [
{
"id": 479097618467,
"fulfillment_order_id": 25543659999,
"quantity": 1,
"line_item_id": 12055235999998,
"inventory_item_id": 7238532562979,
"fulfillable_quantity": 1,
"variant_id": 7239969996835
}
],
"order_line_items": [
{
"id": "12055235999998",
"sku": "T0003",
"quantity": 1,
"current_quantity": 1,
"custom_attributes": [
{
"key": "ASIN",
"value": "B075XX5JF4"
}
]
}
]
}
Skipping Orders and Items
To prevent an order from being created at all, set order.skip:
order.skip = true
The Fulfillment Order will not be imported and the fulfillment request in Shopify is rejected with a message indicating the order was skipped by the transform script, so it remains visible to the merchant that ShipStream will not fulfill it.
To omit individual line items, set skip on the item:
order.items.forEach(item => {
if (item.sku.startsWith('DIGITAL-')) {
item.skip = true
}
})
Skipped items are excluded from the created Order. If every item is skipped, the whole order is treated as skipped.
Examples
Assign orders to a Brand based on a Shopify tag:
if (shopifyOrder.tags.includes('Amazon-US')) {
order.store = 'acme_amazon'
print('Assigned to the Amazon brand based on the Amazon-US tag.')
}
Override the shipping method for heavy orders:
let totalWeightLb = order.items.reduce((total, item) => total + item.qty * ((item.product || {weight_lb: 0}).weight_lb), 0)
if (totalWeightLb > 50) {
order.options.shipping_method = 'ups_03'
print('Total weight ' + totalWeightLb.toFixed(1) + ' lb - switched to UPS Ground.')
}
Copy a custom attribute into the order note:
let amazonOrderId = (shopifyOrder.note_attributes.find(attr => attr.key === 'Amazon Order Id') || {}).value
if (amazonOrderId) {
order.options.note = 'Amazon Order Id: ' + amazonOrderId
}
Skip test orders placed by a specific app:
if (shopifyOrder.test || shopifyOrder.app.name === 'Some Testing App') {
order.skip = true
}
Debugging
- Anything written with
print()is saved as a comment on the created Order, so you can review the script's decisions on the order's history. - If the script throws an error or returns invalid data, the order fails to import and the fulfillment request is rejected with the error message. The error also appears at System -> Integrations -> Errors (see Error Handling). After correcting the script, click Request fulfillment on the Shopify order to retry.