HomeShopify & E-commerceShopify inventory valuation report with n8n…

Shopify inventory valuation report with n8n (weekly, at cost)

Shopify inventory valuation report with n8n (weekly, at cost)









A Shopify inventory valuation report in n8n tells you what your on-hand stock is actually worth at cost, refreshed automatically every week instead of exported by hand. This guide builds a five-node workflow that queries your catalog through the Shopify GraphQL API, multiplies each variant’s quantity by its unit cost, logs the running total to Google Sheets so you can watch the trend, and emails you the headline number. It runs on n8n Cloud or self-hosted, and every service it touches has a free tier.

What it does

Your inventory is one of the largest assets your store owns, but Shopify never shows you its total value in one place. The admin lists quantities per variant; it does not sum quantity times cost across the whole catalog. So when your accountant asks for the closing stock value, or your insurer wants a figure, or you just want to know how much cash is tied up on the shelves, you end up exporting a CSV and building a spreadsheet formula every single time.

This workflow does that math for you on a schedule. Once a week it reads every product and variant, values the on-hand quantity at the cost you entered in Shopify, and produces three things:

  • A single headline number, the total on-hand value of your stock at cost, emailed to you.
  • A new row appended to a Google Sheet so the weekly figures build into a trend line over time.
  • A count of variants that have no cost set, so you know how complete the valuation is.

It is part of the broader pattern of Shopify automation with n8n: let a scheduled workflow pull the numbers out of the store so you stop doing the export-and-formula dance by hand.

Why it beats the default

The manual route is a Shopify export, a pivot table, and a VLOOKUP against a cost list, repeated whenever someone needs the figure. Reports apps in the Shopify App Store can do it, but they charge a monthly fee for a number you calculate once a week, and they still value at retail unless you pay for a higher tier.

Running it in n8n flips that. You own the logic, so you can change the schedule, the recipients, or the math without a subscription. Valuing at cost is built in, because the workflow reads the unit cost straight from each Shopify inventory item. And because every run appends a dated row to a sheet, you get something no one-off export gives you: a history. Watching on-hand value climb before a holiday season or bloat with dead stock is far more useful than a single snapshot.

New to connecting the two tools? Set up the credential first with our guide on how to connect Shopify to n8n in 2026, then come back here.

What you need

  • An n8n instance (Cloud or self-hosted, version 1.0 or later).
  • A Shopify custom app access token with read_products and read_inventory scopes, created through the 2026 Shopify Dev Dashboard method.
  • Unit costs entered on your product variants in Shopify (the cost per item field). Variants without a cost are skipped and counted.
  • A Google account for the trend sheet and a Gmail account for the email. Both free tiers are plenty.

Build time: about 25 minutes from scratch, or a couple of minutes if you import the ready-made template below.

Node-by-node list

Five nodes, wired in a straight line that forks at the end so the sheet and the email both receive the computed result:

# Node Type Job
1 Weekly schedule Schedule Trigger Fires the workflow every Monday at 7am.
2 Query Shopify inventory HTTP Request Sends one GraphQL query to Shopify for every variant’s quantity and unit cost.
3 Compute valuation Code Flattens the response and sums quantity times cost into the total.
4 Append to trend sheet Google Sheets Adds a dated row with the totals so the figures build a trend.
5 Email the report Gmail Emails you the headline number and the skipped-variant count.
[Weekly schedule] --> [Query Shopify inventory] --> [Compute valuation] --+--> [Append to trend sheet]
                                                                          |
                                                                          +--> [Email the report]

Step-by-step build

1. Weekly schedule (Schedule Trigger)

Add a Schedule Trigger node. Set the interval to a cron expression and enter 0 7 * * 1, which means 7am every Monday. This is the only trigger in the workflow, so everything downstream runs on this cadence.

2. Query Shopify inventory (HTTP Request)

Add an HTTP Request node. Rather than the Shopify node’s paginated product loop, a single GraphQL query pulls exactly the fields you need, quantity and cost, in one call.

  1. Set Method to POST.
  2. Set URL to https://your-store.myshopify.com/admin/api/2026-04/graphql.json (swap in your store’s subdomain).
  3. Under Authentication, choose Predefined Credential Type, then Shopify Access Token API, and select your credential.
  4. Turn on Send Body, set Body Content Type to JSON, and paste this into the JSON body:
{
  "query": "query InventoryValuation { products(first: 250) { edges { node { title variants(first: 100) { edges { node { sku inventoryQuantity inventoryItem { unitCost { amount } } } } } } } } }"
}
📌

The access token must carry the read_products and read_inventory scopes. Without read_inventory the unitCost field comes back null and every variant looks like it has no cost.

3. Compute valuation (Code)

Add a Code node set to run once for all items. It walks the GraphQL response, values each variant at cost, and returns one clean summary object.

const resp = $input.first().json;
const products = (resp.data && resp.data.products && resp.data.products.edges) || [];

let totalValue = 0;
let totalUnits = 0;
let variantsMissingCost = 0;
const rows = [];

