Skip to content
Back to all articles
Matrixify
Shopify
Bulk Product Upload
Shopify CSV Import
Catalog Operations

Matrixify: The Field Guide to Shopify Bulk Operations at Scale

Six years of running Matrixify on production Shopify stores — export discipline, import commands, cross-store sync, dry runs, rollback files, and the failure modes nobody warns you about.

August 28, 2026 14 min readBy Matheus Abrahão

Why this post exists

Matrixify is the single most important tool in my Shopify stack, and almost nothing written about it goes past "here is how to export a CSV."

I have used it every week for years — on my own store, on an international luxury fashion brand, on a US beauty and lifestyle brand, and today on two storefronts of a US building-products manufacturer that together run an enterprise-scale catalog of 2,800+ products and 13,000+ multi-level variants. That is where you learn what Matrixify actually is: not an import app, but the write layer for a catalog that no human can maintain by hand.

This is the field guide I wish I had in year one.

What Matrixify really is

Shopify's admin is a single-record editor. Matrixify turns the entire store — products, variants, inventory, metafields, customers, orders, redirects, collections, pages, discounts — into spreadsheets you can export, diff, edit, version, and replay.

That reframing matters. Once the catalog is a file, catalog work becomes software work: you get diffs, you get review, you get rollback, you get repeatability. Without it, "update pricing on 900 SKUs" is a two-week project with a 100% chance of at least one typo reaching a customer.

The three commands that do 90% of the work

Every Matrixify import sheet can carry a Command column, and getting this wrong is how people nuke production.

  • UPDATE — touch existing records only. If a row does not match an existing product, it is skipped. This is the default I use for everything. It cannot create garbage.
  • NEW — create only. Fails on collision instead of silently overwriting.
  • REPLACE — wipe and rewrite the record. Powerful, and the reason people have bad days.

Then there are the per-field commands, and the one that matters most is Tags Command:

  • MERGE — append the tags in this row, leave existing tags alone.
  • REPLACE — the row's tags become the entire tag set. Everything else is gone.

I have seen a single Tags Command: REPLACE erase merchandising tags across a whole collection because someone exported tags a week earlier and re-imported a stale column. Default to MERGE. Always. Same logic applies to Variant Command and Metafield Command.

Handle              Command   Tags                       Tags Command
redi-base-32x60     UPDATE    clearance,spring-2026      MERGE
redi-base-36x60     UPDATE    clearance,spring-2026      MERGE

That sheet adds two tags. Change MERGE to REPLACE and it deletes every other tag those products had.

Rule 1: the export you did yesterday is already wrong

Every change starts with a fresh export, not because the old one was wrong when you took it, but because someone else on the team, an app, or a sync job may have touched the catalog since.

The discipline: never edit yesterday's export. I keep one folder per operation:

  • source.xlsx — the fresh export, never modified
  • changes.xlsx — import-ready, only the rows and columns that change
  • rollback.xlsx — current state of exactly the rows I am about to touch
  • validation.csv — a script-generated diff of what should change

If the diff does not match my expectation, the import does not run. That is the whole gate.

Rule 2: export narrow, import narrower

The biggest cause of accidental damage is exporting everything and importing everything back.

If you export 91 columns and import 91 columns, you are asserting the value of 91 fields on every row — including fields you never looked at, and fields that an app owns. Import only the key column plus the columns you are changing. Matrixify ignores what is not present.

A pricing update is four columns: Handle, Variant SKU, Variant Price, Variant Compare At Price. Not ninety-one.

Rule 3: choose your key deliberately

Matrixify can match on ID, Handle, or Variant SKU. They fail differently:

  • ID is exact and store-specific. It is also the one that silently corrupts: a 13-digit product ID pasted into Excel becomes 1.05E+13 and every row fails or, worse, matches nothing and reports success on zero rows. Format the column as Text before you paste, every time.
  • Handle is stable and human-readable, but changes if someone renames a product, and a handle change is a URL change.
  • Variant SKU is the best key for anything inventory-shaped, because it is the identifier your ERP, your 3PL and your retail partners already speak. Its catch: SKU maps to variants, so a product-level operation keyed by SKU needs de-duplication first — I have collapsed 90 variant SKUs down to 3 product IDs in a single migration batch.

Rule 4: Analyze before Import, every time

Matrixify's "Analyze" pass reads your file and reports what it would do, per row, without writing. Use it for:

  • Any first run of a new sheet format
  • Anything touching more than ~100 rows
  • Anything touching price, inventory, status, or redirects

The output tells you how many rows matched. If you uploaded 340 rows and Analyze reports 338 matched, stop. Those two rows are the bug. They are usually a trailing space in a SKU, a scientific-notation ID, or a product that lives on the other store.

Then run 5 rows for real. Look at them in the admin. Then run the 340.

Rule 5: the sheet name is load-bearing

For XLSX imports, Matrixify reads the sheet name to know what object you are importing. A sheet of product statuses must be on a tab named exactly Products. Not Products (1), not Sheet1, not products.

