Operations and admin

WooCommerce–Square sync: nothing synced, or stock went to 0

Arif Özelci, developer of SyncLanePublished 8 min read

The two complaints about the WooCommerce Square extension are opposites: a sync that says it finished while nothing changed in Square, and a sync that changed too much — every product’s stock reset to zero. Both come from the same three settings, and both are worth understanding before you trust any connector with a live catalogue.

Three gates a product has to pass before anything syncs

The extension does not sync your catalogue. It syncs the products that pass three checks, and “Sync completed” means it finished looking at them — not that any of them qualified. When nothing appears in Square, one of these gates is closed.

  1. A system of record is chosen. WooCommerce → Settings → Square → Update: the setting has three states — Square, WooCommerce, or not chosen. Not chosen is the default after installation, and it means products are not synced in either direction. The connection is live, the settings page looks complete, and nothing moves.
  2. The product is individually marked “Sync with Square”. It is a checkbox on each product’s edit screen (and a bulk action on the product list). Products are opted in one by one; a fresh install has none. The manual sync button is disabled with the message “There are currently no products marked to be synced with Square” when this is the reason.
  3. The product has a SKU — and for a variable product, every variation has its own SKU. A product without one is skipped, because the SKU is what the extension uses to match a WooCommerce product to a Square catalogue item. A variable product with one blank variation fails the whole product.

Check all three on one product you expect to see in Square. In most “nothing syncs” reports, the first gate is the closed one.

The automatic sync is a queue job

After a first successful manual sync, the extension schedules a recurring sync — hourly by default — through Action Scheduler, the same job queue WooCommerce uses for webhooks and analytics. If that queue is stalled, the scheduled sync never runs, and the extension has no way to tell you. It will still say the last sync completed, because the last one did; it is the next ones that are not happening.

Check WooCommerce → Status → Scheduled Actions for past-due actions. If there are any, the problem is the queue, not Square, and the fix is a real system cron — the past-due actions article walks through it. Note also that the schedule is only created once a manual sync has succeeded; a store that connected Square but never pressed the sync button has no schedule at all.

What “system of record” actually overwrites

The extension’s own wording is exact, and it is worth reading before choosing. With Square as the system of record, for every synced product: name, price, description, category and inventory in WooCommerce are overwritten from Square. With WooCommerce as the system of record: name, price, inventory, category and image in Square are overwritten from WooCommerce.

Two things follow. First, there is no field-level choice: you cannot let Square own stock while WooCommerce owns descriptions. The side you pick owns the whole list. Second, the losing side is overwritten, not merged. A description written in WooCommerce for a product whose system of record is Square will be replaced with whatever Square has — which for many merchants is nothing. If your product copy lives in WooCommerce, Square cannot be the system of record for that product; there is no partial setting that saves the copy.

Why stock went to zero

This one had a real bug behind it, and understanding the bug tells you how to avoid the same thing with any connector. When Square is the system of record, the extension pulls each item’s inventory count from Square’s inventory API. An item that has never been counted at your Square location returns a count of zero, in exactly the same shape as an item that has genuinely sold out. Until August 2026, the extension wrote both to WooCommerce as stock 0 and switched stock management on. Every product that was tracked in WooCommerce but never counted in Square went out of stock on the website at the next hourly sync.

Version 5.5.0 (31 August 2026) changed the pull to check Square’s inventory history before writing a zero: a zero with no history behind it is now treated as “no information” and the WooCommerce stock is left alone. A second fix in 5.4.1 stopped a sync that failed partway through leaving newly pushed products at zero. If you are on an older version, update first; if you are on 5.5.0 or later and still seeing zeros, the zeros are real counts in Square, and the fix is a stock count there.

The general lesson is not about this extension. Any two-way sync will, at some point, receive a value that is indistinguishable from “nothing here”, and what it does with that value is the whole product. A connector that treats absence as zero will empty your shop; one that treats it as unknown will not.

Before pressing sync on a live catalogue

  • Export the WooCommerce catalogue (Products → Export) so you have the names, descriptions and stock as they are now.
  • Decide the system of record per the list above, knowing the whole field list moves with it.
  • If Square is the system of record, count every item at the Square location first. Uncounted items are the ones that become zero.
  • Give every product and every variation a SKU that matches the Square item variation’s SKU. Matching is by SKU; a mismatch creates a duplicate on the losing side.
  • Mark one product “Sync with Square”, run the manual sync, check both sides, and only then mark the rest.
  • Confirm the hourly schedule exists in Scheduled Actions afterwards, and that nothing there is past due.

When a single system of record is the wrong model

The whole-side system of record works for a shop that is really one catalogue in two places. It does not work for a shop where the till and the website both sell from the same stock and both write product content: the till needs stock to be correct after a web sale, the website needs it correct after a till sale, and neither side should overwrite the other’s descriptions. That is a mapping problem — each WooCommerce product bound to its Square item by a permanent id, stock moved in both directions on each sale, everything else left where it was written.

SyncLane keeps a mapping table, not a system of record$149 once. Products matched by SKU on the first run and keyed by Square id afterwards, so re-runs update instead of duplicating; stock kept correct on both sides after a sale on either; unchanged records skipped, with a webhook instead of hourly polling.
Open the demo →
Arif ÖzelciBuilds the WebKoding plugins. Answers support himself.