HomeShopify & E-commerceShopify return rate by product report…

Shopify return rate by product report with n8n

Shopify return rate by product report with n8n









A Shopify return rate by product report with n8n tells you the one thing a blended refund number hides: which products keep coming back. Once a month this workflow reads your recent orders and their refunds, groups units sold and units returned by product, and writes a ranked table to Google Sheets. The item at the top of that list is where a photo, a size chart, or a supplier is quietly costing you money. Built in four n8n nodes, no manual spreadsheet math.

What it does

Every store has an overall return rate, and it is nearly useless on its own. A store at 8 percent might have forty products returning at 2 percent and three returning at 40 percent. The average tells you nothing about which three to fix. You need the rate per product, and Shopify does not report it.

This workflow builds it. On a schedule it pulls the orders from your report window, reads each order’s line items for units sold and its refund line items for units returned, and groups both by product. Then it computes a return rate for every product and writes the ranked result to a Google Sheet, worst offenders first. A report looks like this:

Product                     Ordered  Refunded  Return rate
Merino Crew Sweater             120       31       25.8%
Slim Chino Pant                  95       14       14.7%
Canvas Tote Bag                 210        9        4.3%
Ceramic Mug 12oz                340        4        1.2%

The Merino Crew line is doing real damage, and now you can see it, name it, and go fix the cause.

Why it beats the default

The manual default is exporting orders and refunds to a spreadsheet and building the per-product math by hand, which is fiddly enough that almost no one does it monthly. Shopify’s analytics show returns in aggregate, not a clean per-product rate you can sort and act on. So the products that quietly drive most of your refunds stay invisible.

An automated report surfaces them and keeps a history. Because each run appends dated rows, you can watch a product’s return rate fall after you swap a supplier or fix a size chart, which is the proof that your fix worked. Compared with Shopify Flow, which is limited to Shopify Plus and does no aggregation, n8n does the grouping in a Code step and sends the table anywhere you like.

It also completes the returns picture. A refund tracker logs each refund as it happens; this report turns those refunds into a rate per product, so you move from “we refunded $2,400 last month” to “this one product is why.”

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 report.

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

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

# Node Type Job
1 First of month scheduleTrigger Runs the report once a month at a set hour.
2 Get orders shopify Pulls recent orders of any status, each carrying line_items and a refunds array.
3 Return rate per product code Groups units ordered and units refunded by product, then computes and ranks the return rate.
4 Append to Sheet googleSheets Writes one row per product to your report sheet, worst return rate first.

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
Product Product title Merino Crew Sweater
Product_id Shopify product id 8123456789
Units_ordered Units sold in the window 120
Units_refunded Units refunded in the window 31
Return_rate_pct Refunded divided by ordered 25.8
📌

Note: the header names must match the field names above exactly, since the append step uses automatic mapping. One product gets one row per run, so filtering the sheet by Product gives you that product’s return-rate trend over time.

How it works

  [First of month]  (monthly schedule)
          |
          v
  [Get orders]  (line_items + refunds[])
          |
          v
  [Return rate per product]  (ordered vs refunded units, grouped by product)
          |
          v
  [Append to Sheet]  (one ranked row per product)
  

Step-by-step build

  1. Create a new workflow in n8n and name it “Shopify return rate by product.”
  2. Add a Schedule Trigger node named “First of month.” Set it to run monthly, on day 1, at an early hour such as 7 AM.
  3. Add a Shopify node named “Get orders.” Set Authentication to Access Token and attach your credential. Resource Order, Operation Get Many, Return All on. Under Filters set Status to any (so refunded and closed orders are included) and Created At Min to {{ $now.minus({ days: 35 }).toISO() }}.
  4. Add a Code node named “Return rate per product” after it, in Run Once for All Items mode. It walks each order’s line_items to tally units sold per product and its refunds[].refund_line_items to tally units returned, groups both by product id, and returns one row per product with the return rate, sorted worst first. The window is one line:
    const cutoff = $now.minus({ days: 35 }).toMillis();

    Widen it to 60 or 90 days if your returns arrive later.

  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 product row lands in the matching columns.
  6. Save, run the workflow once by hand, and confirm your products appear in the Sheet with ordered, refunded, and rate filled in. Then toggle it Active.
💡

Tip: turn the report into an alert. Add an IF after the Code node that keeps only products with Return_rate_pct over, say, 20, and send those to Telegram. You get the full monthly table in Sheets and an immediate ping whenever a product crosses your pain threshold.

Common mistakes

  • Leaving the status filter on the default. Shopify’s order list defaults to open orders. Set Status to any or you miss the closed and refunded orders that carry the returns you are counting.
  • Dividing by the wrong base. Return rate is refunded units over ordered units for that product, not over total store orders. The Code node keeps each product’s own counts, so the rate is per product.
  • Header names that do not match. Auto-mapping writes by column name. If a header is off by a character, that column stays blank. Copy the field names exactly.
  • Too short a window for slow returns. If most returns land 40 days out, a 35-day window undercounts them. Match the window in both the filter and the Code node to how long your returns actually take.
  • Reading refunds as money. This report counts refunded units, not refunded dollars. A partial-dollar refund with no unit returned will not inflate the rate, which is what you want for a returns signal.

Cost at realistic volume

This workflow runs inside free tiers at normal store volume. The Shopify Admin API is included with your plan, and Google Sheets is free. One monthly run reads a month of orders and writes a handful of product rows, well within any rate limit.

On n8n, the cost is one execution a month that fans over the window’s orders in a single Code step. Even a store doing thousands of orders a month runs this comfortably on n8n Cloud’s entry plans and free on self-hosted n8n. In exchange you get the one report that points straight at the products quietly driving your refunds.

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 ($16) →

Instant download · Works on n8n Cloud and self-hosted

FAQ

How is the return rate calculated?

For each product, it is refunded units divided by ordered units, across the orders placed in the report window. The workflow reads every order’s line items for units sold and its refund line items for units returned, groups both by product, and reports the percentage. That gives a per-product rate rather than one blended store number.

Does it count returns or refunds?

It counts refunded line items, because a refund is the concrete signal Shopify records when a return is accepted. If you issue a refund without the item coming back, or refund partially, the units refunded reflect exactly what you refunded. For most stores that tracks real returns closely enough to spot problem products.

Why does a product show up with zero returns?

Because it sold in the window but nothing was refunded, which is a healthy result worth seeing. The report lists every product that had orders, sorted by return rate, so your clean performers sit at the bottom and your problem products rise to the top where they belong.

Returns lag behind orders. How do I handle that?

The default window is the last 35 days, which suits fast-moving stores. If your returns arrive weeks later, widen the window in the Code node and the Shopify filter to 60 or 90 days. You are measuring the return rate of a cohort of orders, so a longer window captures more of their eventual returns.

Can I change the period or send it elsewhere?

Yes. The schedule sets how often it runs and the window is one line in the Code node. The report is a set of rows, so besides Google Sheets you can add a Telegram or Slack step that flags any product over a return-rate threshold, turning the monthly report into an alert when a product starts coming back too often.

Related guides