Skip to main content

Add Tracking Number

Modern eCommerce operations often rely on automated systems to manage order fulfillment and shipping. When your warehouse management system, shipping software, or third-party logistics provider updates tracking information, you want that data to flow seamlessly to PayPal without manual intervention.

This approach allows your automated systems to directly update PayPal tracking information whenever shipments are processed, ensuring customers receive timely notifications and reducing the risk of payment disputes. Whether you're using a custom shipping integration or receiving webhooks from your fulfillment partner, this code provides the foundation for automated tracking updates.

When would you use this?

Programmatic tracking updates are essential for merchants who process high volumes of orders or use sophisticated fulfillment systems. Instead of manually entering tracking numbers or relying on basic plugin integrations, you can create a direct pipeline from your shipping data to PayPal.

Common scenarios include receiving tracking updates from third-party logistics providers via API, processing bulk shipment files from your warehouse, integrating with custom shipping software that your fulfillment team uses, or handling tracking updates from multiple carriers through a unified system.

Real-World Example

If you're already using ShipStation, the plugin actually includes this functionality built-in. You can see exactly how this works by examining the TrackingController implementation, which shows how tracking updates are processed when ShipStation sends notifications about shipment changes. This serves as a practical reference for implementing similar functionality with other shipping systems.

The Code

This example shows how to update PayPal tracking information when you receive data from an automated system. The $request variable represents the tracking data from your shipping system, API webhook, or automated process:

/**
* Update PayPal tracking information programmatically
* @param int $order_id WooCommerce order ID
* @param array $request Tracking data from your shipping system
*/
function update_paypal_tracking_programmatically($order_id, $request) {
$order = \wc_get_order( absint( $order_id ) );
$txn_id = $order->get_transaction_id();
$tracking_number = $order->get_meta( Constants::PAYPAL_TRACKING_NUMBER );

//the transaction ID is required to update the tracking number
if ( ! $txn_id ) {
return;
}

// get the tracking info
$tracker = new PaymentPlugins\PayPalSDK\V1\Tracker();
$tracker->setTransactionId( $txn_id );
$tracker->setTrackingNumber( $request['tracking'] );
$tracker->setStatus( $request['shipping_status'] );
$tracker->setCarrier( $request['carrier'] );

if ( ! empty( $request['carrier_other'] ) ) {
$tracker->setCarrierNameOther( $request['carrier_other'] );
}
if ( ! empty( $request['notify_buyer'] ) ) {
$tracker->setNotifyBuyer( $request['notify_buyer'] );
}

$client = wc_ppcp_get_container()->get(PaymentPlugins\PayPalSDK\PayPalClient::class);

if ( $tracking_number ) {
$response = $client->orderMode($order)->tracking->update( $tracking_number, $txn_id, $tracker );
} else {
$response = $client->orderMode( $order )->tracking->create( $tracker );
}

//save the PayPal tracking number to the order
if ( ! \is_wp_error( $response ) ) {
$order->update_meta_data( Constants::PAYPAL_TRACKING_NUMBER, $tracker->getTrackingNumber() );
$order->save();
}
}

How the Code Works

The function begins by retrieving the WooCommerce order and extracting the PayPal transaction ID. The transaction ID is crucial because PayPal uses it to link tracking information to the specific payment. If no transaction ID exists, the function returns early since tracking updates aren't possible without this connection.

Next, the code creates a new PayPal Tracker object and populates it with data from your shipping system. The $request array should contain the tracking number, shipping status, carrier information, and optional fields like custom carrier names or buyer notification preferences.

The code then determines whether to create new tracking information or update existing data. If the order already has a PayPal tracking number stored, it updates the existing record. Otherwise, it creates a new tracking entry in PayPal's system.

Finally, if the PayPal API call succeeds, the tracking number is saved to the WooCommerce order as metadata for future reference.

Integrating with Shipping Webhooks

You can use this code with webhook endpoints that receive tracking updates from your shipping providers:

/**
* Handle shipping webhook and update PayPal tracking
*/
add_action('rest_api_init', function() {
register_rest_route('your-site/v1', '/shipping-webhook', array(
'methods' => 'POST',
'callback' => 'handle_shipping_webhook',
'permission_callback' => '__return_true' // Add proper authentication
));
});

function handle_shipping_webhook($request) {
$data = $request->get_json_params();

// Find the order by your reference
$order_id = find_order_by_reference($data['order_reference']);

if ($order_id) {
$tracking_data = array(
'tracking' => $data['tracking_number'],
'shipping_status' => $data['status'],
'carrier' => $data['carrier_code'],
'notify_buyer' => true
);

update_paypal_tracking_programmatically($order_id, $tracking_data);
}

return new WP_REST_Response('OK', 200);
}

Expected Request Data Format

Your $request array should include these fields:

  • tracking: The tracking number from your carrier
  • shipping_status: Status like "SHIPPED", "IN_TRANSIT", or "DELIVERED"
  • carrier: Carrier code like "UPS", "FEDEX", "USPS"
  • carrier_other: Custom carrier name (optional)
  • notify_buyer: Boolean to send PayPal notification to customer (optional)

Testing Your Implementation

Before deploying to production, test your integration in PayPal's sandbox environment. Create a test order, process a payment, then trigger your tracking update function with sample data. Verify that the tracking information appears correctly in your PayPal sandbox dashboard and that customers receive the expected notifications.

Monitor your error logs during initial deployment to catch any data format issues or API errors that might occur with real shipping data.