The situation
Ilana has sold on Etsy for over ten years and she is very good at it. The Shopify site came later, and it never really caught up.
Three things were wrong at once. The Shopify catalog had drifted to 1,176 products, most of them long since sold or no longer real. The sync app connecting the two stores ran the wrong direction, pushing Shopify at Etsy instead of the other way around, which produced duplicate SKUs. And a lot of listings had no reliable SKU at all, so nothing could be matched between the two stores with confidence.
For a normal retailer that is annoying. For a one-of-a-kind maker it is a real problem. There is exactly one of each hat. If both storefronts sell it, one customer gets a refund and an apology instead of a hat, right before the Derby.
What we did, in order
- First, agree on a source of truth Etsy is where the business actually lives, so Etsy became the source of truth and Shopify became the secondary storefront. Every decision after this one follows from that. Picking a direction is most of the work in a sync project, and skipping it is why the old setup failed.
- Give every hat a real SKU I assigned a clean, unique SKU to every active Etsy listing, 411 of them, in a single scheme. Then I verified all 411 against a cross-reference file before touching anything else. Without unique SKUs there is nothing for a sync tool to match on.
- Back up, then wipe I exported the entire existing Shopify catalog first, 1,176 products and 10,400 rows, and kept the backup. Then I removed the old sync app and cleared the stale catalog. You do not clean up 1,176 bad records one at a time. You keep a copy and start from the good data.
- Rebuild from the good data I imported the 411 clean listings into Shopify with 3,498 product images attached. Same day. The store went from a catalog nobody trusted to a catalog that matched Etsy exactly.
- Connect the sync, both directions I connected Trunk between the two stores. It pulled in all 5,771 Etsy listings across every status, active, draft, expired, inactive, and sold out, and the count matched Etsy's own numbers exactly. Then we ran a live two-way sale test the same evening and it passed.
- Keep it honest with a script, not with eyeballs I wrote a reconciliation script that compares the live Etsy catalog against the live Shopify storefront feed every time it runs. It reports two numbers: active hats missing from the website, and website listings that are still buyable when Etsy says they are gone. That second number is the double-sell risk, stated as a number instead of a worry.
What happened
The migration ran in a single evening on July 3, 2026. The old app came off, the stale catalog came out, 411 clean products went in, and the live two-way sync test passed before the night was over.
Where these come from: the project's own migration records and the reconciliation script's saved output. The last verified snapshot in the records is dated August 17, 2026, and shows zero active hats missing from the website and zero true double-sell risks. The script gets re-run rather than assumed, which is the whole point of having it.
Since the migration the same process has kept running. A second batch of 108 new listings went through end to end in July. In August a backlog of 579 studio photos became 61 new listings, and every one of the 562 photos that made it into a listing was verified as a pixel match to the original file before the listing went live.
Where it stands now
The migration was the start, not the finish. A catalog is a live thing and it drifts if nobody tends it.
Auto-renew matters more than it sounds. An expired listing keeps its history and its photos but stops being findable, and on a catalog this size nobody notices one at a time. 378 of them renew on their own now.
The 269 drafts are the next wave of hats, written and queued and waiting on her to publish. Every draft gets read back out of the Etsy API and compared against what I sent before I count it as built. A draft that reports success and isn't there is worse than no draft at all.
The parity check is the reconciliation script on a schedule. It compares the live Etsy catalog against the live Shopify feed every night and reports the gap as a number. Nobody has to remember to run it, which is the only version of a check that survives a busy Derby week.
What the monthly covers
Ilana is on an ongoing monthly support plan: listings stay in sync, the site stays current, and the nightly check catches drift before she does. Current plans and what they include are on the retainers page.
What it covers:
- The Shopify store stays up and current. Theme and app updates, the platform housekeeping, the small breakages a live store produces.
- The sync stays honest. The nightly Etsy and Shopify parity check runs, and I look at the number when it moves.
- Listing hygiene. Auto-renew stays on, SKUs stay unique, and new listings go in through the same verified process as the first 411.
- Small content edits on the site as the shop changes.
- She calls or texts me. No portal, no ticket queue.
What it doesn't cover: building the catalog itself, new photography batches, and website redesign work. Those get quoted as their own projects. Folding catalog production into a monthly is how a monthly turns into a full-time job, so I don't do it.
There are no hours in that list on purpose. The scope is the list.
Why this worked
Nothing here was clever. It was order of operations.
Pick a source of truth. Give every item an identifier. Back up before you delete. Rebuild from the clean data instead of repairing the dirty data. Then replace human checking with a script that produces a number, so "is the store correct" has an answer instead of an opinion.
That last part is the piece most small ecommerce operators never get. Two storefronts will always drift. The question is whether you find out from a script or from a customer.
The pattern this fits
This is the multi-channel inventory pattern. It shows up anywhere one business sells the same physical thing in more than one place: Etsy and Shopify, a website and a marketplace, an online store and a register in the shop.
It gets worse the more unique your inventory is. Handmade, vintage, antiques, art, and one-off restoration work are the hardest cases, because you cannot just reorder the thing you accidentally sold twice.
If your stores disagree and you have been fixing it by hand, this is what fixing it properly looks like.