Integrating Shopify with a CRM via API: Orders and Customers Sync
To sync customers and orders from Shopify to a CRM (such as HubSpot, Salesforce, or Zoho) without relying on third-party middleware, you must build a custom integration. This guide outlines how to configure Shopify API credentials, set up secure real-time webhooks, and process payloads to sync data to your CRM.
Step 1: Generate Shopify API Credentials
To read data from Shopify, you need an Admin API Access Token from a custom app inside your Shopify admin panel.
- Navigate to Settings > Apps and sales channels > Develop apps.
- Click Create an app and name it (e.g., "CRM Integration").
- Under Configuration, select Admin API integration.
-
Enable the following API scopes:
read_customers/write_customers-
read_orders/write_orders
-
Click Save and then Install App.
Copy the Admin API access token. Store it securely; you can only view it once.
Step 2: Choose Your Sync Architecture
There are two primary methods to fetch data from Shopify:
-
Polling (REST/GraphQL API): Querying Shopify's endpoints (e.g.,
/admin/api/2024-01/orders.json) at scheduled intervals. This is resource-heavy and introduces latency. -
Webhooks (Recommended): Shopify pushes data to your server instantly when an event occurs. Use these topics for customer and order sync:
customers/createandcustomers/update-
orders/createandorders/updated
-
Step 3: Implement the Webhook Receiver
Your middleware server must expose an endpoint to receive Shopify's POST requests, verify the webhook's authenticity using the HMAC header, and map the payload to your CRM's API structure.
Below is a production-ready Node.js Express example demonstrating how to receive a Shopify order webhook, verify it, and forward the mapped data to a CRM:
const express = require('express');
const crypto = require('crypto');
const axios = require('axios');
const app = express();
app.use(express.json({
verify: (req, res, buf) => { req.rawBody = buf; }
}));
const SHOPIFY_CLIENT_SECRET = process.env.SHOPIFY_CLIENT_SECRET;
const CRM_API_URL = 'https://api.yourcrm.com/v1';
const CRM_API_KEY = process.env.CRM_API_KEY;
// Verify webhook signature to ensure request came from Shopify
function verifyWebhook(req) {
const hmacHeader = req.headers['x-shopify-hmac-sha256'];
const hash = crypto
.createHmac('sha256', SHOPIFY_CLIENT_SECRET)
.update(req.rawBody, 'utf8')
.digest('base64');
return hash === hmacHeader;
}
app.post('/webhooks/shopify/orders', async (req, res) => {
if (!verifyWebhook(req)) {
return res.status(401).send('Unauthorized: HMAC verification failed');
}
const order = req.body;
// Map Shopify Order Schema to CRM Schema
const crmPayload = {
external_deal_id: order.id.toString(),
deal_name: `Shopify Order #${order.order_number}`,
amount: parseFloat(order.total_price),
customer_email: order.email,
customer_first_name: order.customer?.first_name || '',
customer_last_name: order.customer?.last_name || '',
created_at: order.created_at
};
try {
// Upsert customer in CRM, then link the order/deal
await axios.post(`${CRM_API_URL}/contacts/upsert`, {
email: crmPayload.customer_email,
first_name: crmPayload.customer_first_name,
last_name: crmPayload.customer_last_name
}, {
headers: { 'Authorization': `Bearer ${CRM_API_KEY}` }
});
await axios.post(`${CRM_API_URL}/deals`, crmPayload, {
headers: { 'Authorization': `Bearer ${CRM_API_KEY}` }
});
res.status(200).send('Webhook successfully processed');
} catch (error) {
console.error('CRM Sync Error:', error.response?.data || error.message);
res.status(500).send('Internal Server Error');
}
});
app.listen(3000, () => console.log('Webhook receiver running on port 3000'));
Step 4: Handle Rate Limits and Idempotency
When syncing high volumes of data, you must account for API rate limits on both sides:
-
Shopify Rate Limits: The REST Admin API is limited to 40 requests per second per app (replenished at 2 requests/sec). GraphQL uses a point-based bucket system. Implement a retry mechanism with exponential backoff when encountering
429 Too Many Requests. - CRM Rate Limits: If your CRM limits concurrent API requests, use a message queue (e.g., Redis with BullMQ or RabbitMQ) to buffer incoming Shopify webhooks and process them sequentially.
-
Idempotency: Shopify webhooks guarantee "at-least-once" delivery. Your server may receive the same event twice. Always use Shopify's unique
order.idorcustomer.idas an external key in your CRM to prevent duplicate record creation.
Need this done fast? order an integration on Kwork (https://kwork.com/scripting/52991008/integrate-your-services-api-webhooks-crm-and-payments).
Top comments (0)