HomeShopify & E-commerceShopify Duplicate SKU Finder in n8n…

Shopify Duplicate SKU Finder in n8n (Weekly Audit)

Shopify Duplicate SKU Finder in n8n (Weekly Audit)

A Shopify duplicate SKU finder is a small n8n workflow that scans every product variant in your store on a weekly schedule, flags any SKU that is attached to more than one variant, and emails you the list. Duplicate SKUs quietly break inventory sync, fulfillment, and analytics, yet Shopify never warns you when you create one. This guide walks through building the audit in five nodes with a Shopify GraphQL call and a Code node, and hands you a ready-to-import template if you would rather skip the build.

What it does

The workflow runs once a week on a schedule trigger. It calls the Shopify Admin GraphQL API for your product variants, then a Code node groups every variant by its SKU and keeps only the SKUs that appear on two or more variants. If any duplicates exist, you get a plain-text email listing each duplicated SKU and the product variants that share it. If the store is clean, nothing is sent, so a quiet inbox means a healthy catalog.

Duplicate SKUs are the kind of data problem that never announces itself. A bulk CSV import reuses a code, a supplier feed collides with an existing product, or someone copies a variant and forgets to change the SKU. From then on, any tool that keys on SKU, third-party inventory sync, 3PL fulfillment, accounting exports, sees two things as one. This is exactly the sort of background hygiene check that belongs in Shopify automation with n8n rather than a manual spreadsheet audit you will forget to run.

Why it beats the default

Shopify has no built-in duplicate SKU report. The admin lets you save two variants with the same SKU without a single warning, and there is no screen anywhere that lists collisions. Your options inside Shopify are to export the full product CSV and pivot it by hand, or to click through products hoping to spot a repeat. Both are slow, both are easy to skip, and neither runs on its own.

The n8n version flips that. It is proactive instead of reactive: the check runs every week whether or not you remember, and it only speaks up when something is actually wrong. Because it reads straight from the Admin API, it always reflects the live catalog, not a stale export. And because it is just five nodes, you can extend it later to log to Google Sheets, post to Slack, or run daily during a big import week.

What you need

  • An n8n instance (cloud or self-hosted). Any recent version works.
  • A Shopify Admin API access token with read_products scope. Create it with the 2026 Dev Dashboard method described in how to connect Shopify to n8n. The old in-admin custom app flow has been removed.
  • A Gmail account for the alert email (any SMTP or Outlook account works too if you swap the last node).
  • About 20 minutes to build from scratch, or a couple of minutes with the template below.

Node-by-node list

Five nodes, wired in a straight line with one branch at the end:

[Weekly Schedule] -> [Get Shopify Variants] -> [Find Duplicate SKUs] -> [Any Duplicates?]
                                                                             |
                                                                     true -> [Email Duplicate Report]
                                                                     false -> (stop, no email)
  
  1. Weekly Schedule (Schedule Trigger) fires the run every Monday morning.
  2. Get Shopify Variants (HTTP Request) posts a GraphQL query to the Admin API and returns your product variants with their SKUs.
  3. Find Duplicate SKUs (Code) groups variants by SKU and builds a report of the duplicates.
  4. Any Duplicates? (IF) checks whether the Code node found anything.
  5. Email Duplicate Report (Gmail) sends the list, and only runs when duplicates exist.

Step-by-step build

Step 1 — Weekly Schedule (Schedule Trigger)

Add a Schedule Trigger node. Set the rule to an interval of Weeks, every 1 week, triggering on day Monday at hour 7. This gives you a fresh audit at the start of each week. If you are in the middle of a large catalog import, you can temporarily switch the interval to daily.

Step 2 — Get Shopify Variants (HTTP Request)

Add an HTTP Request node named Get Shopify Variants and configure it:

  1. Method: POST
  2. URL: https://YOUR_STORE.myshopify.com/admin/api/2026-04/graphql.json
  3. Authentication: Generic Credential Type, then Header Auth. Create a Header Auth credential with name X-Shopify-Access-Token and your Admin API token as the value.
  4. Send Headers: on. Add Content-Type = application/json.
  5. Send Body: on. Body Content Type: JSON. Paste this into the JSON body:
{
  "query": "{ productVariants(first: 250) { edges { node { id sku displayName product { id title } } } pageInfo { hasNextPage endCursor } } }"
}

After this node runs, each variant arrives shaped like the snippet below, nested under data.productVariants.edges:

{
  "node": {
    "id": "gid://shopify/ProductVariant/4820115...",
    "sku": "TEE-BLK-M",
    "displayName": "Classic Tee - Black / M",
    "product": { "id": "gid://shopify/Product/981...", "title": "Classic Tee" }
  }
}

Step 3 — Find Duplicate SKUs (Code)

Add a Code node named Find Duplicate SKUs, mode Run Once for All Items, and paste this JavaScript. It groups every non-empty SKU, keeps the ones used more than once, and returns a single item describing the result:

