How to Generate Printable QR Codes for WooCommerce Products
A QR code on a screen is not the same problem as a QR code on a sticker. The on-screen one is forgiving — high contrast, infinite resolution, perfect lighting. The printed one has to survive a 12mm thermal label, a smudged inkjet, a phone camera at arm’s length, and the box being half-rotated under bad warehouse lighting. Most “QR code for WooCommerce” tutorials skip every part of that and just dump a 200×200 PNG into a shortcode.
Scan orders, not spreadsheets. Order Barcodes for WooCommerce adds a scannable barcode and QR code to every order — built for check-ins, pickups, and fulfillment.
This post is the build guide. It covers what to actually encode in a product QR, what resolution to render at for a given physical label size, how to bulk-export labels for an entire catalog, and three setups depending on how much code you want to touch. If you’re researching the broader topic first, the pillar guide on WooCommerce QR codes covers the conceptual ground.
What goes inside the QR matters more than the QR
Before any rendering, decide what the scan should do. There are three sane payloads for product QR codes, and choosing wrong is the most common reason a printed sticker ends up useless six months later.
| Payload | Example | Best for | Failure mode |
|---|---|---|---|
| Product URL | https://store.com/product/widget-blue/ |
Retail shelf tags, marketing | Permalinks change → dead QR |
| SKU only | WID-BLUE-42 |
Internal warehouse, POS lookup | Useless without an app that knows what to do with it |
| Short redirect | https://store.com/q/a8f3 |
Anything you might re-route later | Requires a redirect table you maintain |
The third option — a short redirect under your own domain — is the only one that’s safe to print on something that goes into the world for years. You keep a redirect map (a custom post type or a single options row works fine), and if the destination needs to change you update the row. The sticker on the box doesn’t care.
For internal-only labels (warehouse bins, kitting trays, inventory counts), encode the SKU as plain text. Your scanner app reads the string and queries WooCommerce. Don’t put a URL on a label that never leaves the building.
DPI math: how big does the QR have to be?
A QR code prints reliably when each “module” (the smallest black square) is at least 0.4mm wide on paper. Below that you start losing scans on cheap thermal printers, especially at distance.
A standard product URL of ~30 characters fits in a Version 3 QR (29×29 modules) at error correction level M. With quiet zone (4 modules), that’s 37 modules wide. So:
minimum physical size = 37 × 0.4mm = 14.8mm
That’s your floor for a small label. For an Avery L7120 35×35mm square you have plenty of room — render at 600 DPI and it’ll look sharp.
Render resolution math:
pixels = (mm / 25.4) × DPI
30mm at 300 DPI = (30 / 25.4) × 300 = 354px
30mm at 600 DPI = 708px
Render at 2× your target DPI minimum. A 354px PNG printed at 30mm via a thermal driver that resamples to 203 DPI will look blocky. A 708px PNG resamples down cleanly. There is no point rendering above 1200px for a product label — you’re just making bigger files for no scan benefit.
Use error correction level M (15% recovery) for clean indoor labels and Q (25%) for anything that gets handled, scuffed, or sits outdoors. Level H eats into your data capacity and is overkill for product use.
Setup 1: Plugin-only (the ten-minute path)
If you don’t want to touch code, install a plugin that generates and prints. The honest comparison:
- Order Barcodes & QR Codes for WooCommerce — built primarily for order workflows but supports product QR codes with bulk PDF export.
- WooCommerce QR & Barcode Generator (official) — Woo’s first-party option, supports printable PDF labels with customizable fields.
- YITH WooCommerce Barcodes and QR Codes — generates on products and orders, decent UI.
- A4 Barcode Generator — free, opinionated toward A4 sheet output.
For comparing the broader plugin field, see the best WooCommerce barcode plugins comparison.
The workflow is the same across them: install, choose what to encode (URL / SKU / custom field), select the products in admin, click “Generate PDF.” The differences are layout flexibility (how many labels per A4 sheet, support for thermal label sizes) and whether the QR contains live product data or a static snapshot at generation time.
Setup 2: A WP-CLI script for bulk export
If you have more than ~500 SKUs or you want to regenerate the full catalog on a schedule, the admin “select all → export” loop falls over. A 30-line WP-CLI command is faster and scriptable.
// drop in a mu-plugin or your theme's functions.php
if ( defined( 'WP_CLI' ) && WP_CLI ) {
WP_CLI::add_command( 'pd qr-export', function( $args, $assoc_args ) {
$out_dir = $assoc_args['out'] ?? WP_CONTENT_DIR . '/qr-exports';
wp_mkdir_p( $out_dir );
$products = wc_get_products( [
'limit' => -1,
'status' => 'publish',
'return' => 'ids',
] );
foreach ( $products as $pid ) {
$product = wc_get_product( $pid );
$payload = home_url( '/q/' . $product->get_sku() );
// chillerlan/php-qrcode — Composer-installed
$qr = ( new \chillerlan\QRCode\QRCode(
new \chillerlan\QRCode\QROptions( [
'eccLevel' => \chillerlan\QRCode\QRCode::ECC_Q,
'scale' => 12,
'imageBase64' => false,
] )
) )->render( $payload );
file_put_contents( "$out_dir/{$product->get_sku()}.png", $qr );
WP_CLI::log( "Generated: {$product->get_sku()}" );
}
} );
}
Run with wp pd qr-export --out=/tmp/labels. The chillerlan/php-qrcode library is the right pick over the older phpqrcode — it’s actively maintained, supports SVG output, and has a sane API. Install via Composer in your theme or mu-plugin: composer require chillerlan/php-qrcode.
Once you have a folder of PNGs, lay them out into a printable PDF with mPDF or DomPDF. Or — simpler if you do this once a quarter — drop them into a Google Sheet or Avery Design & Print template. Don’t write a label-layout engine if you’re going to print labels four times a year.
Setup 3: On-demand single label from the product admin
For the case where staff want to print one label for a single product, add a meta box.
add_action( 'add_meta_boxes', function() {
add_meta_box(
'pd_product_qr',
'Product QR',
function( $post ) {
$sku = get_post_meta( $post->ID, '_sku', true );
if ( ! $sku ) {
echo '<p>Set a SKU first.</p>';
return;
}
$url = admin_url( "admin-ajax.php?action=pd_qr&sku=" . rawurlencode( $sku ) );
printf(
'<img src="%s" style="width:200px;height:200px"><br>
<a href="%s" target="_blank" class="button">Open print view</a>',
esc_url( $url ),
esc_url( $url . '&print=1' )
);
},
'product',
'side'
);
} );
add_action( 'wp_ajax_pd_qr', function() {
$sku = sanitize_text_field( $_GET['sku'] ?? '' );
if ( ! $sku ) wp_die( 'no sku', 400 );
header( 'Content-Type: image/png' );
header( 'Cache-Control: public, max-age=86400' );
echo ( new \chillerlan\QRCode\QRCode(
new \chillerlan\QRCode\QROptions( [ 'scale' => 8, 'eccLevel' => 16 ] )
) )->render( home_url( "/q/$sku" ) );
exit;
} );
This gives every product a sidebar QR that staff can print straight from the browser. Add a ?print=1 branch that renders a centered image on a blank page sized for your labels. Cheap, fast, no PDF library needed.
Print testing — actually do it
Before you commit a QR design to a 5,000-label print run, test the full pipeline:
- Render at the planned dimensions, print one sheet on the actual printer.
- Scan with three different phones, including one cheap Android, in normal warehouse light.
- Crumple, smudge with a thumb, and scan again.
- Photograph from 30cm away and scan from the photo (this catches resolution problems labs miss).
If any of those fail, bump scale by 50% or step error correction up one level. Re-test. The cost of a failed print run is hours of relabeling.
When a QR is the wrong choice
For a single-line numeric SKU that staff scan with a tethered USB barcode gun, a Code 128 1D barcode is faster, smaller, and cheaper to print. QR codes win when the payload is a URL, when the scan happens via phone camera, or when the label has to survive partial damage. The QR vs barcode comparison goes deeper on the trade-offs.
For internal warehouse use specifically, see the warehouse picking and packing setup — it’s a different problem with different answers.
If you’d rather skip the build, Order Barcodes & QR Codes for WooCommerce handles all three setups above out of the box, with bulk export, customizable label layouts, and a stable redirect system so your printed stickers don’t expire when you change permalinks.
Ready to speed up check-ins and fulfillment? Every order gets a unique code you can scan from any phone camera or USB scanner — no third-party service, no order data leaving your site.
Want help applying this?
Tell us your workflow and we'll point you to the right plugin or next step.