Shopify Integration — Automation SOP
⚡ THE GOLDEN RULE
ERPNext is the source of truth for STOCK and the LEDGER.
Every Shopify order lands in ERPNext as a Sales Order. Stock only ever moves on the Delivery Note. The invoice is only submitted once the goods have physically left.
1. How Orders Are Received
Orders are pushed by Shopify, not polled on a timer. The chain is four steps and it is fully automatic:
| # | What happens | Where you can see it |
|---|---|---|
| 1 | A shopper checks out. Shopify immediately fires an orders/create webhook. | Shopify Admin → Settings → Notifications → Webhooks |
| 2 | The webhook lands in ERPNext and is recorded as an Integration Request with service Shopify Webhook, status Queued. | Integration Request list |
| 3 | Velobiotics Shopify – Webhook Bridge reads that payload and arms a tight ±3 minute pull window on Shopify Setting. It creates no documents itself. | Shopify Setting → Old Orders From / To |
| 4 | The native job order.sync_old_orders runs, pulls that order over the Shopify Admin API and writes the Sales Order. Everything downstream follows from there. | Ecommerce Integration Log |
2. Frequency — What Runs When
Normal end-to-end latency from checkout to a Sales Order in ERPNext is under 5 minutes.
| Trigger | Frequency | What it does |
|---|---|---|
Shopify orders/create webhook | Instant, on checkout | Records the Integration Request |
| Velobiotics Shopify – Webhook Bridge | Instant, on that record | Arms the pull window |
order.sync_old_orders (native) | Every 5 minutes | Pulls the order, creates the Sales Order. Idles instantly when nothing is armed. |
| Velobiotics Shopify – Route Order | Instant, on Sales Order submit | Draft Sales Invoice + draft Pick List + Bridget's call task |
| Velobiotics Shopify – Hourly Catch-up Arm | Every hour at :50 | Safety net. Re-scans the last 4 hours so a missed webhook cannot lose an order. |
| Velobiotics B2C – Daily Shopify Call Tasks | 07:00 daily | Raises the abandoned-cart call task only |
| Inventory push to Shopify | Stopped | Deliberately off — stock is not pushed back to Shopify |
3. The Order Flow — End to End
What each step guarantees
| Step | Document | Rule that is enforced automatically |
|---|---|---|
| 1 | Sales Order | Submitted. Carries Shopify order ID, order number and payment status. |
| 2 | Sales Invoice | Stays in Draft. Update Stock = 0. Invoice Source = Shopify. Order Date = the Shopify order date, not today. |
| 3 | Pick List | Warehouse forced to Finished Goods - V and linked back to its invoice. |
| 6 | Delivery Note | The only document that moves stock. |
| 7 | Sales Invoice | Submitted on Delivery Note submit. Shopify order status set to fulfilled. |
4. Money — Where the Numbers Land
| Item | Account | Rule |
|---|---|---|
| VAT | 200300 Standard Rate VAT 15% | Always |
| Shipping charged by Shopify | 100100 Shipping Revenue - V | Revenue, never an expense account |
| Free shipping (orders over R500) | 100100 | Posts as zero — the line still appears |
5. Customers — One Human, One Record
Before the sync creates a customer it searches for an existing one, in this order:
| Tier | Match on | Notes |
|---|---|---|
| 1 | Customer email field and any linked Contact email | |
| 2 | Phone | Last 9 digits, so +27 / 0 prefixes do not matter |
| 3 | Exact name | Only if there is exactly one match and that record has no conflicting email or phone |
When a match is found the Shopify customer ID is written onto the existing record and it is reused. A duplicate is only created when all three tiers come back empty.
6. Items — SKU Is the Only Key
Shopify variants map to ERPNext items strictly by SKU, held in the Ecommerce Item table. Never create a new ERPNext item to satisfy a Shopify order — find the existing SKU and map it.
- If an order line arrives with a blank Item Code, the SKU has no mapping. Add the mapping, then re-sync the order.
- Bundles: where Shopify sells a bundle, the individual component SKUs are the source of truth for stock. The bundle is a Product Bundle in ERPNext and explodes into its components on the Delivery Note.
- An item code that looks like a long number (e.g.
44605740253355) is a Shopify variant ID that leaked in as a placeholder. That is a fault — report it.
7. B2C Call Tasks (Bridget)
Call tasks are raised with the order, not on a batch. A customer called minutes after checking out converts far better than one called the next morning, so the task is created in the same transaction that creates the Sales Order.
| Situation | When the task appears | Task subject | What Bridget does |
|---|---|---|---|
| New paid order | Immediately on import | Shopify NEW order #SPF… – call customer to confirm order and advise fulfilment | Call to confirm the order, verify the delivery address, advise fulfilment timing |
| Pending payment | Immediately on import | Shopify UNPAID order #SPF… – call customer for payment | Call and request payment, then update the order |
| Abandoned cart | 07:00 each working day | Shopify abandoned carts <date> – call shoppers and offer a recovery discount | Work the Shopify abandoned-checkout list, find out what stopped them, offer the approved discount |
Every task is High priority, starts today, and carries a ToDo assigned to support@velobiotics.com so it shows on Bridget's own list.
One order, one call
An order gets either the confirmation task or the payment task — never both. This is deliberate: it stops the same customer being phoned twice about the same order.
Working days — how the deadline is chosen
The deadline is the same day wherever possible. If today is not a working day for Bridget, the deadline rolls forward to her next working day. Two things are checked, in order:
- Company holiday list (currently
South Africa 2026) — this already contains every Saturday and Sunday as well as public holidays. - Approved leave — any submitted, approved Leave Application covering that date.
8. Automation Status
| Component | Type | Schedule | State |
|---|---|---|---|
| Velobiotics Shopify – Webhook Bridge | Integration Request, After Insert | Instant | ON |
order.sync_old_orders | Native scheduled job | Cron */5 * * * * | ON |
| Velobiotics Shopify – Route Order | Sales Order, After Submit | Instant | ON |
| Velobiotics Shopify – Match Existing Customer | Ecommerce Integration Log, Before Save | Instant | ON |
| Velobiotics Shopify – DN Submit Closes Invoice | Delivery Note, On Submit | Instant | ON |
| Velobiotics Shopify – Print Paid Invoice | Sales Invoice event | Instant | ON |
| Velobiotics Shopify – Hourly Catch-up Arm | Scheduler event | Cron 50 * * * * | ON |
| Velobiotics B2C – Daily Shopify Call Tasks | Scheduler event | Cron 0 7 * * * | ON |
| Shadow Block – Customer / Sales Order / Sales Invoice | Before Insert guards | Always | ON |
| Inventory push to Shopify | Native scheduled job | — | STOPPED (intentional) |
erpnext_shopify app | Legacy app | — | NOT INSTALLED |
App erpnext_shopify is not installed roughly every 30 minutes. That is a stale webhook subscription still registered in Shopify pointing at the removed app; Shopify keeps retrying it. It is harmless but should be deleted in Shopify Admin → Settings → Notifications → Webhooks.9. Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Order in Shopify but not in ERPNext | Webhook not delivered | Wait for the hourly catch-up, or ask Operations to run the sync for that time window |
| Invoice line has a blank Item Code | SKU has no Ecommerce Item mapping | Add the mapping, then re-sync the order |
| Invoice Source shows blank | Stale browser cache | Hard refresh with Ctrl+Shift+R |
| Customer created ending in " - 1" | No email, phone or name match found | Merge into the original and report it |
| Sales Invoice owned by "Guest" | Legacy shadow service | Report immediately — this should be impossible |
| Stock does not reconcile on Friday | An invoice was submitted with Update Stock ON | Report to Operations; stock must only move on the Delivery Note |
10. Never Do This
- Never tick Update Stock on a Shopify Sales Invoice.
- Never submit a Shopify invoice before the goods have shipped — the Delivery Note does it for you.
- Never create a new Item to satisfy a Shopify order. Map the SKU instead.
- Never change the warehouse away from Finished Goods - V.
- Never re-enable the old Shopify service or the
fix_shopify_*scripts. - Never round a Shopify total.
Questions or a fault to report: Operations Manager.