Shopify to QuickBooks Online Proportional Sales Sync (n8n)
Automate real-time financial reconciliation and revenue recognition using n8n's visual node-based workflows.
Tools: Shopify → QuickBooks
Platform: n8n
Short Answer
A fully automated pipeline that triggers on Shopify payment capture, searches for or creates customers in QuickBooks, and generates a Sales Receipt with line-item precision. This ensures your Profit & Loss statement and Balance Sheet are always up-to-date with zero manual data entry.
The Problem
Manual entry of Shopify orders into QuickBooks is labor-intensive and prone to human error, leading to mismatched balances and delayed financial reporting. Many standard integrations fail to handle complex tax mappings or existing customers, resulting in duplicate entries and messy Chart of Accounts data.
The Outcome
A fully automated pipeline that triggers on Shopify payment capture, searches for or creates customers in QuickBooks, and generates a Sales Receipt with line-item precision. This ensures your Profit & Loss statement and Balance Sheet are always up-to-date with zero manual data entry.
Step-by-Step Guide
1. **Create Webhook Trigger**: Add a 'Shopify Trigger' node. Set the 'Event' to `Order Paid`. Copy the Webhook URL provided by n8n and paste it into your Shopify Admin > Settings > Notifications > Webhooks.
2. **Configure Credentials**: In the Shopify Trigger, create new credentials using your Shopify Access Token and Shop Name. Ensure 'Read Orders' scopes are active.
3. **Search for Customer**: Add a 'QuickBooks Online' node. Set the Resource to `Customer` and Operation to `Get All`. Use the 'Filters' option to search by `PrimaryEmailAddr` using the expression `{{ $json.email }}` from the Shopify trigger.
4. **Logic Branching**: Add an 'If' node to check if the QuickBooks Search returned a result. Use the expression `{{ $node["QuickBooks Online"].json["Id"] }}`. If empty, proceed to create customer; otherwise, skip to creating the receipt.
5. **Create Customer (If New)**: Add another 'QuickBooks Online' node. Resource: `Customer`, Operation: `Create`. Map `DisplayName` to Shopify's `first_name` + `last_name` and `PrimaryEmailAddr` to the email from Step 1.
6. **Format Line Items**: Use a 'Code' node or 'Set' node to map the Shopify `line_items` array to the QuickBooks format. QuickBooks requires a specific structure for lines: `[{ "Amount": val, "DetailType": "SalesItemLineDetail", "SalesItemLineDetail": { "ItemRef": { "value": "ID" } } }]`.
7. **Sync Sales Receipt**: Add a 'QuickBooks Online' node. Resource: `Sales Receipt`, Operation: `Create`. Use expressions to map the Customer ID (from search or creation), Total Amount, and the Line Item array from the previous step.
8. **Handle Shipping/Taxes**: Add separate line items for `shipping_lines` and `total_tax` using the QuickBooks 'Global Tax' setting or dedicated service items in your Chart of Accounts.
9. **Configure Error Handling**: Create a 'Error Trigger' node connected to a Slack or Email node to notify you if an API rate limit is hit or if a SKU exists in Shopify but not in QuickBooks.
Data Mapping
| Shopify Field (Source) | QuickBooks Field (Destination) | n8n Expression Syntax |
| :--- | :--- | :--- |
| `email` | `PrimaryEmailAddr` | `{{ $json.email }}` |
| `customer.first_name` + `last_name` | `DisplayName` | `{{ $json.customer.first_name }} {{ $json.customer.last_name }}` |
| `total_price` | `TotalAmt` | `{{ parseFloat($json.total_price) }}` |
| `line_items[].price` | `Line.Amount` | `{{ $json.line_items.map(i => { return { Amount: i.price } }) }}` |
| `order_number` | `DocNumber` | `{{ $json.order_number.toString() }}` |
| `N/A (Fixed Value)` | `DepositToAccountRef` | Usually `Undeposited Funds` ID |
Gotchas & Failure Modes
• **Rate Limits**: Shopify and QuickBooks both have strict API limits. If processing high volumes (>100 orders/hr), add a 'Wait' node or use the 'Split in Batches' node to throttle requests.
• **Data Type Mismatches**: Shopify returns prices as Strings (e.g., "10.00"). QuickBooks requires Numbers. Always wrapping price expressions in `parseFloat()` within n8n.
• **SKU Matching**: Ensure every Shopify SKU matches the 'Name' or 'SKU' field in QuickBooks exactly, or the Sales Receipt node will return a 400 Bad Request.
• **Workflow Activation**: Changes in n8n are not live until you toggle the 'Active' switch in the top right. Testing via the 'Execute Workflow' button creates real data in QuickBooks.
Verification Checklist
- [ ] **Webhook Validation**: Sent a test payload from Shopify; check n8n 'Execution' tab for 200 OK status.
- [ ] **Customer Deduplication**: Ran the workflow twice for the same email; confirmed no duplicate customer was created in QuickBooks.
- [ ] **Line Item Precision**: Verified that (Subtotal + Tax + Shipping) in Shopify equals the Total Amount in the QuickBooks Sales Receipt.
- [ ] **Credential Refresh**: Confirmed QuickBooks OAuth credentials aren't expired (standard for first-time n8n setup).
- [ ] **Error Path Test**: Intentionally changed a SKU to a non-existent value to ensure the Error Trigger node successfully notified the admin.
Ready to Automate?
Build this automation with n8n in minutes.