HomeShopify & E-commerceShopify profit margin tracker with Google…

Shopify profit margin tracker with Google Sheets and n8n

Shopify profit margin tracker with Google Sheets and n8n







A Shopify profit margin tracker built with Google Sheets and n8n turns your raw paid orders into a per-order net-margin report every week, without paying for another analytics app. Shopify shows you revenue, but revenue is not profit. This workflow pulls each paid order, matches every line item to its cost from a simple Google Sheet, subtracts an estimated payment fee, and logs the real net margin per order so you can see which sales actually made money and which quietly lost it.

What it does

Once a week the workflow wakes up on a schedule, asks Shopify for every paid order from the last seven days, and reads a Google Sheet where you have listed the unit cost of each SKU. For every order it computes revenue, cost of goods sold, an estimated payment fee, gross profit, net profit, and a net margin percentage. It writes one row per order to a Margin Report tab and emails you a plain summary: total revenue, total net profit, average margin, and the five lowest-margin products in the period.

The result is the number most Shopify dashboards hide. You stop guessing whether a busy week was a profitable week, and you get an early warning when a discount, a supplier price rise, or a heavy-shipping product starts eating your margin.

Take an order for three units of SKU MUG-01 at $18 each. Revenue is $54. If the sheet lists a unit cost of $7, cost of goods is $21. The estimated fee is 2.9 percent of $54 plus 30 cents, about $1.87. Gross profit is $33 and net profit is $31.13, a net margin near 57.6 percent. That single row is what the workflow writes to your sheet, and rolling it up across the week is what the email reports.

Why it beats the default

Shopify Analytics reports gross sales, discounts, and returns, but it does not know your cost of goods. Neither does it net out payment processing fees per order. That leaves most store owners exporting orders to a spreadsheet by hand, pasting in costs, and rebuilding the same formulas every month. Third-party profit apps solve it, but they charge a monthly fee and want deep access to your store.

This approach keeps the cost data in a sheet you own, runs on your own n8n instance, and costs nothing beyond the accounts you already have. Because costs live in a spreadsheet rather than buried in the automation, anyone on your team can keep them current. And since it is n8n, you can later branch the same order data into Slack alerts, restock triggers, or a monthly PDF without rebuilding anything. See the full n8n Shopify automation hub for related builds.

What you need

  • An n8n instance, either the free self-hosted community edition or n8n Cloud.
  • A Shopify store and access to the Admin API. Follow the 2026 Dev Dashboard method in our connect Shopify to n8n guide to create a custom app and copy its Admin API access token. The old admin custom-app screen has been removed, so use the Dev Dashboard flow.
  • A Google account for Google Sheets (cost data plus the report) and Gmail (the summary email).
  • A Google Sheet with two tabs: a COGS tab holding SKU and Unit Cost columns, and a Margin Report tab with the nine report headers.

Build time is about 30 to 40 minutes from scratch, or under 10 minutes if you import the ready-made template below.

Node-by-node list

Seven nodes, wired in a straight line from schedule to email:

[Weekly schedule] -> [Config] -> [Get paid orders] -> [Read COGS]
        -> [Compute margins] -> [Append margin report] -> [Email summary]
  
  • Weekly schedule (Schedule Trigger) fires every Monday at 6am.
  • Config (Set) holds the lookback window and the payment fee assumptions in one place.
  • Get paid orders (HTTP Request) calls the Shopify Admin API for paid orders in the window.
  • Read COGS (Google Sheets) reads your SKU-to-cost table.
  • Compute margins (Code) joins orders to costs and does the math.
  • Append margin report (Google Sheets) writes one row per order.
  • Email summary (Gmail) sends the period totals and the worst-margin products.

