Integration Guide

Shopify Webhook Integration Guide

Sync orders, inventory, and customer data in real-time with Shopify webhooks. Complete guide with signature verification and production-ready code examples.

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. 1. Go to Settings → Notifications → Webhooks
  2. 2. Click "Create webhook"
  3. 3. Select Event (e.g., "Order creation")
  4. 4. Enter URL: https://yourapp.com/webhooks/shopify
  5. 5. Format: JSON
  6. 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 placed
orders/updatedOrder modified
orders/fulfilledOrder fulfilled
products/updateProduct changed
inventory_levels/updateInventory changed
customers/createNew customer

Real-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.