How to Build E-Commerce Shipping Notifications

Customers expect to know exactly where their package is at all times. In fact, 93% of online shoppers say shipping tracking is important to their overall shopping experience. In this tutorial, we’ll build a complete shipping notification system using WhereParcel’s API.

What We’ll Build

By the end of this tutorial, you’ll have:

  • Automatic tracking registration when orders ship
  • Real-time status updates via webhooks
  • Email and SMS notifications at key delivery milestones
  • A customer-facing tracking page

Architecture Overview

Order Shipped → Register Tracking → WhereParcel API

                                    Webhook Events

                               Your Notification Service
                                   ↓           ↓
                                Email          SMS

Step 1: Register Tracking When Orders Ship

When your fulfillment system marks an order as shipped, register the tracking number with WhereParcel:

async function registerTracking(order) {
  const response = await fetch('https://api.whereparcel.com/v2/track', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.WHEREPARCEL_API_KEY}:${process.env.WHEREPARCEL_SECRET_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      trackingItems: [{ carrier: order.carrier, trackingNumber: order.trackingNumber }],
      webhook: {
        url: 'https://yourapp.com/webhooks/tracking',
        events: ['status_changed', 'delivered', 'exception'],
      },
    }),
  });

  return response.json();
}

Step 2: Set Up the Webhook Endpoint

Create an endpoint to receive tracking updates:

app.post('/webhooks/tracking', async (req, res) => {
  // Verify webhook signature
  const signature = req.headers['x-webhook-signature'];
  if (!verifySignature(req.body, signature)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Respond immediately
  res.status(200).json({ received: true });

  // Process the event
  const { event, data } = req.body;
  await handleTrackingEvent(event, data);
});

Step 3: Handle Different Event Types

Map tracking events to customer notifications:

async function handleTrackingEvent(event, data) {
  const order = await findOrderByTracking(data.trackingNumber);
  if (!order) return;

  switch (data.status) {
    case 'picked_up':
      await sendNotification(order.customer, {
        title: 'Your order has been picked up!',
        body: `Your package is on its way from ${data.location}.`,
      });
      break;

    case 'in_transit':
      await sendNotification(order.customer, {
        title: 'Your package is in transit',
        body: `Last seen at ${data.location}.`,
      });
      break;

    case 'out_for_delivery':
      await sendNotification(order.customer, {
        title: 'Out for delivery!',
        body: 'Your package will arrive today.',
      });
      break;

    case 'delivered':
      await sendNotification(order.customer, {
        title: 'Package delivered!',
        body: `Delivered at ${data.location}.`,
      });
      break;

    case 'exception':
      await sendNotification(order.customer, {
        title: 'Delivery update',
        body: `There's an update on your package: ${data.description}`,
      });
      break;
  }
}

Step 4: Build a Tracking Page

Create a customer-facing tracking page that fetches the latest status:

app.get('/track/:trackingNumber', async (req, res) => {
  const { trackingNumber } = req.params;

  const tracking = await fetch(
    'https://api.whereparcel.com/v2/track',
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.WHEREPARCEL_API_KEY}:${process.env.WHEREPARCEL_SECRET_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        trackingItems: [{ carrier: 'auto', trackingNumber }],
      }),
    }
  );

  const result = await tracking.json();
  res.render('tracking', { tracking: result.data });
});

Step 5: Add Notification Preferences

Let customers choose how they want to be notified:

const notificationPreferences = {
  email: true,      // Always on by default
  sms: false,       // Opt-in
  push: false,      // Opt-in
  milestones: [     // Which events to notify
    'picked_up',
    'out_for_delivery',
    'delivered',
    'exception',
  ],
};

Best Practices

  1. Don’t over-notify — Customers don’t need an update for every sorting facility. Focus on key milestones: picked up, out for delivery, delivered, and exceptions.

  2. Include tracking links — Every notification should link to your tracking page where customers can see the full timeline.

  3. Handle carrier delays — If a package hasn’t moved in 48+ hours, proactively notify the customer rather than leaving them wondering.

  4. Time zone awareness — Send notifications during the recipient’s business hours when possible.

  5. Batch international updates — International shipments can have many events. Batch them into daily summaries rather than sending individual notifications.

Next Steps