Why Use Shopify Webhooks?
Shopify webhooks enable real-time synchronization between your store and external systems:
✓ Order Processing
Automatically fulfill orders, send to warehouse, update ERP
✓ Inventory Sync
Keep inventory levels synchronized across platforms
✓ Customer Data
Sync customer info to CRM and marketing tools
✓ Analytics
Send order data to analytics and reporting systems
Step 1: Create Webhook Endpoint
Node.js / Express.js
const express = require('express');
const crypto = require('crypto');
const app = express();
app.post('/webhooks/shopify',
express.raw({type: 'application/json'}),
async (req, res) => {
const hmac = req.headers['x-shopify-hmac-sha256'];
const topic = req.headers['x-shopify-topic'];
const shop = req.headers['x-shopify-shop-domain'];
// Verify signature
if (!verifyShopifyWebhook(req.body, hmac)) {
return res.sendStatus(401);
}
console.log(`Received ${topic} from ${shop}`);
res.sendStatus(200);
}
);
app.listen(3000);Step 2: Register Webhook in Shopify
You can register webhooks via Shopify Admin or programmatically via API:
Option 1: Shopify Admin
- 1. Go to Settings → Notifications → Webhooks
- 2. Click "Create webhook"
- 3. Select Event (e.g., "Order creation")
- 4. Enter URL:
https://yourapp.com/webhooks/shopify - 5. Format: JSON
- 6. Click "Save webhook"
Option 2: Shopify API
const shopify = require('shopify-api-node');
const shop = new shopify({
shopName: 'your-store',
accessToken: process.env.SHOPIFY_ACCESS_TOKEN
});
await shop.webhook.create({
topic: 'orders/create',
address: 'https://yourapp.com/webhooks/shopify',
format: 'json'
});Step 3: Verify Webhook Signatures
Signature Verification
const crypto = require('crypto');
function verifyShopifyWebhook(data, hmacHeader) {
const secret = process.env.SHOPIFY_WEBHOOK_SECRET;
// Compute expected HMAC
const hash = crypto
.createHmac('sha256', secret)
.update(data, 'utf8')
.digest('base64');
// Compare with header
return crypto.timingSafeEqual(
Buffer.from(hash),
Buffer.from(hmacHeader)
);
}
app.post('/webhooks/shopify',
express.raw({type: 'application/json'}),
async (req, res) => {
const hmac = req.headers['x-shopify-hmac-sha256'];
if (!verifyShopifyWebhook(req.body, hmac)) {
console.error('Invalid Shopify webhook signature');
return res.sendStatus(401);
}
// Process webhook...
res.sendStatus(200);
}
);Step 4: Handle Webhook Events
Event Handling Example
app.post('/webhooks/shopify',
express.raw({type: 'application/json'}),
async (req, res) => {
const hmac = req.headers['x-shopify-hmac-sha256'];
const topic = req.headers['x-shopify-topic'];
if (!verifyShopifyWebhook(req.body, hmac)) {
return res.sendStatus(401);
}
const payload = JSON.parse(req.body.toString());
switch (topic) {
case 'orders/create':
await handleOrderCreated(payload);
break;
case 'orders/updated':
await handleOrderUpdated(payload);
break;
case 'products/update':
await handleProductUpdated(payload);
break;
case 'inventory_levels/update':
await handleInventoryUpdated(payload);
break;
default:
console.log(`Unhandled topic: ${topic}`);
}
res.sendStatus(200);
}
);
async function handleOrderCreated(order) {
console.log(`New order #${order.order_number}`);
// Send to fulfillment system
await sendToWarehouse({
orderId: order.id,
items: order.line_items,
shippingAddress: order.shipping_address
});
// Update analytics
await trackOrder({
orderId: order.id,
total: order.total_price,
customer: order.customer
});
}Common Shopify Webhook Topics
orders/createNew order placedorders/updatedOrder modifiedorders/fulfilledOrder fulfilledproducts/updateProduct changedinventory_levels/updateInventory changedcustomers/createNew customerReal-World Use Cases
Order Fulfillment
Automatically send orders to your warehouse or 3PL:
async function handleOrderCreated(order) {
await fulfillmentAPI.createOrder({
externalId: order.id,
items: order.line_items.map(item => ({
sku: item.sku,
quantity: item.quantity
})),
shippingAddress: order.shipping_address
});
}Inventory Synchronization
Keep inventory levels in sync across platforms:
async function handleInventoryUpdated(payload) {
const { inventory_item_id, available } = payload;
// Update in your database
await db.inventory.update({
shopifyItemId: inventory_item_id
}, {
quantity: available,
lastSyncedAt: new Date()
});
}Best Practices
Always verify HMAC signatures
Prevent unauthorized webhook requests
Return 200 within 5 seconds
Shopify times out after 5s - process asynchronously
Handle duplicate webhooks
Use order IDs to prevent duplicate processing
Monitor webhook health
Check Shopify Admin for failed deliveries
Simplify Shopify Webhook Management
hookVM provides signature verification, retry logic, and a dashboard to inspect Shopify webhooks. Perfect for e-commerce integrations.