{"id":343739,"date":"2026-07-23T13:39:47","date_gmt":"2026-07-23T13:39:47","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/multi-store-stock-sync-for-woocommerce\/"},"modified":"2026-07-23T13:47:36","modified_gmt":"2026-07-23T13:47:36","slug":"mountaineering-labs-stock-sync","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/mountaineering-labs-stock-sync\/","author":23536253,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.4.1","stable_tag":"trunk","tested":"7.0.2","requires":"6.5","requires_php":"7.4","requires_plugins":null,"header_name":"Mountaineering Labs Multi-Store Stock Sync for WooCommerce","header_author":"Mountaineering Labs","header_description":"Central stock management across multiple WooCommerce installations (hub\/spoke, SKU-based matching).","assets_banners_color":"0b4c65","last_updated":"2026-07-23 13:47:36","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/github.com\/mountaineering-labs\/mountaineering-labs-stock-sync","header_author_uri":"https:\/\/mountaineering.no","rating":0,"author_block_rating":0,"active_installs":0,"downloads":47,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.4.0":{"tag":"1.4.0","author":"mountaineeringlabs","date":"2026-07-23 13:39:35"},"v1.4.1":{"tag":"v1.4.1","author":"mountaineeringlabs","date":"2026-07-23 13:47:36"}},"upgrade_notice":{"1.2.0":"<p>Adds five new admin languages. No functional changes.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3620094,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3620094,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3620098,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3620098,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.4.0","v1.4.1"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[],"plugin_tags":[6601,22912,12448,1564,286],"plugin_category":[45],"plugin_contributors":[272988],"plugin_business_model":[],"class_list":["post-343739","plugin","type-plugin","status-publish","hentry","plugin_tags-inventory","plugin_tags-multistore","plugin_tags-stock","plugin_tags-synchronization","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_contributors-mountaineeringlabs","plugin_committers-mountaineeringlabs"],"banners":{"banner":"https:\/\/ps.w.org\/mountaineering-labs-stock-sync\/assets\/banner-772x250.png?rev=3620098","banner_2x":"https:\/\/ps.w.org\/mountaineering-labs-stock-sync\/assets\/banner-1544x500.png?rev=3620098","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/mountaineering-labs-stock-sync\/assets\/icon-128x128.png?rev=3620094","icon_2x":"https:\/\/ps.w.org\/mountaineering-labs-stock-sync\/assets\/icon-256x256.png?rev=3620094","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>Run several WooCommerce stores that sell the same products \u2014 for example a domestic and an international site \u2014 and keep stock quantities in sync automatically.<\/p>\n\n<p><strong>How it works<\/strong><\/p>\n\n<ul>\n<li>One site is configured as the <strong>hub<\/strong>, the authoritative source of stock levels. The other sites are <strong>spokes<\/strong>.<\/li>\n<li>When stock changes anywhere (a sale, a refund\/restock, or a manual edit in wp-admin), the change is picked up via WooCommerce's stock hooks and sent to the hub.<\/li>\n<li>The hub updates its own stock <strong>atomically<\/strong> (safe under concurrent sales on different sites) and broadcasts the resulting authoritative value to all spokes.<\/li>\n<li>Products and variations are matched across sites by <strong>SKU<\/strong>. Works with both simple and variable products.<\/li>\n<\/ul>\n\n<p><strong>Reliable by design<\/strong><\/p>\n\n<ul>\n<li>Outbound messages are written to a local queue (a fast database insert) \u2014 customer-facing requests never wait on network calls to other sites.<\/li>\n<li>A background worker delivers queued messages within seconds and retries with backoff if a peer site is temporarily unreachable. Temporary outages cause delay, not data loss.<\/li>\n<li>Every message carries a unique id; receivers ignore duplicates, so retries can never double-apply a stock change.<\/li>\n<\/ul>\n\n<p><strong>Secure<\/strong><\/p>\n\n<ul>\n<li>Sites communicate over a dedicated REST endpoint authenticated with an HMAC-SHA256 signature over a shared secret \u2014 no WooCommerce API keys needed.<\/li>\n<li>Stale requests are rejected and duplicate message ids are ignored (replay protection).<\/li>\n<\/ul>\n\n<p><strong>Languages<\/strong><\/p>\n\n<p>English admin UI, fully internationalized. Translations are managed through translate.wordpress.org and delivered automatically.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate the plugin on <strong>every<\/strong> site that should participate.<\/li>\n<li>On the hub site: go to <em>WooCommerce \u2192 Stock Sync<\/em>, set role <strong>Hub<\/strong>, choose a Site ID, generate a shared secret, and list the spoke URLs (one per line).<\/li>\n<li>On each spoke site: set role <strong>Spoke<\/strong>, choose a Site ID, paste the <strong>same<\/strong> shared secret, and set the Hub URL.<\/li>\n<li>On the hub: click <strong>Run full resync<\/strong> to push current stock levels to all spokes.<\/li>\n<li>Test: change a stock quantity on one site and confirm it updates on the others. The <strong>Recent events<\/strong> log on each site's settings page shows exactly what was sent and received.<\/li>\n<\/ol>\n\n<p>Corresponding products\/variations must share the same SKU on every site, and have \"Manage stock\" enabled. For variable products the SKU on <strong>each variation<\/strong> is what counts.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20all%20products%20have%20to%20exist%20on%20every%20site%3F\"><h3>Do all products have to exist on every site?<\/h3><\/dt>\n<dd><p>No. Products that only exist on some sites are simply not synced \u2014 unknown SKUs are ignored by the receiver. However, every product you want synced must exist on the hub, since all sync flows through it.<\/p><\/dd>\n<dt id=\"does%20a%20spoke%20work%20if%20the%20hub%20is%20down%3F\"><h3>Does a spoke work if the hub is down?<\/h3><\/dt>\n<dd><p>Yes. Orders complete normally \u2014 stock reports are queued locally and delivered automatically once the hub is reachable again.<\/p><\/dd>\n<dt id=\"why%20is%20sync%20slow%20on%20my%20site%3F\"><h3>Why is sync slow on my site?<\/h3><\/dt>\n<dd><p>Delivery runs on WP-Cron, which is triggered by site visits. On low-traffic sites, configure a real server cron job to hit wp-cron.php on each site.<\/p><\/dd>\n<dt id=\"my%20sites%20are%20on%20the%20same%20server%20and%20i%20see%20timeouts%20in%20the%20log\"><h3>My sites are on the same server and I see timeouts in the log<\/h3><\/dt>\n<dd><p>Ask your host about loopback requests and the number of concurrent PHP workers. The queue retries automatically, so changes still arrive \u2014 just with delay.<\/p><\/dd>\n<dt id=\"can%20i%20map%20different%20skus%20to%20each%20other%20across%20sites%3F\"><h3>Can I map different SKUs to each other across sites?<\/h3><\/dt>\n<dd><p>Identical SKUs are strongly recommended, but the <code>wcss_resolve_sku<\/code> filter lets developers map incoming SKUs to local product IDs in code.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.4.1<\/h4>\n\n<ul>\n<li>Display name now includes \"Multi-Store\" to better describe what the plugin does.<\/li>\n<\/ul>\n\n<h4>1.4.0<\/h4>\n\n<ul>\n<li>Renamed to Mountaineering Labs Stock Sync for WooCommerce for a distinctive name.<\/li>\n<li>Admin settings script is now enqueued via wp_enqueue_script instead of inline output.<\/li>\n<li>Removed bundled translation files; translations are handled by translate.wordpress.org.<\/li>\n<\/ul>\n\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>Renamed to Mountaineering Labs Stock Sync for WooCommerce (trademark compliance).<\/li>\n<li>Hardened SQL statements and cleaned up coding-standard warnings.<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>Added German, French, Spanish, Danish and Swedish translations.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>English admin UI with Norwegian (bokm\u00e5l and nynorsk) translations.<\/li>\n<li>Replay\/duplicate protection: every message carries a unique id; retries can no longer double-apply a change.<\/li>\n<li>uninstall.php: cleans up all plugin data on deletion.<\/li>\n<li>Schema migrations now run on in-place upgrades as well as activation.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release: hub\/spoke stock sync with signed messages, durable outbound queue with retry, and full resync.<\/li>\n<\/ul>","raw_excerpt":"Central stock management across multiple WooCommerce stores. One hub owns the stock; spokes stay in sync automatically via SKU matching.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/343739","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=343739"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/mountaineeringlabs"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=343739"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=343739"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=343739"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=343739"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=343739"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=343739"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}