PDF template action hooks
The template engine of PDF Invoices & Packing slips is built for flexibility, and includes several action hooks where you can output custom content:
Hook | Position | Arguments |
---|---|---|
wpo_wcpdf_before_document | Before all content on the document | $template_type, $order |
wpo_wcpdf_after_document | After all content on the document (=after the footer) | $template_type, $order |
wpo_wcpdf_after_document_label | After the document label (Invoice, Packing Slip etc.) | $template_type, $order |
wpo_wcpdf_before_billing_address | Before the billing address | $template_type, $order |
wpo_wcpdf_after_billing_address | After the billing address | $template_type, $order |
wpo_wcpdf_before_shipping_address | Before the shipping address | $template_type, $order |
wpo_wcpdf_after_shipping_address | After the shipping address | $template_type, $order |
wpo_wcpdf_before_order_data | Before the order data (invoice number, order date, etc.) note that this is inside a table, and you should output the data as an html table row/cells |
$template_type, $order |
wpo_wcpdf_after_order_data | After the order data note that this is inside a table, and you should output the data as an html table row/cells |
$template_type, $order |
wpo_wcpdf_before_order_details | Before the order details table with all items | $template_type, $order |
wpo_wcpdf_after_order_details | After the order details table | $template_type, $order |
wpo_wcpdf_before_item_meta | Before the item meta (for each item in the order details table) | $template_type, $item, $order |
wpo_wcpdf_after_item_meta | After the item meta (for each item in the order details table) | $template_type, $item, $order |
wpo_wcpdf_before_customer_notes | Before the customer/shipping notes (left of the order details) | $template_type, $order |
wpo_wcpdf_after_customer_notes | After the customer/shipping notes (left of the order details) | $template_type, $order |
Using the template action hooks
If you have never used WordPress action hooks before, this may sound like abracadabra. Luckily it’s not that difficult, although some basic PHP knowledge does help a lot if you’re doing this.
There are two places where you can put the code from the examples below. You can either insert the code into your theme functions / functions.php (read this if you have never edited that file before!) or if you have already created a custom pdf template, you can put it in the template-functions.php file inside your custom template folder.
Example 1: Print a delivery date on the packing slip
This will print a custom field (for example ‘delivery_date’) below the regular order data on the packing slip. If you don’t know the name of your custom field, follow this guide: Finding WooCommerce Custom Fields
add_action( 'wpo_wcpdf_after_order_data', 'wpo_wcpdf_delivery_date', 10, 2 ); function wpo_wcpdf_delivery_date ($template_type, $order) { $document = wcpdf_get_document( $template_type, $order ); if ($template_type == 'packing-slip') { ?> <tr class="delivery-date"> <th>Delivery Date:</th> <td><?php $document->custom_field('delivery_date'); ?></td> </tr> <?php } }
Some plugins save the delivery date as a UNIX timestamp, which is a big number like 1483228800. In this case you will need to convert this to human readable format first.
add_action( 'wpo_wcpdf_after_order_data', 'wpo_wcpdf_delivery_date', 10, 2 ); function wpo_wcpdf_delivery_date ($template_type, $order) { if ($template_type == 'packing-slip') { // get the delivery date from the order $delivery_date = $order->get_meta('delivery_date'); // convert the delivery date to a human readable format (using the WooCommerce/WordPress date format settings) $formatted_delivery_date = date_i18n( wc_date_format(), $delivery_date ); ?> <tr class="delivery-date"> <th>Delivery Date:</th> <td><?php echo $formatted_delivery_date; ?></td> </tr> <?php } }
Example 2: Print a custom text after the order details table
This will print a simple text below the order details table on all PDF documents.
add_action( 'wpo_wcpdf_after_order_details', 'wpo_wcpdf_custom_text', 10, 2 ); function wpo_wcpdf_custom_text ($template_type, $order) { ?> <div class="custom-text"> If you have any questions about your order, don't hesitate to contact us! </div> <?php }
Or restricted to the PDF invoice and BACS payment method:
add_action( 'wpo_wcpdf_after_order_details', 'wpo_wcpdf_custom_text', 10, 2 ); function wpo_wcpdf_custom_text ($template_type, $order) { $payment_method = $order->get_payment_method(); if ($template_type == 'invoice' && $payment_method == 'bacs') { ?> <div class="custom-text"> Thank you for your order. Please send the full amount to our bank account: 123-456-789. After we have received your payment, you will receive a notification and we will send you the goods. </div> <?php } }
Or a text about intra-community supply, restricted to invoices (& proforma invoices & credit notes) without tax:
add_action( 'wpo_wcpdf_after_order_details', 'wpo_wcpdf_tax_exempt', 10, 2 ); function wpo_wcpdf_tax_exempt( $document_type, $order ) { // only in financial documents if ( !in_array( $document_type, array('invoice', 'proforma', 'credit-note') ) ) { return; } // get shop location $shop_base_location = wc_get_base_location(); // get billing country if ( $order->get_type() == 'shop_order_refund' ) { // get data from parent order for refunds $order = wc_get_order( $order->get_parent_id() ); } $billing_country = $order->get_billing_country(); // check if any tax was charged and if billing country is outside of shop base country if ( $order->get_total_tax() == 0 && $order->get_total() > 0 && $billing_country != $shop_base_location['country'] ) { ?> <div class="tax-exempt"> Tax free under intra-community supply. </div> <?php } }
Example 3: Print a list of categories under each product name
This example prints a comma separated list of categories for each product under the product name (after the item meta).
add_action( 'wpo_wcpdf_after_item_meta', 'wpo_wcpdf_show_product_categories', 10, 3 ); function wpo_wcpdf_show_product_categories ( $template_type, $item, $order ) { // get a comma separated list of categories (category links stripped) if (isset($item['product'])) { echo '<div class="product-categories">Categories: '.strip_tags( wc_get_product_category_list( $item['product']->get_id() ) ).'</div>'; } }
Example 4: Print a due date on the invoice
Calculate a due date 14 days after the invoice date (see the ‘+ 14 days’ bit and strtotime() for reference)
add_action( 'wpo_wcpdf_after_order_data', 'wpo_wcpdf_due_date', 10, 2 ); function wpo_wcpdf_due_date ($template_type, $order) { if ($template_type == 'invoice') { // put due date only on invoice $invoice = wcpdf_get_invoice( $order ); if ( $invoice_date = $invoice->get_date() ) { $due_date = date_i18n( get_option( 'date_format' ), strtotime( $invoice_date->date_i18n('Y-m-d H:i:s') . ' + 14 days') ); ?> <tr class="due-date"> <th>Due Date:</th> <td><?php echo $due_date; ?></td> </tr> <?php } } }
Example 5: Printing payment instructions on the Proforma Invoice
You may want to add some custom styles to make this look a bit better.
add_action( 'wpo_wcpdf_after_order_details', 'wpo_wcpdf_payment_instructions', 10, 2 ); function wpo_wcpdf_payment_instructions ($template_type, $order) { if ($template_type == 'proforma') { // change 'proforma' to 'invoice' if you want to put this on the invoice WC()->payment_gateways(); $order_id = $order->get_id(); $payment_method = $order->get_payment_method(); do_action( 'woocommerce_thankyou_' . $payment_method, $order_id ); } }