Is this the only WooCommerce shipping label plugin that can list SKUs?

I run an e-commerce site selling bike parts at https://fixmymechhanger.co.uk, and as it expanded I needed a way to move away from writing envelopes by hand, so I invested in a bluetooth label printer, and started researching WooCommerce plugins for label printing, of which there are many, both paid and free. However, the key requirement was to make the whole packing process as fast as possible, which meant I wanted the item SKUs (a unique product ID) to be displayed on the envelope so it could act as a packing note to prompt which item to send. I wanted to avoid a separate packing note for cost and environmental reasons. None of the plugins I looked at could list the SKUs in the WooCommerce order on the shipping label, so I decided to create my own plugin. Its Here’s how I did it!

1. Get all the orders that are ready to send (processing state)
This should be pretty self explanatory:

$all_orders = wc_get_orders(array(
	'limit'=>-1,
	'orderby' => 'date',
	'order' => 'DESC',
	'type'=> 'shop_order',
	'status'=> array( 'wc-processing' ),
	)
);

2. Setup the label as a PDF using fpdf
Next we setup a new PDF document that is 100mmx150mm (standard 6″ x 4″ label size), with a 5mm margin all around, and for each order add a new page, with some lines.
I decided to use fpdf (docs here) as a php PDF creation library, which is simple but works quite well. This uses the concept of a ‘current cursor location’, so after drawing some lines to create sections for the address and the item list, I set the position of the cursor to (10, 50).

require('fpdf.php'); // in the plugin main section

$pdf = new FPDF('L','mm',array(100,150)); 
$pdf->SetAutoPageBreak(false);
$pdf->SetMargins(5,5,5);
foreach ( $all_orders as $order ) {
	$pdf->AddPage('L',array(100,150),'90');
	$pdf->SetFont('Arial','',12);
	$pdf->Line(90, 5, 90, 95); // vertical line from point (X=90, Y=5) to (X=90, Y=95)
	$pdf->Line(90, 50, 145, 50);  // horizontal line from point (X=90, Y=50) to (X=145, Y=50)
	$pdf->SetXY(10,50);

3. Add the shipping address section
Still inside the foreach loop, we get the order’s data, write a line with the full name and each line of the address. Ln() creates a new line. A more advanced version replaces the shipping address with the billing address if the shipping information is missing.

$data = $order->get_data();
$shipping = $data["shipping"]; 
$full_name = $shipping['first_name'] . ' ' . $shipping['last_name'];
$pdf->Write(5, $full_name);
$pdf->Ln();

foreach ($shipping as $key => $shipping_lines){
	$pdf->SetX(10);
	if ($key == 'phone' or $key == 'country' or $key == 'email' or $shipping_lines == '' ) continue; // drop blank, country, phone
	if ($key == 'first_name' or $key == 'last_name') continue; // drop names as already printed above
	$pdf->Write(5, $shipping_lines);
	$pdf->Ln();
}	

4. Add the order ID section
In the bottom right section, we add the order ID. Again this is simplified, since in the actual plugin I replace the WooCommerce order ID with the eBay ID if the order is placed from eBay, and I additionally add my website graphic.

$pdf->SetFont('Arial','B',8);
$pdf->SetXY(91,65);
$order = wc_get_order( $data['id'] );
$order_items = $order->get_items();
$order_id = 'Order ID: ' . $order_id_no;

5. Add the SKU and quantity for each item in the order
Under the order ID, set the cursor back to the start of the line for each item in the order. We use the WooCommerce API to get the SKU and quantity, and write it this time using fpdf’s multicell option.

$pdf->MultiCell(0, 5, $order_id, 0, 'L');
$pdf->SetFont('Arial','',8);
foreach( $order_items as $item_id => $item ){
	$item_data = $item->get_data();
		$product = wc_get_product( $item_data['product_id'] );
		$order_line = $product->get_sku() . ' - Quantity: ' . $item_data['quantity'];
		$pdf->SetX(91);
		$pdf->MultiCell(0, 5, $order_line, 0, 'L');
}

6. Create the PDF
Finally, we create the PDF with a filename based on the date and time.

$filename = date("Y-m-d(Hi)") . '-FMMHlabel.pdf';
$pdf->Output('I', $filename, true);
die();

Using this code with a plugin

This also needs some plugin boilerplate code, so that the PDF can be downloaded when you open a URL. I set this only accessible to logged in users for security reasons, and added a WordPress plugin backend page to allow selection of the graphic of your choice.

Finally I can download the PDF, print the list of labels, and then I have all the information I need to pack the orders, and I can mark each one as ‘completed’ in WooCommerce so they don’t get included in the PDF next time I load it, and my packing workflow is now fast and simple – just need to stick the stamp in the top right of the label, stick the label on the envelope, and pack the correct item SKU!