How to Sync Inventory Between WordPress and Shopify
On this page
Sync inventory between WordPress and Shopify by configuring custom API calls and webhooks. You must grant read_products and write_products scopes in Shopify, then map product SKIs to trigger stock updates via orders/create and products/update events. This bypasses generic plugins that lack conflict resolution logic.
Most guides assume a pre-built plugin handles the complexity, but real-time accuracy requires manual API configuration. The critical failure point is race conditions when both platforms record a sale simultaneously. Without specific webhook event mapping and permission scope validation, stock mismatches persist despite using standard sync tools.
Why Manual Sync Fails for Multi-Channel Sellers
Manual inventory synchronisation fails because two independent systems process sales simultaneously without a shared lock mechanism. When a customer purchases a widget on your WordPress site while another buys the same item on Shopify, both platforms decrement stock independently. Neither system knows about the other’s transaction until you manually update the CSV or wait for a scheduled plugin run. This race condition creates overselling: you commit to shipping two units when only one remains in the warehouse. For a Melbourne-based store handling multiple channels, this discrepancy compounds daily. Manual CSV exports are unsustainable because they operate on batch intervals, not real-time events. A 15-minute sync window means any sale occurring in that gap creates a conflict. You cannot resolve this by checking stock levels manually; the volume of transactions makes human intervention impossible for real-time accuracy. The solution requires event-driven architecture where each sale triggers an immediate API call to the other platform. This is where OAuth 2.0 becomes critical. Both WordPress and Shopify use OAuth 2.0 to authorise third-party applications to access store data securely. Without properly scoped OAuth tokens, your sync script cannot read or write inventory levels. You must generate application credentials in Shopify’s admin under Settings > Apps and sales channels > Develop apps, and configure corresponding permissions in your WordPress plugin or custom code. The token grants read and write access to the products and inventory_levels endpoints. If you are building this from scratch, understanding how to handle concurrent write requests is essential. We recommend reviewing our guide on Boost Shopify Sales with AI Automation | CloudyWP for context on how automated workflows reduce human error in multi-channel operations. The core issue is not the technology, but the lack of atomic transaction handling between two separate databases. Until you implement webhook listeners that fire on every stock change, manual sync will always lag behind actual sales velocity.
Setting Up the Shopify API Key and Permissions
Shopify Admin API keys determine whether your WordPress scripts can read stock levels or push updates back to Shopify. You need a Custom App with specific permissions to enable two-way inventory sync via the REST API.
- Log in to your Shopify store and navigate to Settings in the left-hand sidebar.
- Select Apps and sales channels, then click Develop apps.
- Click Create app. Name it something distinct, like “WP Inventory Sync,” and click Create app.
- Under Admin API scopes, expand the Products section.
- Check the boxes for read_products and write_products. These scopes allow your WordPress plugin to fetch current stock counts and modify them.
- Click Save.
- Click Create API credential and select Admin API access token.
- Copy the generated token immediately. Shopify hides it after this step.
Store this token securely in your WordPress configuration file or a protected environment variable. Never hardcode it into theme files or public JavaScript. If your sync fails with a 401 error, verify that the token is not truncated and that the write_products scope is still active. For broader architectural issues that cause silent failures, review 5 Automation Mistakes When Connecting WP and Shopify. The REST API endpoint for inventory updates requires this exact credential format to authenticate requests.
Configuring WordPress E-commerce Plugin Webhooks
WooCommerce Webhooks transmit stock and order data to Shopify the moment a transaction completes or product details change. Navigate to WooCommerce > Settings > Advanced in your WordPress dashboard. Select the Webhooks tab to access the configuration screen. Click Add Webhook to create a new listener.
- Enter a descriptive Name, such as “Shopify Stock Sync”.
- Set the Status to Active so the hook fires immediately.
- Choose Order Completed from the Topic dropdown. This event triggers when a customer finalises a purchase, ensuring inventory decrements on Shopify match the sale.
- Paste your Shopify Webhook URL into the URL field. This endpoint must accept POST requests and include your secret token in the header for verification.
- Set the HTTP Method to POST.
- Click Add Webhook to save the first listener.
Repeat the process for the Product Updated topic. This hook captures changes to SKU, price, or stock quantity when you edit a product in WordPress. It pushes those updates to Shopify, preventing stale data. Ensure both webhooks are Active before testing. If you are restructuring your storefront architecture, consider how Headless Commerce for WordPress and Shopify: A Guide | CloudyWP affects your data flow. For specific local support, our Melbourne WordPress & Shopify Automation Experts can audit your endpoint configurations.
Writing the Sync Logic: Handling Stock Decrements
Middleware handles stock decrements by intercepting the WordPress webhook, calculating the new Stock Level, and pushing the update to Shopify via a POST request. The JSON payload from your e-commerce plugin contains the order ID, product SKU, and quantity sold. Your middleware script parses this JSON object to extract the current inventory count from your local database or cache. Subtract the quantity sold from the existing Stock Level to determine the new value. If the result is negative, clamp it to zero to prevent overselling.
Use the Shopify Admin API endpoint /admin/api/2024-01/inventory_levels.json to send the update. The request body must be a JSON object specifying the inventory_item_id and the new available quantity. Do not use PUT; the Inventory API requires POST to modify levels. Include your Admin API access token in the X-Shopify-Access-Token header.
Common failures occur when the middleware ignores the inventory_item_id lookup. Shopify identifies stock by this ID, not the SKU. If your middleware sends the SKU directly, the API returns a 404 error, and your Shopify stock remains unchanged. Ensure your middleware queries the Shopify API first to map the WordPress SKU to the correct inventory_item_id before posting the update. This step resolves most “stock not updating” issues where WordPress shows sold-out items but Shopify still lists them as available.
Troubleshooting Common Sync Conflicts
Shopify API rate limits and SKU mismatches are the primary causes of sync failures, and both require specific handling in your PHP logic. Shopify enforces strict Rate Limiting on inventory endpoints; when you exceed the allowed requests per minute, the API returns an HTTP 429 status code. A naive implementation that ignores this status will leave stock levels stale until the next manual refresh. Your sync script must parse the response headers, specifically X-RateLimit-Remaining and X-RateLimit-Reset, to calculate the exact sleep duration required before the next call. If you receive an HTTP 429, do not retry immediately. Instead, log the error, sleep for the duration specified in the reset header, and then re-queue the request. This prevents a cascade of failed attempts that worsens the throttle.
SKU mismatches occur when the identifier in WordPress does not match the sku field in Shopify’s product variant object. This usually happens during initial import if the mapping script skips variants with identical titles but different SKUs. To resolve this, ensure your sync logic queries Shopify variants by their unique id rather than relying on title matching. When updating stock, always send the variant ID to the /admin/api/2024-01/products/{product_id}/inventory_levels endpoint. If the update returns an HTTP 200 status, the stock level has been successfully adjusted. If it returns a 404, the variant ID is invalid or the product has been archived in Shopify. In that case, halt the sync for that specific item and flag it for manual review. Do not attempt to create the variant automatically, as this can duplicate products. For broader context on managing these edge cases, see WordPress + Shopify Automation: 7 Common Questions.
Implementing robust retry logic is essential for transient network errors. Wrap your API calls in a try-catch block. If an exception is thrown, check the error code. For network timeouts or 5xx server errors, implement exponential backoff. Start with a one-second delay, double it for the second attempt, and cap the delay at thirty seconds. Limit retries to three attempts per request. If all attempts fail, log the full request payload and response body to your error log. This allows you to diagnose whether the issue is a temporary network glitch or a persistent data problem. Regularly review these logs to identify patterns. If you see frequent 429 errors, reduce your sync frequency or batch your requests more aggressively. You can explore how we structure these automated workflows in our Shopify Automation documentation.
Frequently asked questions
How to connect WordPress and Shopify inventory
Connect them by creating a custom API key in Shopify and configuring a webhook in your WordPress e-commerce plugin to trigger a PHP script. This script uses the Shopify Admin API to push stock levels from WordPress to Shopify. You do not need a third-party middleware plugin if you are comfortable writing a small amount of custom code to handle the data mapping and HTTP requests.
What Shopify API key permissions are required for inventory sync
You need a custom API key with read and write access to products and inventory. Create this in the Shopify admin under Settings > Apps and sales channels > Develop in private. Do not use a legacy API key, as it grants full store access and poses a security risk. The specific scopes required are read_products, write_products, read_inventory, and write_inventory.
Where are the webhook settings for stock updates in WordPress
Webhook settings are located within your specific e-commerce plugin, such as WooCommerce or a custom solution. In WooCommerce, you find these under WooCommerce > Settings > Advanced > Webhooks. You must create a new webhook that triggers on the product.updated or product.stock_updated topic. The delivery URL should point to your custom PHP endpoint that handles the Shopify API call.
How to handle stock conflicts in multi-channel selling
Use a “last-write-wins” strategy combined with a buffer stock level to prevent overselling. Define a specific stock threshold in your code that triggers a hard stop on sales across both platforms. If a conflict occurs, your sync script should check the current Shopify stock level before pushing the WordPress value. This prevents a race condition where two sales happen simultaneously, leaving you with negative inventory in one system.
What is the best middleware for WordPress Shopify sync
A custom PHP script using the official Shopify Admin API is the most reliable method. Third-party middleware often adds unnecessary latency and costs. If you require complex logic, look for plugins that expose raw API access rather than those that abstract the process. This gives you full control over error handling and retry logic, which is critical for maintaining accurate stock levels during high-traffic periods.
Why is my Shopify stock not updating in WordPress
The most common cause is a mismatch in SKU mapping between the two platforms. Ensure that the sku field in your WordPress product matches the sku field in your Shopify product exactly, including case sensitivity. Check your server logs for 403 Forbidden or 404 Not Found errors from the Shopify API. If the SKUs match, verify that your API key has the correct write permissions and that the webhook is actually firing when stock changes in WordPress.
What to do next
The next step is to test your sync logic against a live transaction. Do not wait for a customer to buy. Log in to your Shopify admin, navigate to Orders, and create a test order for a product with stock. Watch your WordPress inventory update. If the stock level does not change within 30 seconds, your webhook is not firing, or your PHP script is failing silently. Check your server logs immediately. This single test validates the entire chain: API key, webhook trigger, and database update. If it fails, you have a specific error to debug, not a vague “it’s not working” problem. If it succeeds, you have a reliable foundation. Run this test for both stock increases and decreases. Stock increases happen when you cancel an order or restock. Stock decreases happen when a sale occurs. Both paths must work. If one works and the other does not, your conditional logic in the sync script is flawed. Fix it now. A broken sync that only works half the time is worse than no sync at all, because it creates false confidence. Once both directions are verified, monitor your logs for the first week. Look for 429 errors (rate limiting) or 500 errors (server failures). If you see these, adjust your retry logic or increase your timeout values. The goal is not just to get it working once, but to keep it working under load.
Be the first to comment