Shopify Packing Slip Template Generator

A Liquid packing slip for Order Printer, in A4, Letter or a 4×6 label, with a scan code and gift messages.

Describe the result you need. AI will set up the tool and ask for any missing details.

Configure with AI

Enter to submit · Shift + Enter for a new line

Sent to AI. Leave out passwords and private customer data.

Your details

Paper
Content

A QR code, loaded from the free api.qrserver.com image service when the slip prints (Liquid can't draw one itself). For product-level 1D barcodes, use our Barcode Generator.

Reads a product metafield you create: Settings > Custom data > Products > Add definition, namespace custom, key bin_location.

Reads the order note, or a "Gift message" cart attribute if your theme collects one separately.

Order Printer Liquid template

packing-slip.liquid
{%- comment -%}
  Packing slip {{ order.name }} — Liquid template for Shopify's Order Printer app.
  Paste this into Order Printer > your template > Edit code, or create a new template with it.
{%- endcomment -%}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Packing slip {{ order.name }}</title>
<style>
  * { box-sizing: border-box; }
  body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; color: #111; margin: 0; padding: 32px; font-size: 13px; line-height: 1.5; background: #fff; }
  .doc { max-width: 760px; margin: 0 auto; }
  .row { display: flex; justify-content: space-between; gap: 24px; }
  .head { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 28px; gap: 16px; }
  h1 { font-size: 22px; margin: 0 0 4px; letter-spacing: -0.02em; }
  h2 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; color: #666; margin: 24px 0 8px; }
  table { width: 100%; border-collapse: collapse; margin-top: 8px; }
  th, td { text-align: left; padding: 8px 10px; border-bottom: 1px solid #e3e3e3; font-size: 12.5px; }
  th { text-transform: uppercase; font-size: 10.5px; letter-spacing: 0.05em; color: #666; border-bottom: 2px solid #111; }
  td.num, th.num { text-align: right; }
  .totals { margin-top: 12px; width: 260px; margin-left: auto; }
  .totals div { display: flex; justify-content: space-between; padding: 4px 0; }
  .totals .grand { font-weight: 700; border-top: 2px solid #111; margin-top: 4px; padding-top: 8px; font-size: 15px; }
  .muted { color: #666; }
  .box { border: 1px solid #ddd; border-radius: 8px; padding: 12px 14px; }
  .scan { text-align: center; }
  @media print { body { padding: 0; } @page { size: auto; margin: 12mm; } }
@media print { @page { size: A4; margin: 14mm; } }</style>
</head>
<body>
<div class="doc">
<div class="head">
  <div>
    <h1>Packing slip</h1>
    <p class="muted">Order {{ order.name }} · {{ order.created_at | date: "%B %d, %Y" }}</p>
  </div>
  <div class="box" style="text-align:right">
    <p><strong>{{ shop.name }}</strong></p>
    {%- if shop.email %}<p class="muted">{{ shop.email }}</p>{% endif -%}
  </div>
</div>
<div class="row">
  <div>
    <h2>Ship to</h2>
    <p><strong>{{ shipping_address.name }}</strong></p>
    <p class="muted">
      {{ shipping_address.address1 }}{% if shipping_address.address2 != blank %}<br>{{ shipping_address.address2 }}{% endif %}<br>
      {{ shipping_address.city }}, {{ shipping_address.province_code }} {{ shipping_address.zip }}<br>
      {{ shipping_address.country }}
    </p>
  </div>
  <div style="text-align:right">
    <h2>Order details</h2>
    <p>Email: {{ order.email }}</p>
    {%- if order.phone %}<p>Phone: {{ order.phone }}</p>{% endif -%}
  </div>
</div>
{%- if order.note != blank -%}
<div class="box" style="margin-bottom:16px">
  <h2 style="margin-top:0">Gift message</h2>
  <p>{{ order.note }}</p>
</div>
{%- endif -%}
<table>
  <thead>
    <tr>
      <th>SKU</th>
      <th>Item</th>
      <th class="num">Qty</th>
    </tr>
  </thead>
  <tbody>
    {%- for line in line_items -%}
    <tr>
      <td>{{ line.sku }}</td>
      <td>{{ line.title }}{% if line.variant_title != blank and line.variant_title != "Default Title" %} ({{ line.variant_title }}){% endif %}</td>
      <td class="num">{{ line.quantity }}</td>
    </tr>
    {%- endfor -%}
  </tbody>
</table>
<div class="scan" style="margin-top:20px">
  <img src="https://api.qrserver.com/v1/create-qr-code/?size=120x120&data={{ order.name | url_encode }}" width="120" height="120" alt="Scan for order {{ order.name }}">
  <p class="muted">{{ order.name }}</p>
</div>
<h2>Returns</h2>
<p class="muted">Questions about this order? Contact {{ shop.email }}.</p>
</div>
</body>
</html>

This Liquid uses the objects Shopify's free Order Printer app provides (order, line_items, shop, billing_address, shipping_address, discounts, tax_lines). Order Printer no longer shows up as a new install on the Shopify App Store; stores that already have it keep it and can edit its templates. If you don't have it, use the built-in Orders > Export/Print bulk action for a plain version, or a paid app (Order Printer Templates, Order Printer Pro) if you want this Liquid customized visually without code.

In Order Printer: Templates > Create template (or edit an existing one) > Edit code, then paste this in and Save. Bulk-print from Orders by selecting orders, then More actions > Print packing slips (or your template's name).

Live preview

What this generates

The output is Liquid, built for Shopify's Order Printer app, using the same objects Shopify's order templates provide: order, line_items, shop, shipping_address, and so on. Pick a paper size (A4, Letter, or a 4×6 label for thermal or small-format printers) and which extras to include.

  • Scan code: a QR code of the order number for quick lookup, not a 1D barcode. For product-level barcodes, use our Barcode Generator.
  • Bin location: reads a custom.bin_location product metafield you create yourself, useful for warehouse picking.
  • Gift message: shows the order note when one exists.

Order Printer isn't a new install anymore

Shopify's Order Printer app no longer appears as a new install on the Shopify App Store. If your store already has it, you can still edit its templates with this Liquid. If you don't have it installed, use the built-in Orders > Print bulk action for a plain, uncustomized slip, or a paid template app (Order Printer Templates, Order Printer Pro) for a visual, code-free builder.

Setting up bin locations: Settings > Custom data > Products > Add definition, namespace custom, key bin_location.

Questions people ask

Do I need to code anything to use this?

No, just paste the generated Liquid into Order Printer's template editor. Turn options on or off here first to skip the parts you don't need.

Why a QR scan code instead of a real barcode?

A QR code renders reliably in Liquid with no font or encoding table needed and scans with any phone camera or barcode scanner. For a true 1D product barcode (UPC/EAN), use our dedicated Barcode Generator instead.

Can I bulk print packing slips for many orders at once?

Yes, select the orders in Shopify admin, then More actions > Print, choosing this template.

What if `bin_location` shows nothing?

You need to create that metafield definition first and set a value on each product; otherwise the field renders empty and the template shows an em dash.

Want this builtinto your store?

I'm Emmanuel, a Shopify and WooCommerce developer. If this tool pointed at something you'd rather have fixed for you (a faster store, cleaner product data, a migration, a custom feature), send me a note.

Emmanuel Asika

Emmanuel Asika

Shopify & WooCommerce developer, Dublin

I build and fix online stores: new builds, migrations, speed, SEO and the custom bits apps can't do.

hello@emmanuelasika.com