ShipStream Knowledge Base
Shopify

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.

Make sure you are familiar with the Scripting Basics before proceeding. If the logic you need is not specific to Shopify, consider a Before Create Order Script instead — those run for orders from every source, while the Order Transform Script runs only for orders imported by this Shopify subscription and additionally has access to the raw Shopify order data.

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, so print is the easiest way to confirm what your script did.

The 'order' Object

The order object contains the following properties:

PropertyDescription
storeThe 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.
itemsThe line items to be added to the Order. You may add, remove, or modify elements.
addressThe shipping address for the Order.
optionsAll other order properties, such as the shipping method and order note.
timestampA 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[*].qty reflects only the remaining unfulfilled quantity, and items[*].order_item_ref contains the Shopify line item ID (or a comma-separated list when multiple Shopify line items share the same SKU).
  • items[*].product provides the matching ShipStream Product data — including weight and dimensions in converted units such as weight_lb and weight_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 no product data.
  • options.shipping_method is 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 order data with its store, items, address, and options properties 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.