for (const p of products) {
  const title = p.node.title;
  const variants = (p.node.variants && p.node.variants.edges) || [];
  for (const v of variants) {
    const node = v.node;
    const qty = node.inventoryQuantity || 0;
    const unitCost = node.inventoryItem && node.inventoryItem.unitCost
      ? parseFloat(node.inventoryItem.unitCost.amount)
      : null;
    if (unitCost === null || Number.isNaN(unitCost)) {
      variantsMissingCost++;
      continue;
    }
    const lineValue = qty * unitCost;
    totalValue += lineValue;
    totalUnits += qty;
    rows.push({ product: title, sku: node.sku || '', quantity: qty, unit_cost: unitCost, line_value: Math.round(lineValue * 100) / 100 });
  }
}

const today = new Date().toISOString().slice(0, 10);

return [{ json: {
  date: today,
  total_on_hand_value: Math.round(totalValue * 100) / 100,
  total_units: totalUnits,
  variants_missing_cost: variantsMissingCost,
  rows
} }];

After this node runs, the data looks like this:

{
  "date": "2026-08-26",
  "total_on_hand_value": 48213.75,
  "total_units": 3140,
  "variants_missing_cost": 4,
  "rows": [
    { "product": "Cedar Camp Mug", "sku": "MUG-CED-12", "quantity": 220, "unit_cost": 3.10, "line_value": 682.00 }
  ]
}

4. Append to trend sheet (Google Sheets)

Add a Google Sheets node, operation Append. Point it at a spreadsheet with a tab named Valuation whose header row reads date, total_on_hand_value, total_units, variants_missing_cost. Map each column to the matching field from the previous node. Every weekly run adds one row, and the column of dated totals becomes your trend line.

5. Email the report (Gmail)

Add a Gmail node, operation Send. Set the recipient to your address, and use expressions for the subject and body so the numbers fill in automatically:

Subject: Inventory valuation: {{ $json.total_on_hand_value }} on-hand ({{ $json.date }})

On-hand inventory value at cost: {{ $json.total_on_hand_value }}
Total units in stock: {{ $json.total_units }}
Variants skipped (no cost set): {{ $json.variants_missing_cost }}

Wire node 3 to both node 4 and node 5 so the sheet and the email each receive the computed summary. Save, toggle the workflow active, and it will report itself every Monday morning.

💡

Want a Slack or Telegram ping instead of email? Swap the Gmail node for a Telegram or Slack node and reuse the same expressions. The upstream logic does not change.

Common mistakes

  • Valuing at retail by accident. This report uses unitCost, not the variant price. If you want retail value instead, read price in the query and the Code node, but keep the two figures separate so you do not confuse asset value with sales value.
  • Missing the read_inventory scope. Cost lives on the inventory item, not the variant. If your token only has read_products, every unitCost returns null and the total reads zero. Add the scope and reissue the token.
  • Assuming it covers a huge catalog. The query fetches the first 250 products and 100 variants each in one call. Above that, add cursor pagination (pageInfo { hasNextPage endCursor }) and loop until hasNextPage is false before computing the total.
  • Sending the body as form data. The HTTP Request must use Body Content Type JSON with the query in the JSON body. Sending it as form fields makes Shopify reject the GraphQL request.
  • Blank costs skewing your read. A large variants_missing_cost count means the total understates reality. Fill costs in Shopify before trusting the figure for accounting.

Cost at realistic volume

This is about as cheap as automation gets. The workflow runs once a week, so four or five executions a month, each making a single GraphQL call to Shopify.

Service Usage per month Cost
Shopify GraphQL API ~5 calls Free (included with your plan)
Google Sheets ~5 appended rows Free
Gmail ~5 emails Free
n8n ~5 executions Free self-hosted, or a handful of Cloud executions

Even on n8n Cloud’s starter plan, five executions a month is a rounding error against your quota. Self-hosted, it is genuinely free.

Get the inventory valuation template

The full guide above is free to follow. If you would rather skip the build, download the ready-made workflow, import the JSON, add your credentials, and have your first valuation in a couple of minutes. Prefer it done for you? Our done-for-you service installs and tailors it to your store.

Download the template ($19) →

Instant download · Works on n8n Cloud and self-hosted

FAQ

Does this value my stock at cost or at retail price?

At cost. The workflow reads each variant’s unit cost from Shopify’s inventory item (the cost per item field) and multiplies it by the on-hand quantity. That gives you the accounting value of your inventory as an asset, which is different from what the same stock would sell for at retail.

What if I have not set a cost per item on my products?

Any variant with no unit cost is skipped and counted in the variants_missing_cost field of the report, so you know how complete the number is. Fill in the cost per item on each variant in Shopify, or use the bulk editor to add costs, and the next weekly run will include them.

My store has more than 250 products. Will it capture everything?

The template fetches the first 250 products and the first 100 variants per product in a single GraphQL call, which covers most small and mid-size catalogs. For larger stores, add cursor-based pagination to the query so it pages through every product before computing the total. The guide explains where that goes.

How often does the report run?

The Schedule Trigger is set to run every Monday at 7am on a weekly cron. You can change it to daily, monthly, or any interval by editing the cron expression in the first node. Inventory value moves slowly, so weekly is a sensible default for most stores.

Does this work on n8n Cloud and self-hosted n8n?

Yes, both. The workflow uses only core nodes plus the Shopify, Google Sheets, and Gmail integrations, all of which ship with n8n Cloud and self-hosted installs. You only need to attach your own credentials after importing the template.

Related guides