Supplier Spreadsheets Are Not Shopify CSVs: Handle Keys, SKU Mapping, and the Image-Prep Pipeline That Keeps Bulk Updates Safe
By EasyCatch Growth Desk — weekly technical deep-dive for the Shopify community. Written 2026-09-07. TL;DR Most merchants treat "importing" as the hard part and "updating" as a smaller repeat of it. The two m
By EasyCatch Growth Desk — weekly technical deep-dive for the Shopify community. Written 2026-09-07.
TL;DR
Most merchants treat "importing" as the hard part and "updating" as a smaller repeat of it. The two most active workflow threads on community.shopify.com this week show the opposite is true. In How do you handle supplier spreadsheets when updating your store? (Sep 5), a developer exploring this exact workflow is told by merchants that the import itself is rarely the failure point — it is everything before it: supplier files are keyed on SKU while Shopify's products CSV is keyed on Handle, so a blank or drifted handle silently creates duplicate products instead of updating the one you meant. In What do you do with product images before they're ready for Shopify? (Sep 4), the consensus is that renaming, organizing, and matching images to variants is the "most repetitive and time-consuming" stage — and the filename is where variant-to-image binding is won or lost before the CSV is ever written. This guide explains why the update loop is a data-model problem, not a spreadsheet chore: handle-keyed upsert semantics, SKU-to-handle mapping, Excel's silent corruption of identifiers, and an image-prep naming discipline that makes the Variant Image column trivially correct.
1. Why Your Supplier File Is Not a Shopify CSV
Open Shopify's product CSV template next to a supplier's price/stock sheet and the difference is not the columns — it is the key. Supplier files identify a row by SKU (ABC123-BLUE-M). Shopify's importer identifies a row by Handle (abc123-blue-m), and merges every CSV row sharing a handle into one product record before applying variant-level changes.
This mismatch is invisible until it bites. As one merchant put it in 676989: "the supplier file is keyed on SKU and Shopify's product CSV is keyed on Handle. Nothing warns you about the mismatch. If the handle column is blank or slightly wrong, the row does not update the product you meant, it creates a new one, and you find out when the store has two of everything." That is the single most expensive sentence in the thread. A price-update file built by joining on SKU but written with a stale or hand-typed handle column is a duplicate-product generator, and the import summary will show zero errors — handle-keyed upserts silently create when they cannot match.
The fix starts with a mapping, not a merge. Before touching the supplier file, export a fresh product list and build a SKU → Handle map from it. Not last month's copy, not the CSV you imported last time — a fresh export, because handles change when titles change and SKUs get reassigned. Join the supplier file to the map on SKU; let any SKU with no handle fall into an exceptions list for human review instead of being auto-created.
2. Excel Is a Data-Damage Tool, Not a Data Tool
The second recurring theme in 676989 is that opening the file is enough to break it. Excel silently rewrites identifiers on save:
-
Leading zeros stripped. SKU
001234becomes1234— which no longer matches anything in the SKU → Handle map, so the row either creates a duplicate or silently updates nothing. -
Scientific notation. Long numeric IDs (order IDs, barcode-adjacent fields, 11+ digit supplier codes) become
7.05E+11. The value looks wrong only if someone scrolls to it. -
Date coercion.
01-2345or3-4cells get converted to dates, destroying the identifier entirely. - Sorting a column independently. One merchant's hard rule from the thread: "I'd avoid sorting that CSV in Excel." A partial sort detaches rows from their products — the file now says SKU X costs $12 when the adjacent row still holds SKU Y's description.
The practical rule for anyone handling supplier files: never let the supplier file touch Excel before it is normalized. Read it with a proper CSV parser, validate SKU format (length, charset, leading zeros), and fail loudly on rows that don't validate — do not "fix them quietly," because quiet fixes are how wrong prices ship to the storefront.
3. The Update Loop: Change Detection Before Re-Import
A supplier price or stock update should never be applied by re-importing the entire catalog. Full re-imports re-run every upsert rule in Section 1 across every row — one stale handle in a 2,000-row file creates one duplicate you won't notice until the Google Shopping feed flags two products with identical titles.
The safe loop, assembled from the merchants' answers in 676989:
- Export fresh state from Shopify (products + variants + inventory).
- Normalize the supplier file: validate SKUs, strip formatting, parse prices/stocks as numbers, reject malformed rows.
- Join to the SKU → Handle map built in step 1.
- Detect changes — compare the supplier's new price/stock against current values, and keep only rows where something actually changed. Change detection is also your safety net: a supplier file that suddenly shows 40% of SKUs at $0 is a broken export, not a sale, and detection will surface it as an anomaly instead of importing it.
- Review exceptions (unmatched SKUs, zero prices, new products) in a separate list.
- Import, and use Shopify's own stock safety check for inventory rows — the On hand (current)/(new) confirmation that one merchant called "the safety check" — before confirming.
- Keep an update log of what was changed and when, so a bad import can be rolled back by re-running the previous good state.
This loop turns "import the file and pray" into a reviewable, reversible operation.
4. The Image-Prep Pipeline: Filenames Are the Join Key
Thread 676739 asks merchants what they actually do with images between creation and upload. The answers converge on one discipline that most stores skip: the filename is the data model. The most-cited pattern in the thread is a SKU-position naming rule:
-
ABC123-01.jpg,ABC123-02.jpg— gallery order encoded in the filename -
ABC123-blue-01.jpg— variant shots carry their option value - One folder per batch, with
approved / needs-editing / rejectedsubfolders, and only approved files get renamed - Crop to a consistent aspect ratio and compress before upload (merchants cited ~2000 px on the long side as a working default)
- A spreadsheet mapping final filenames to product handles before the CSV is written
Why does this matter technically? Because Shopify's CSV binds variant images by URL-string identity: the Variant Image column must repeat, per variant row, a URL that exactly matches an Image Src row in the same file — or an existing image in the Media library. When your files are named ABC123-blue-01.jpg from the start, generating the cartesian expansion (5 colors × 4 sizes = 20 variant rows, each repeating its own color's image URL) is a mechanical join on the filename. When your files are named IMG_4821.jpg, someone has to eyeball every row — and eyeballing 20-row variant blocks is exactly where "colors swapped / sizes show the wrong image" complaints are born. One merchant in the thread confirmed the slowest step is "making sure each image belongs to the right color/option" — which is only slow when the naming scheme doesn't encode the answer.
5. WebP and the File-Prep Stage
The image-prep stage is also where format conversion belongs — before naming and upload, never after. 1688/Alibaba supplier galleries are predominantly WebP files behind signed CDN URLs (...webp?x-oss-process=image/...). If a WebP URL survives into the CSV, Shopify's async download queue can silently skip the fetch — the row imports "successfully," the image slot stays blank, and no error is surfaced anywhere.
The conversion is a local binary operation: a browser <canvas> decodes the source via drawImage, then toDataURL('image/jpeg') re-encodes it. Two honest constraints: JPEG is 8-bit per channel, so higher bit-depth sources and alpha channels are downsampled (visually negligible for product photography, relevant for line art), and the re-encoded file must be re-hosted at a stable, standard-format URL — a signed, expiring supplier URL re-entered into the CSV just moves the failure a few hours later when the signature expires before Shopify's queue fetches it.
Local-first is not a privacy slogan here; it is a correctness argument. Transpiling on your own machine means the CSV never contains a format Shopify will drop, and the file you produce — standard JPEGs plus a Matrixify-compliant ZIP with every expanded variant row repeating its own image URL — is deterministic. You can run the same prep twice and get the same catalog. You cannot say that about a manual Excel session at 11 p.m. before a product launch.
6. A Normalization Pipeline That Makes All Three Safer
Every failure in this guide happens upstream of Shopify, which is the good news: fix the pipeline once, and every future supplier update inherits the fix.
- Read supplier files programmatically — never Excel-first. Validate SKUs, preserve leading zeros, parse numbers strictly.
- Transpile WebP to JPEG locally (canvas decode → re-encode → stable output), so no unsupported binary or expiring signed URL ever enters a CSV. This is the same binary conversion as Section 5, running as a repeatable step instead of a manual one-off.
- Build the SKU → Handle map from a fresh export and join, never blind-merge.
-
Generate the cartesian expansion programmatically, repeating each color's
Variant ImageURL on every size row, and package the result as a Matrixify-compliant ZIP that Shopify's importer (or Matrixify) accepts without row-level hand-editing. - Run change detection and keep an update log, so a price update touches only the rows that actually changed.
This is exactly the workflow class that a tool like EasyCatch (easycatch.org) — a 100% Local-First 1688-to-Shopify copilot built around a Local Canvas Transpiler for WebP-to-JPG conversion and Matrixify-compliant ZIP generation — automates end to end. But the architecture matters more than the tool: normalize the source catalog locally, and the entire class of silent-import bugs disappears for every future batch, not just this one.
Conclusion
The two threads that anchor this guide say the same thing from opposite ends of the workflow. The supplier-update thread (676989) shows that updating a store breaks on keying — SKU files against a handle-keyed importer, with Excel quietly corrupting the identifiers in between. The image-prep thread (676739) shows that the tedious, error-prone half of merchandising is naming and matching — and that a filename convention converts variant-image binding from eyeball work into a join. Both are upstream problems. Handle them there — with a fresh SKU → Handle map, strict file validation, change detection, an update log, and a local transpile-and-package step — and "import" becomes the boring, reliable 5% of the job it was always supposed to be.
About EasyCatch
EasyCatch (easycatch.org) is a 100% Local-First copilot for 1688-to-Shopify sourcing. Its Local Canvas Transpiler converts supplier WebP images to JPG entirely in your browser, and its CSV engine expands color-by-size variants into Matrixify-compliant ZIPs with correct per-row image mapping — no supplier link or product data ever leaves your machine. Zero-Server Privacy by design.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.