Step-by-step build

  1. Add a Schedule Trigger named Weekly schedule. Set the interval to weeks, every 1 week, on day 1 (Monday) at hour 6. This defines how far back each run looks together with the next node.
  2. Add a Set node named Config. Create three fields: createdMin as a string with the expression {{ $now.minus({ days: 7 }).toISO() }}, feeRate as a number set to 0.029, and flatFee as a number set to 0.3. Adjust the fee values to match your payment provider.
  3. Add an HTTP Request node named Get paid orders. Method GET, URL https://YOUR_STORE.myshopify.com/admin/api/2026-04/orders.json. Set authentication to Generic Credential Type, Header Auth, and create a header credential with name X-Shopify-Access-Token and your Admin API token as the value. Turn on Send Query Parameters and add status=any, financial_status=paid, created_at_min={{ $json.createdMin }}, limit=250, and fields=id,name,created_at,customer,line_items,financial_status.
  4. Add a Google Sheets node named Read COGS. Operation Read Rows, pick your spreadsheet, and select the COGS tab. This returns one item per SKU with its unit cost.
  5. Add a Code node named Compute margins. Paste the join-and-calculate script from the template. It builds a SKU-to-cost map from Read COGS, walks each order’s line items, and outputs one item per order plus a shared summary block.
  6. Add a Google Sheets node named Append margin report. Operation Append, select the Margin Report tab, and map the nine columns: Date, Order, Customer, Revenue, COGS, Fees, Gross Profit, Net Profit, Margin %.
  7. Add a Gmail node named Email summary. Send to your own address, and reference {{ $('Compute margins').first().json.totalNet }}, avgMargin, and worstProducts in the body. Save, then toggle the workflow Active.

Common mistakes

  • Leaving SKUs blank on products. The cost match keys on SKU, so any line item without a SKU is treated as zero cost and shows an inflated margin. Fill in SKUs before you trust the numbers.
  • Mismatched SKU text. A cost of MUG-01 in the sheet will not match mug-01 from Shopify if you also change surrounding spaces. The script trims whitespace, but keep the SKU spelling identical.
  • Confusing gross margin with net margin. Gross profit is revenue minus cost of goods. Net profit here also subtracts the estimated payment fee. The headline number in the email is net.
  • Forgetting returns. This tracks paid orders, not refunds. If returns are material for you, pair it with a refund tracker so the two reports tell the full story.
  • Wrong API version. Use a current Admin API version such as 2026-04. An old version in the URL can drop fields the script expects.

Cost at realistic volume

Everything here runs on free tiers. n8n community edition is free to self-host; n8n Cloud plans count this as one execution per week. Google Sheets and Gmail are free with any Google account, and reading a cost tab plus appending a few dozen rows sits far inside the daily API quotas. The Shopify Admin API calls are free on any plan.

Store size Orders per week Runs per month Monthly cost
Small Up to 50 4 $0
Growing 50 to 250 4 $0
High volume 250+ Switch to daily, 30 $0 self-hosted

Ready-to-import template

The full guide above is free to follow. If you would rather skip the build, the downloadable template is the exact seven-node workflow, validated and ready to import, so you only add your credentials and spreadsheet. Prefer it done for you? See our done-for-you setup service.

Download the template ($19) →

Instant download · Works on n8n Cloud and self-hosted

FAQ

Where does the cost data come from?

From a Google Sheet tab you fill in once, mapping each SKU to its unit cost. The workflow reads that tab on every run, so keeping margins accurate is a matter of updating a spreadsheet cell, not editing the automation itself.

Does this include Shopify payment fees?

It applies an estimated fee of 2.9 percent plus 30 cents per order by default, which you can change in the Config node. It is an estimate, not a reconciled payout, but it lands close enough to flag which orders and products are quietly losing money.

How often does it run?

The template ships with a weekly schedule every Monday at 6am, looking back seven days. Change the Schedule Trigger to daily or monthly, and adjust the lookback window in the Config node to match. Both live in plain fields you can edit without code.

Will it work with a large order volume?

The template pulls up to 250 orders per run, which covers most weekly windows. For higher volume, add pagination on the Get paid orders node using the page_info cursor, or shorten the schedule to daily so each run handles fewer orders.

Do I need a paid n8n plan?

No. This runs on the free self-hosted community edition or any n8n Cloud plan. The only accounts you need are Shopify, a Google account for Sheets and Gmail, and an n8n instance to run the seven nodes on a schedule.

Related guides