---
title: "Build a custom WooCommerce template for BizPrint"
description: "Add your own print template to the BizPrint plugin for WooCommerce with a small WordPress plugin, so it appears in the Template list of your printer locations."
url: https://docs.getbizprint.com/developers/custom-templates/
section: "Developers"
last_updated: 2026-11-12
---

# Build a custom WooCommerce template for BizPrint

Section: Developers

> Add your own print template to the BizPrint plugin for WooCommerce with a small WordPress plugin, so it appears in the Template list of your printer locations.

This page shows developers how to add their own print [template](https://docs.getbizprint.com/start-here/glossary/#template) to the [BizPrint plugin for WooCommerce](https://docs.getbizprint.com/start-here/glossary/#bizprint-plugin-for-woocommerce). It is for developers and agencies who know PHP and WordPress, and it applies only to orders printed from a WooCommerce store.

A custom template is a small PHP class plus one template file for each [output format](https://docs.getbizprint.com/start-here/glossary/#output-format) it supports. Once you register it, it appears in the **Template** list of every [printer location](https://docs.getbizprint.com/start-here/glossary/#printer-location), next to the built-in templates.

If you only want to add a line or two to a built-in template, you may not need a whole template. See [WooCommerce plugin hooks and filters for BizPrint](https://docs.getbizprint.com/developers/woocommerce-hooks/).

## Before you start

- Install and connect the BizPrint plugin for WooCommerce. See [Connect the BizPrint plugin for WooCommerce to your BizPrint account](https://docs.getbizprint.com/set-up/connect-woocommerce-plugin/).
- Put your code in your own plugin (or a site-specific plugin). Never edit the template files inside the BizPrint plugin: plugin updates replace them.
- Test on a staging copy of your store first if you can.

## How a template works

A template is a PHP object that implements the `Zprint\Template\Index` interface. It has four methods:

- `getName()`: the name shown in the **Template** list.
- `getSlug()`: a short, unique ID for the template, such as `acme-pickup-slip`. Use your own prefix so it cannot clash with a built-in template or another plugin.
- `getFormats()`: which output formats it supports, as an array such as `array( 'html' => true, 'plain' => true )`. Only the formats you return appear in the **Output Format** list (**HTML** and **Plain Text**) when someone picks your template.
- `getPath( $format )`: the full path to the template file for that format (`html` or `plain`).

You register the template with `Zprint\Templates::registerTemplate()`. Do this inside the `zprint_loaded` action, which runs after the BizPrint plugin has loaded, so its classes are always available.

## Step 1: Register the template

This example registers a “Pickup Slip” template from your own plugin. Save it as the main file of a new plugin, for example `acme-bizprint-templates/acme-bizprint-templates.php`.

```php
<?php
/**
 * Plugin Name: Acme BizPrint Templates
 */

add_action( 'zprint_loaded', function () {

  class Acme_Pickup_Slip implements \Zprint\Template\Index {

    public function getName() {
      return 'Pickup Slip';
    }

    public function getSlug() {
      return 'acme-pickup-slip';
    }

    public function getFormats() {
      return array( 'html' => true, 'plain' => true );
    }

    public function getPath( $format ) {
      return __DIR__ . '/templates/pickup-slip-' . $format . '.php';
    }
  }

  \Zprint\Templates::registerTemplate( new Acme_Pickup_Slip() );
} );
```

The class is declared inside the action on purpose: the interface it implements only exists once the BizPrint plugin has loaded.

## Step 2: Write the HTML template file

The plugin includes your template file each time it prepares an order for printing. Inside the file you can use:

- `$order`: the WooCommerce order (a `WC_Order` object).
- `$location_data`: an array with the settings of the printer location that is printing, such as `$location_data['title']` and `$location_data['format']`.
- `$templateOptions`: the values saved for your own template settings (see [Optional: add your own template settings](https://docs.getbizprint.com/developers/custom-templates/#optional-add-your-own-template-settings)), or an empty array.

HTML templates are full web pages that a [BizPrint desktop app](https://docs.getbizprint.com/start-here/glossary/#bizprint-desktop-app) [station](https://docs.getbizprint.com/start-here/glossary/#station) prints. Save this as `templates/pickup-slip-html.php` in your plugin:

```php
<?php
/** @var WC_Order $order */
defined( 'ABSPATH' ) || exit;
?>
<html>
<head>
  <style>
    body { font-family: sans-serif; font-size: 14px; }
    h1 { font-size: 20px; }
  </style>
</head>
<body>
  <h1>Pickup: order <?php echo esc_html( $order->get_order_number() ); ?></h1>
  <p><?php echo esc_html( $order->get_formatted_billing_full_name() ); ?></p>
  <ul>
    <?php foreach ( $order->get_items() as $item ) : ?>
      <li><?php echo esc_html( $item->get_quantity() . ' x ' . $item->get_name() ); ?></li>
    <?php endforeach; ?>
  </ul>
</body>
</html>
```

Keep styles inside the file. On a desktop station, the paper size and margins come from the printer location. On an Android station, they come from the printer’s settings in the [BizPrint Android app](https://docs.getbizprint.com/start-here/glossary/#bizprint-android-app), unless the printer is set to use the job’s page size. Design the page to fit the paper you use. If text is cut off at the edges of desktop printouts, tick **Custom Margins** for the location and set margins that suit your [printer](https://docs.getbizprint.com/start-here/glossary/#printer).

## Step 3: Write the plain text template file

Plain text works on desktop and Android stations. On a receipt printer connected to the BizPrint Android app, it prints fast with the printer’s own fonts. Print one line at a time with the plugin’s `Zprint\Document` helpers, which fit text to the width set in the location’s **Plain text format symbols width** field:

- `Document::line( $text )`: prints a line, wrapping long text.
- `Document::centerLine( $text )`: prints a centered line.
- `Document::symbolsAlign( $left, $right )`: prints text on the left and the right of the same line, for example a product and its quantity.
- `Document::emptyLine()`: prints a blank line.

Save this as `templates/pickup-slip-plain.php`:

```php
<?php
use Zprint\Document;

/** @var WC_Order $order */
defined( 'ABSPATH' ) || exit;

echo Document::centerLine( 'PICKUP' );
echo Document::symbolsAlign( 'Order', $order->get_order_number() );
echo Document::emptyLine();

foreach ( $order->get_items() as $item ) {
  echo Document::symbolsAlign( $item->get_name(), $item->get_quantity() );
}
```

Do not output HTML tags in a plain text template, and do not use tabs for spacing: tabs are removed from plain text output.

## Step 4: Use the template in a printer location

1. Activate your plugin in WordPress.
2. Go to **WooCommerce** > **Print Manager**.
3. Click the **Printers** tab.
4. Click the name of the printer location you want to use in the **Description** column, or create a new location. See [Create a printer location in the BizPrint plugin for WooCommerce](https://docs.getbizprint.com/set-up/create-printer-location/).
5. Choose your template (for example **Pickup Slip**) in the **Template** list.
6. Choose **HTML** or **Plain Text** in the **Output Format** list.
7. Click **Save Changes**.
8. Click **View Sample** to preview the result without printing. The button appears only on a saved location when your store has at least one order. See [Preview a BizPrint printout in WooCommerce with View Sample](https://docs.getbizprint.com/print/view-sample/).
9. Read [Send a test print from a BizPrint printer location in WooCommerce](https://docs.getbizprint.com/print/test-print/). A test print prints your newest real order again.
10. Do the checks in [Check before you send a test print](https://docs.getbizprint.com/developers/custom-templates/#check-before-you-send-a-test-print).
11. Click the **Printers** tab.
12. Click the name of the printer location in the **Description** column.
13. Click **Test print** once, only if no job for that order is **pending**, **connecting-to-printer** or **processing**.

A test print still follows the location’s mapping rules from Product Mapping, Shipping Mapping or Metadata Mapping (add-ons included with some plans). If your newest order does not match a location’s rules, it does not print there.

## Check before you send a test print

A test print prints your newest real order again, so check first that it will not print twice:

1. Look at the paper at the printer for a printout of your newest order.
2. Check the [status](https://docs.getbizprint.com/start-here/glossary/#print-job-status) of that order’s [print job](https://docs.getbizprint.com/start-here/glossary/#print-job) in the [BizPrint dashboard](https://docs.getbizprint.com/start-here/glossary/#bizprint-dashboard).
3. Wait for the station to finish anything it is still printing, whatever status the job shows.
4. Go to **WooCommerce** > **Print Manager** in WordPress.
5. Click the **Support** tab.
6. Check **Queue Status** in the [**Print Job Queue**](https://docs.getbizprint.com/start-here/glossary/#print-job-queue). If a print request could not reach BizPrint, the plugin may keep it in the **Print Job Queue** and try again later.
7. Wait for any pending or processing jobs in the queue to finish.

## Optional: add your own template settings

To give your template its own settings on the printer location page, also implement the `Zprint\Template\Options` interface. Its two methods are:

- `renderOptions( $options )`: returns the HTML for your form fields. The plugin shows it in a **Custom Template Options** box on the printer location page when your template is selected. `$options` holds the values saved earlier.
- `processOptions( $options )`: runs when the location is saved. Read your fields from the submitted form, clean them, and return the array to save.

The saved values reach your template file as `$templateOptions`. For example, add these two methods to the `Acme_Pickup_Slip` class (and add `\Zprint\Template\Options` to its `implements` list):

```php
public function renderOptions( $options ) {
  $note = isset( $options['note'] ) ? $options['note'] : '';

  return '<label>Note at the bottom of the slip '
    . '<input type="text" name="acme_slip_note" value="' . esc_attr( $note ) . '"></label>';
}

public function processOptions( $options ) {
  $options['note'] = isset( $_POST['acme_slip_note'] )
    ? sanitize_text_field( wp_unslash( $_POST['acme_slip_note'] ) )
    : '';

  return $options;
}
```

Then print it in your template file, for example `echo esc_html( $templateOptions['note'] ?? '' );`.

## Good to know

- The **Include** options on the printer location page (such as order cost or shipping details) are shown for your template too. Your template decides whether to use them: their values are in `$location_data['total']` and `$location_data['shipping']`.
- Changes to your template file apply to the next order the plugin prints. A reprint from the BizPrint dashboard also uses the current template file and the current order.
- To make a built-in template use a different file instead of adding a new template, use the `Zprint\getTemplatePath` filter. See [WooCommerce plugin hooks and filters for BizPrint](https://docs.getbizprint.com/developers/woocommerce-hooks/).

## Related pages

- [WooCommerce plugin hooks and filters for BizPrint](https://docs.getbizprint.com/developers/woocommerce-hooks/)
- [Choose a BizPrint template for WooCommerce printouts](https://docs.getbizprint.com/print/choose-a-template/)
- [Create a printer location in the BizPrint plugin for WooCommerce](https://docs.getbizprint.com/set-up/create-printer-location/)
- [BizPrint for developers overview](https://docs.getbizprint.com/developers/)

Need help? Contact BizPrint support at <https://getbizprint.com/support/>.
