HomeShopify & E-commerceShopify fulfillment SLA time-to-ship report with…

Shopify fulfillment SLA time-to-ship report with n8n

Shopify fulfillment SLA time-to-ship report with n8n









A Shopify fulfillment SLA time-to-ship report with n8n answers a question most stores only guess at: how long does a paid order actually wait before it ships? Once a week this workflow reads the orders you shipped, measures the hours between order placed and order fulfilled, and reports the average, the median, and the share that met your SLA. The numbers land in a Google Sheet for the trend and in a Telegram message for a quick read, built in five n8n nodes.

What it does

Fast shipping is a promise, and most stores have no idea whether they keep it. Shopify shows individual orders, but it does not tell you that your average order took 31 hours to ship last week, or that 12 percent blew past your two-day target. Without that number you cannot tell whether fulfillment is improving, slipping, or fine.

This workflow turns raw orders into that number. On a schedule it pulls the orders shipped in the last week, calculates each one’s time from placed to fulfilled, and rolls the set up into a short report: how many orders shipped, the average and median hours to ship, and the percent that met your SLA. It writes one row to a Google Sheet so you build a week-over-week trend, and it sends a summary to Telegram. The message reads like this:

📦 Fulfillment SLA report (week ending 2026-09-01)
Orders shipped: 214
Avg time to ship: 28.6h
Median: 21.0h
Within 48h SLA: 91.6%

Now the promise has a scoreboard, and you see a slip the week it happens rather than when a customer complains.

Why it beats the default

The manual default is exporting orders to a spreadsheet and building the date math by hand, which almost no one keeps up weekly. Shopify’s analytics cover sales and traffic, but time-to-ship is not a report you can pull, so most teams simply do not track it. What you do not measure, you cannot improve.

An automated report runs itself and keeps history. Because each week appends a row, you get a trend line: the average creeping up before the holidays, the median dropping after you hired a packer. Compared with Shopify Flow, which is limited to Shopify Plus and does no aggregation, n8n does the math in a Code step and sends the result anywhere. You own the SLA number, the period, and the destination.

It also pairs naturally with a real-time delay alert. The alert catches the single order running late right now; this report tells you whether late orders are a pattern. Together they cover both the urgent and the strategic side of fulfillment speed.

What you need

  • A Shopify store on any plan, with an admin login that can create a custom app.
  • An n8n instance, either n8n Cloud or self-hosted (version 1.0 or newer).
  • A Shopify Admin API access token, created through the 2026 Shopify Dev Dashboard method. New to connecting the two? Follow connect Shopify to n8n (2026 guide) first.
  • A Google account with a Sheet to hold the weekly report, and a Telegram bot token plus the chat id for the summary.

Build time is about 25 minutes from scratch, or a couple of minutes if you import the ready-made template below and add your credentials.

Node-by-node list

Five nodes in a straight line. Here is each one and what it does.

# Node Type Job
1 Every Monday scheduleTrigger Runs the report once a week at a set hour.
2 Get fulfilled orders shopify Pulls recent orders, each carrying a created_at and a fulfillments array with ship times.
3 Compute SLA report code Filters to orders shipped in the window, computes hours-to-ship per order, and rolls up count, average, median, and percent within SLA.
4 Append to Sheet googleSheets Adds one row to your report sheet so weeks stack into a trend.
5 Send Telegram summary telegram Posts the week’s numbers to your team channel.

The report sheet

Create a Google Sheet first, with a header row whose columns match the fields the report produces exactly, because the append step maps input fields to columns by name.

Column Meaning Example
Period_end Date the report was run 2026-09-01
Orders_shipped Orders fulfilled in the window 214
Avg_hours_to_ship Average hours from placed to shipped 28.6
Median_hours_to_ship Typical order’s hours to ship 21.0
SLA_hours Your target, in hours 48
Pct_within_SLA Percent that met the target 91.6
📌

Note: the header names must match the field names above exactly, since the append step uses automatic mapping. Get them right once and every future run drops cleanly into place.

