Warehance renders many of your customer-facing and warehouse-facing documents — packing slips, pick slips, batch cover sheets, order summaries, billing invoices, cycle count sheets, and more — from PDF Templates. Each template is a small XML document that tells Warehance where to draw text, tables, barcodes, and images on the page, and where to inject live data (order numbers, product SKUs, addresses) at print time.
This article covers the shared concepts: what a template is, the XML syntax, the placeholder system, how to use the editor and preview, and where each template type slots into Warehance. Individual template types (batch shipping cover/footer, pick slips, billing invoices, etc.) have their own deep-dive articles with type-specific placeholders and layout examples.
What a PDF Template Looks Like
Every template is a single <template> XML block that declares the page size and contains layout elements:
<template width="4in" height="6in" margins="0.25in" page-numbers="true">
<text size="14" weight="bold" align="center">Packing Slip</text>
<spacer height="0.15in"/>
<barcode type="code128" width="3in" height="0.6in" align="center">{{order_number}}</barcode>
</template>
Warehance's renderer parses the XML, replaces every {{placeholder}} with a real value at print time, expands any <data-rows> or <data-groups> loops against the live data, and produces a PDF.
Template Types
Each template has a type that determines where in Warehance it can be used and what data placeholders are available.
| Type | Where it prints | Typical page size |
|---|---|---|
| packing_slip | Included in the shipment PDF alongside the label | 4×6 or 8.5×11 |
| pick_slip | Printed for a single order's pick workflow | 4×6 or 8.5×11 |
| pick_list | Printed for a batch pick session (aggregated) | 8.5×11 |
| barcode | Printed on demand as a standalone barcode label | Configurable |
| product_barcode | Product-level SKU/barcode labels | Small formats |
| inbound_shipment | Prints when receiving an inbound PO | 8.5×11 |
| order_summary | Multi-order summary report | 8.5×11 |
| order_detail | Full per-order detail report | 8.5×11 |
| billing_invoice | Client-facing billing invoice PDFs | 8.5×11 |
| cycle_count | Cycle count sheet for inventory audits | 8.5×11 |
| batch_shipping_cover | Prepended to the combined batch shipping PDF | 4×6 required |
| batch_shipping_footer | Appended to the combined batch shipping PDF | 4×6 required |
Some template types have a fixed page size (like batch shipping cover and footer, which must be 4×6). The editor will show a note under the type dropdown when a size is required, and saving a template with the wrong size will be rejected with a clear error.
Creating a Template
Step 1: Click Templates in the left sidebar, then click PDF Templates.
Step 2: Click the Create button in the top right corner.
Step 3: Enter a Template Name (this is how you'll reference it later — pick something descriptive like "Warehouse Cover with Tracking").
Step 4: Choose a Template Type from the dropdown. If the type has a fixed page size, a hint will appear under the dropdown telling you what dimensions to use.
Step 5: Optionally click Browse Presets to start from a pre-built template. This opens a modal showing every preset available for the selected type — you can click any one to load its XML into the editor as a starting point.
Step 6: Edit the XML in the code editor. As you type {{, the editor will suggest available placeholders for the selected type.
Step 7: Click Generate Preview to render the template against sample data. Any errors in your XML (unbalanced tags, unknown attributes) will be reported here.
Step 8: Click Save Template.
The XML Syntax
Warehance's template renderer supports a small, purposeful set of layout elements. You do not need to know HTML or CSS — the syntax is closer to a report designer.
The <template> root
Every template starts with a <template> element that sets the page dimensions and default behavior:
<template width="4in" height="6in" margins="0.25in" page-numbers="true" font-family="Arial">
Attributes:
- width and height — page size. Supported units: in, mm, cm, pt, px.
- margins — page margin on all sides.
- page-numbers — "true" to render a page-number footer.
- font-family — default font for all text elements.
- page-breaks="false" — disable automatic page breaks entirely (useful for label-style templates that must fit exactly on one page).
Text
<text size="10" weight="bold" align="center" style="italic">Order #{{order_number}}</text>
Attributes:
- size — font size in points.
- weight — normal or bold.
- align — left, center, right.
- style — normal or italic.
- color — hex color code (e.g., #333333).
- height — explicit line height (useful for controlling vertical density).
- wrap="true" — wrap long strings across multiple lines.
- if="{{some_placeholder}}" — only render if the placeholder resolves to a non-empty value.
Rows and Columns
<row border="0">
<col width="60%" border="0">
<text size="10">Left column</text>
</col>
<col width="40%" border="0">
<text size="10" align="right">Right column</text>
</col>
</row>
Rows arrange columns side-by-side; each column stacks its children vertically. Use border="1" to draw a border.
Tables
Tables give you formal columns with headers and repeating rows:
<table border="1">
<columns widths="50%,25%,25%"/>
<header-row background-color="#f0f0f0" height="0.2in">
<cell align="left" size="9" weight="bold">Item</cell>
<cell align="center" size="9" weight="bold">Qty</cell>
<cell align="right" size="9" weight="bold">Price</cell>
</header-row>
<data-rows source="items">
<data-row>
<cell align="left" size="8">{{name}}</cell>
<cell align="center" size="8">{{quantity}}</cell>
<cell align="right" size="8">{{price}}</cell>
</data-row>
</data-rows>
</table>
- <columns widths="..."> declares column widths as percentages.
- <header-row> is optional; it renders once at the top of the table.
- <data-rows source="X"> iterates the array of data named X; each iteration renders the inner <data-row>.
Barcodes
<barcode type="code128" width="3in" height="0.6in" align="center" padding="0.1in">{{order_number}}</barcode>
Supported barcode types include code128, code39, qrcode. The value inside the tag is what gets encoded — it can include placeholders.
Images
<image src="{{product_image_url}}" width="0.5in" height="0.5in" fit="contain"/>
Use fit="contain" to preserve aspect ratio; fit="fill" to stretch to the box.
Spacing and Lines
<spacer height="0.15in"/>
<line color="#cccccc" height="0.5pt"/>
Placeholders and Data
Placeholders use double curly braces: {{order_number}}, {{customer_name}}, {{sku}}. Available names depend on the template type — the editor's autocomplete lists them all.
Names use snake_case. For example, {{batch_id}} (not {{Batch ID}}) and {{ship_to_city_state_zip}} (not {{Ship To City State Zip}}).
Conditional Rendering
Add if="{{some_placeholder}}" to any element to hide it when the placeholder is empty:
<text size="9" if="{{gift_note}}">Gift note: {{gift_note}}</text>
Boolean-style placeholders like {{is_bundle}} or {{priority}} resolve to the strings "true" or "false" — the if check treats "false" and empty the same way (both hide the element).
Loops with <data-rows>
Repeats a block once per item in an array. Used inside tables:
<data-rows source="items">
<data-row>
<cell>{{sku}}</cell>
<cell>{{name}}</cell>
<cell align="right">{{quantity}}</cell>
</data-row>
</data-rows>
Inside each iteration, placeholders like {{sku}} resolve to the current item's fields.
Loops with <data-groups>
Repeats a whole layout block (not just a table row) once per group. Groups can themselves contain nested <data-rows>:
<data-groups source="sections" keep-together="1.5in">
<text size="11" weight="bold">{{title}}</text>
<text size="8" if="{{tracking_number}}">{{carrier}} · {{tracking_number}}</text>
<table border="1">
<columns widths="50%,25%,25%"/>
<data-rows source="rows">
<data-row>
<cell>{{sku}}</cell>
<cell align="center">{{qty}}</cell>
<cell align="right">{{location}}</cell>
</data-row>
</data-rows>
</table>
</data-groups>
The keep-together="1.5in" attribute forces a new page to start if less than 1.5 inches remain on the current page when a new group begins — prevents section headers from stranding at the bottom.
Page Breaks
There are three ways pages break:
- Automatic — When content would overflow the bottom margin, the renderer inserts a page break automatically. The next content continues on a fresh page.
- Explicit <page> blocks — Wrap each logical page in a <page> element to force clean page breaks:
<template width="4in" height="6in" margins="0.2in">
<page>
<!-- page 1 content -->
</page>
<page>
<!-- page 2 content -->
</page>
</template>
- Auto-break disabled — Setting page-breaks="false" on the <template> root disables auto-breaks entirely, which is what you want for label-style templates that must fit on a single page (content past the bottom is clipped).
Auto and explicit page breaks work together: if content inside an explicit <page> overflows, an auto-break inserts an extra page, and the next <page> block still starts fresh.
Preview
The Generate Preview button renders your template against realistic sample data and shows the resulting PDF page-by-page in the preview panel on the right. Some template types let you pick between small / medium / large sample data sizes via a dropdown next to the preview button.
If the preview fails, an error message appears — usually because of an unbalanced tag or an unknown attribute. Fix the XML and click Generate Preview again.
Not every template type supports preview yet. If Generate Preview is disabled, the type is on the list to add preview support to soon. In the meantime, save the template and print it against a real record to verify.
Presets
Presets are pre-built templates that you can use as-is or as starting points. Click Browse Presets at the top of the editor to open the preset modal. Presets are filtered by the currently selected template type, so you'll only see presets that match.
Each preset shows a preview image, a name, a category (Basic, Detailed, With Tracking, etc.), and a description. Clicking a preset loads its XML into the editor, overwriting whatever was there.
Presets are a great way to learn the syntax. Load one, click Generate Preview to see how it renders, then tweak the XML to see the effect.
Assigning a Template to Warehance
Creating a template doesn't do anything until you tell Warehance where to use it. Each template type has a default template setting somewhere in the settings pages:
| Template type | Where the default is set |
|---|---|
| Packing slip | Settings → Shipping → Default Packing Slip Template |
| Pick slip | Settings → Picking → Default Pick Slip Template |
| Pick list | Settings → Picking → Default Pick List Template |
| Inbound shipment | Settings → Inbound Shipments → Inbound Shipment Template |
| Billing invoice | Settings → Shipping → Default Billing Invoice Template (or per billing profile) |
| Order summary | Settings → Order Summary Template |
| Order detail | Settings → Order Detail Template |
| Cycle count | Settings → Cycle Count Template |
| Batch shipping cover | Settings → Printing → Batch Cover Sheet Template |
| Batch shipping footer | Settings → Printing → Batch Footer Sheet Template |
Some template types can also be overridden per record (e.g. a billing profile can override the account-wide billing invoice template). See the individual type's deep-dive article for details.
If you leave the default template setting on None (use built-in default), Warehance uses its built-in layout. This is safe — you can experiment with a custom template and switch back at any time by clearing the setting.
Editing a Template
Templates you've saved appear in the PDF Templates list. Click any row to open the editor, make changes, click Generate Preview to verify, and click Save Template.
Warehance tracks a full change history for each template. Click the History tab on the edit page to see who changed what and when.
Editing a template affects every future PDF that uses it. If you're not sure a change is right, duplicate the template first (click Duplicate in the actions menu), edit the copy, test it in a non-production setting, and only assign it once you're happy.
Deleting a Template
From the PDF Templates list, click the ⋯ menu on a row and select Delete. If the template is currently assigned as a default anywhere, Warehance will warn you before deleting.
Troubleshooting
The preview is blank
- Check for typos in your {{placeholder}} names. Unknown names render as blank strings.
- Make sure your <template> tag is closed with </template>.
- If a <data-rows> or <data-groups> block's source doesn't match any data, that whole block renders empty.
Save fails with a size mismatch error
Some template types (like batch shipping cover/footer) require a fixed page size. Adjust the <template width="..." height="..."> attributes to match the required size, then save again.
Placeholders are rendering as literal {{placeholder_name}} text
Usually means the placeholder name is wrong — check the autocomplete list for the exact name (they're case-sensitive and use snake_case).
Content is clipping at the bottom of the page
Either the content is genuinely too tall for one page (add a <page> block or let auto page-breaks split it), or page-breaks="false" is set on the template root and you're expecting auto-break behavior — remove that attribute.
Table columns are all the wrong width
<columns widths="X%,Y%,Z%"/> percentages must add up to 100%. If they don't, cells shift unpredictably.
Related Articles
- Batch Shipping Cover and Footer Templates (comprehensive deep-dive with every placeholder and 8 preset examples)
- Setting a Default Template Per Client or Billing Profile
- Understanding Warehance's PDF Rendering Engine
Last updated: July 2026