This costs people an hour the first time and never again. Same class of gotcha: the redirects import is a two-column CSV — Redirect from,Redirect to — and it wants full absolute URLs on the destination side, per store domain.

Cross-store sync: the hardest thing Matrixify does

Running a B2C storefront and a B2B storefront on the same catalog means every catalog action happens twice, and the two stores do not share product IDs. A B2C product ID used against the B2B store returns "product not found."

What I actually do:

  • Key cross-store operations on SKU, never ID. SKU is the only identifier that means the same thing in both places.
  • Maintain a mapping sheet — SKU → B2C product ID → B2B product ID — regenerated from fresh exports, never hand-maintained.
  • Generate both stores' files from one approved input list. I wrote a small Python generator that takes a list of parent SKUs, expands children, resolves each store's IDs separately, and emits every file for the round. It was validated by regenerating a historical batch and byte-matching the original.
  • Treat out-of-sync inventory as a Sev-1. A SKU that is live on one store and drafted on the other is a support ticket and a lost order.

And the trap that is not obvious: tags are product-level data shared by every theme in the store. Importing tags to test a badge on an unpublished preview theme immediately changes smart-collection membership on the live theme. There is no theme scoping on catalog data.

Order of operations is a real thing

The clearest example: retiring an old SKU and replacing it with a new one is three operations — new product to Active, old product to Draft, old URL 301 to the new URL.

Run them in that order. Shopify ignores a URL redirect while the source URL still resolves to a live product. Draft the old product first, or your redirects silently do nothing and you find out from Search Console six weeks later.

Rule 6: keep a rollback file, and know the asymmetry

Before any non-trivial import I export the current state of the affected rows to rollback.xlsx. If something goes sideways, recovery is one import away.

But rollback is not symmetric, and this drives what I review hardest:

  • A wrong product field is reversible in five minutes.
  • A wrong price may have already been charged.
  • A wrong redirect on a product with live ads is lost revenue and lost SEO instantly, and no rollback un-loses it.

So price and redirect files get a line-by-line before/after review with a human sign-off. Description and tag files get a spot check.

Rule 7: schedule imports, do not surprise people

  • Pricing: low-traffic window, mid-week morning.
  • Inventory: small deltas, hourly, automated.
  • Metafield and description backfills: weekends.
  • Anything touching the homepage collection or a product in an active campaign: never during the campaign.

Large jobs also queue. A 13,000-variant full import is not a thing you kick off at 4:55pm on a Friday.

Failure modes I have actually hit

  • Silent zero-match success. The job completes, the report says 0 items imported, and nobody reads the report. Always open the results file.
  • Scientific-notation IDs. Covered above. It is always this.
  • Parent/child relationships. Activating a "mother" product can activate derived child products you did not list — separate products, separate IDs, separate URLs. Variants are not children. Missing a child leaves an orphaned live URL.
  • Active but unpublished. Products flipped to Active without the Online Store sales channel added: in stock, correctly priced, and unbuyable. One audit across two stores found 164 of them, 35 carrying inventory, one with 5,469 units sitting idle. Detection is a read-only export filtered to Status = Active, then one query for active AND published = false, sorted by inventory. Note the limitation: the Published column reflects the Online Store channel only — a true multi-channel audit needs the Admin API publications query.
  • Images. Image rows import in order and can duplicate if you re-run a sheet that includes Image Src without Image Command: REPLACE scoped correctly. Image work deserves its own dry run.

The part that is not about Matrixify

The tool is the easy half. What makes bulk operations safe is that every recurring job is written down: what it does, its inputs, its key column, its validation rules, its schedule, who signs off, and when it last ran with what outcome.

That document is the difference between "I import stuff sometimes" and an operations function a business can depend on. Matrixify is what makes the operations function possible; the runbook is what makes it trustworthy.

Where to start

If you have never run a bulk operation on your store, start with the least dangerous one: export your products, add SEO titles and descriptions to fifty rows, import with Command: UPDATE and only the columns you changed. Look at the results file. Then do five hundred.

The muscle you are building is not spreadsheet skill. It is the habit of never letting an unreviewed change reach a live catalog.


I have run Matrixify operations on catalogs from 600 SKUs to 13,000+ variants, across single stores and paired B2C/B2B setups. If your catalog work is still happening one product at a time, I can help — see [Matrixify expert services](/matrixify-expert), [Shopify development services](/shopify-expert), or [hire a Shopify developer](/hire-shopify-developer).

Direct: [WhatsApp +55 11 98851-2788](https://wa.me/5511988512788) · [contato.matheusabrahao@gmail.com](mailto:contato.matheusabrahao@gmail.com)

Need a senior engineer who thinks like an operator?

I take on a small number of Shopify operations and senior engineering engagements each quarter. If your store needs catalog hygiene, technical SEO, performance, or marketing automation done right — let's talk.

Continue reading

Vamos conversar