const edges = $input.first().json.data.productVariants.edges || [];
const map = {};
for (const e of edges) {
  const sku = (e.node.sku || '').trim();
  if (!sku) continue;
  (map[sku] = map[sku] || []).push(
    e.node.displayName || (e.node.product && e.node.product.title) || 'Unknown product'
  );
}
const dups = Object.entries(map).filter(([, arr]) => arr.length > 1);
if (dups.length === 0) {
  return [{ json: { hasDuplicates: false, count: 0, report: 'No duplicate SKUs found.' } }];
}
const lines = dups.map(([sku, arr]) =>
  `SKU "${sku}" is used on ${arr.length} variants: ${arr.join(', ')}`
);
return [{ json: { hasDuplicates: true, count: dups.length, report: lines.join('n') } }];
💡

Tip: empty SKUs are skipped on purpose. Many stores leave the SKU field blank on some variants, and blank is not a real collision, so counting it would flood the report with false positives.

Step 4 — Any Duplicates? (IF)

Add an IF node named Any Duplicates?. Create one condition with a Boolean type: left value {{ $json.hasDuplicates }}, operation is true. The true output carries the report forward; the false output goes nowhere, so a clean store sends no email.

Step 5 — Email Duplicate Report (Gmail)

Connect the IF node’s true output to a Gmail node named Email Duplicate Report. Configure:

  1. Resource: Message, Operation: Send
  2. To: your address, for example owner@yourstore.com
  3. Subject: Duplicate SKUs found in your Shopify store ({{ $json.count }})
  4. Email Type: Text
  5. Message: {{ $json.report }}

Save the workflow and toggle it Active. A typical alert email reads:

SKU "TEE-BLK-M" is used on 2 variants: Classic Tee - Black / M, Summer Tee - Black / M
SKU "MUG-12OZ" is used on 3 variants: Coffee Mug, Gift Mug, Holiday Mug

Common mistakes

  • The 250-variant page limit. A single productVariants(first: 250) call returns up to 250 variants. Stores larger than that need cursor pagination: read pageInfo.hasNextPage and endCursor, then loop the HTTP Request with after: "CURSOR" until hasNextPage is false. The base template audits the first 250, which covers most small and mid-size catalogs; do not assume it scanned everything if you sell thousands of variants.
  • Using OAuth instead of Header Auth. The HTTP Request node here expects a Header Auth credential named X-Shopify-Access-Token. If you pick the built-in Shopify OAuth credential type on an HTTP node it will not attach the token the way the GraphQL endpoint expects.
  • Wrong API version. Keep the URL on a current version such as 2026-04. An outdated or removed version returns a 404 or a deprecation error rather than your variants.
  • Comparing empty SKUs. If you edit the Code node, keep the blank-SKU skip. Treating empty string as a value marks every blank variant as a giant duplicate group.
  • Expecting an email every week. No email means no duplicates, which is the goal. If you want a weekly all-clear confirmation, branch the IF false output to a second Gmail node.

Cost at realistic volume

This workflow is effectively free to run. It uses no paid AI model and no metered service.

Component Usage per week Cost
Shopify Admin API 1 GraphQL call $0 (included with your plan)
Gmail send 0 to 1 email $0 (free tier)
n8n execution 1 run, a few seconds $0 self-hosted; a single execution on n8n Cloud

Even on n8n Cloud’s lowest tier, one weekly execution is a rounding error against your monthly quota. Running it daily during a heavy import period still costs nothing beyond a handful of executions.

Get the Shopify Duplicate SKU Finder template

The guide above is free to follow. If you would rather not build it node by node, download the ready-to-import n8n template, drop in your Shopify token and email, and run your first audit in a couple of minutes.

Download the template ($12) →

Instant download · works on n8n Cloud and self-hosted. Want it built and connected for you? See our done-for-you setup service.

Frequently asked questions

Does Shopify allow duplicate SKUs at all?

Yes. Shopify treats the SKU as a free-text label, not a unique key, so it will happily save the same SKU on many variants without any warning. That permissiveness is why an external audit is worth running, because nothing in the admin surfaces the collisions for you.

Will this scan every variant in a large store?

The base template reads the first 250 variants in one GraphQL call, which covers most small and mid-size catalogs. For larger stores, add cursor pagination using the pageInfo.hasNextPage and endCursor fields so the workflow loops until it has fetched every variant.

Can I log the duplicates to Google Sheets instead of email?

Yes. Change the Code node to output one item per duplicate group, then connect a Google Sheets Append node after the IF. You can keep the Gmail node too, so you get both a running log and an inbox alert on the same run.

How do I get the Shopify Admin API token?

Create a custom app in the 2026 Shopify Dev Dashboard, grant it the read_products scope, and install it to reveal the Admin API access token. Full steps are in our guide on connecting Shopify to n8n. Paste that token into an n8n Header Auth credential named X-Shopify-Access-Token.

What if I want it to run daily during an import?

Open the Weekly Schedule node and change the interval from weeks to days. The rest of the workflow is unchanged. When the import is finished and the catalog is stable, switch it back to weekly so your inbox stays quiet.

Related guides