How it works

  [Every Monday]  (weekly schedule)
          |
          v
  [Get fulfilled orders]  (created_at + fulfillments[])
          |
          v
  [Compute SLA report]  (hours per order -> avg, median, % within SLA)
          |
          v
  [Append to Sheet]  (one row per week)
          |
          v
  [Send Telegram summary]  (the week's numbers)
  

Step-by-step build

  1. Create a new workflow in n8n and name it “Shopify fulfillment SLA report.”
  2. Add a Schedule Trigger node named “Every Monday.” Set it to run weekly, on Monday, at an early hour such as 7 AM, so the report covers the week just ended.
  3. Add a Shopify node named “Get fulfilled orders.” Set Authentication to Access Token and attach your credential. Resource Order, Operation Get Many, Return All on. Under Filters set Fulfillment Status to shipped and Created At Min to {{ $now.minus({ days: 10 }).toISO() }} so you pull a little more than a week and let the Code node trim to the exact window.
  4. Add a Code node named “Compute SLA report” after it, in Run Once for All Items mode. It reads every order, keeps those whose first fulfillment shipped within the last seven days, and computes the hours from created_at to the fulfillment time. It returns a single row with the count, average, median, SLA target, and percent within SLA. The SLA target lives in one line:
    const slaHours = 48;   // your target, in hours

    Change 48 to your own target and the whole report follows.

  5. Create a Google Sheet with the six header columns from the table above. Add a Google Sheets node named “Append to Sheet,” operation Append, and pick your document and sheet. Leave mapping on Auto-map Input Data so each computed field lands in its matching column.
  6. Add a Telegram node named “Send Telegram summary.” Attach your bot credential, set the chat id, and write a short message that reads the report values, for example the average with {{ $('Compute SLA report').item.json.Avg_hours_to_ship }}. Referencing the Code node by name keeps the numbers correct even though the Sheets step ran in between.
  7. Save, run the workflow once by hand to confirm a row appears in the Sheet and the Telegram message arrives, then toggle it Active.
💡

Tip: want a per-order breakdown, not just the weekly totals? Have the Code node return one item per order with its hours-to-ship, and point the Sheets append at a second tab. You then keep both a weekly trend and a line-by-line log you can sort to find the slowest orders.

Common mistakes

  • Counting unshipped orders. Time-to-ship only makes sense for orders that shipped. The Code node skips any order without a fulfillment, so a pile of open orders does not distort the average.
  • Header names that do not match. Auto-mapping writes by column name. If the sheet says Avg hours but the field is Avg_hours_to_ship, that column stays blank. Copy the names exactly.
  • Double counting across weeks. The cutoff keeps each run to orders shipped in the last seven days, so a run does not re-report last week’s orders. Keep the schedule and the cutoff on the same period.
  • Reading the wrong ship time. Use the created_at on the fulfillment, not the order’s updated_at, which changes for many reasons unrelated to shipping.
  • Referencing $json in the Telegram text. After the Sheets step, $json is the Sheets response. Pull the numbers from $('Compute SLA report') so the message shows the report, not the append result.

Cost at realistic volume

This workflow runs inside free tiers at normal store volume. The Shopify Admin API is included with your plan, Google Sheets is free, and Telegram messages are free. One weekly run reads a week of orders and writes a single row, which is nowhere near any rate limit.

On n8n, the cost is one execution a week that fans over the week’s orders in a single Code step. Even a store shipping thousands of orders a week runs this comfortably on n8n Cloud’s entry plans and free on self-hosted n8n. For the price of a few minutes of compute you get a fulfillment scoreboard you never have to assemble by hand.

Download the ready-to-import template

The guide above is free to follow, and building it by hand takes about 25 minutes. The template is the same validated workflow as a single .json import, so you skip the build and just add your credentials and sheet. Prefer it done for you? Our done-for-you setup service installs and tests it on your instance.

Download the template ($14) →

Instant download · Works on n8n Cloud and self-hosted

FAQ

What exactly counts as time-to-ship?

It is the gap between when the order was placed and when its first fulfillment was created. The report reads the order’s created_at and the created_at on its first fulfillment, then reports the difference in hours. That measures how long a paid order waited before it left your hands, which is the number your SLA is really about.

How do I change the SLA threshold or the period?

The SLA is one number in the Code node, set to 48 hours by default, so change it to your target. The period is set by the schedule and the seven-day cutoff in the same node. Move the schedule to daily or monthly and match the cutoff, and the report window follows. Both are one-line edits.

What about orders that have not shipped yet?

They are excluded on purpose. The report only measures orders that actually shipped in the window, because time-to-ship is undefined for an order still sitting unfulfilled. To watch the ones running late instead, pair this with a fulfillment delay alert that flags orders past your SLA before they ship.

Can I send the report somewhere other than Telegram and Sheets?

Yes. The Code node produces a small set of numbers, so any destination works. Swap the Telegram node for Slack, Discord, or a Gmail node, or drop the Sheets step if you only want the message. The calculation does not change, so you are only replacing the final delivery step.

Why report a median as well as an average?

A single very slow order can drag the average up and make a good week look bad. The median shows the typical order’s experience, unmoved by one outlier. Reading both tells you whether a high average is your whole operation slipping or just one stuck order, which points you at the right fix.

Related guides