Practical WordPress guide

Purchase Order Number for WooCommerce Checkout: safe setup, failure cases, and rollback

A plain-language guide for nontechnical site owners. It separates what the parent plugin really knows from what a helper plugin should never guess.

Reviewed July 20, 2026Official-source links includedNo invented performance claims

Direct answer

To collect a PO number in WooCommerce, register one bounded text field through WooCommerce's supported additional checkout field API, choose whether it is optional or required, and let WooCommerce save the sanitized value with the order.

Keep the job separate from payment. A customer-supplied PO reference does not approve credit, create an invoice, establish payment terms, change the order total, or authorize fulfillment.

Purchase Order Number for WooCommerce Checkout follows that narrow boundary. Free collects and shows one reference to an authorized administrator. Pro adds plain-language customer-type choices, help text, email display, and authorized My Account display.

A PO number field is not a PO payment gateway

The words "purchase order" can describe several different jobs:

Job What it changes
Reference field Saves customer-supplied text with an order
Payment gateway Determines how or when the order is paid
Credit workflow Approves customer limits and terms
Invoice workflow Creates financial documents and due dates
Accounting sync Exchanges data with an external system
Procurement approval Applies organizational policy and authorization

A one-field plugin should claim only the first job.

Public support threads show the confusion. Users ask to make a purchase order number required, report that a purchase order option is missing at checkout, troubleshoot a purchase-order payment option, or want to show a PO number in My Account and order output.

Those are related but not identical problems. Naming the boundary on the settings screen prevents a merchant from mistaking saved text for payment approval.

Use WooCommerce's supported checkout field API

WooCommerce documents the Additional Checkout Fields API and provides a field implementation guide. The current CheckoutFields service source shows the platform-owned field lifecycle.

That API gives a focused extension a common path for supported native classic and block checkout. It is preferable to:

  • replacing checkout templates;
  • injecting a visual-only browser field;
  • writing directly to order database tables;
  • maintaining separate classic and block persistence code;
  • trusting unbounded request data;
  • using undocumented internal React state.

The plugin should register only when WooCommerce and the API are ready. If the API is missing, checkout should remain usable and the settings screen should show the requirement clearly.

Give the field one stable identity

A stable field ID such as storefixkit/po-number lets WooCommerce associate the value with the order. The shopper-facing label can change without changing that storage identity.

Use simple limits:

  • label: plain text, 80 characters or fewer;
  • value: plain text, 64 characters or fewer;
  • help sentence: plain text, 160 characters or fewer;
  • mode: optional, required, or a bounded Pro override.

Sanitize on input and escape on every output. Do not interpret the PO number as HTML, a URL, a formula, a command, a price, or an account identifier.

Required should block only the supported checkout request

When the field is required and empty, WooCommerce should return a field-level validation error through its normal checkout process. The plugin should not:

  • redirect the customer elsewhere;
  • clear the cart;
  • change the selected payment method;
  • create a failed order record itself;
  • alter totals or tax;
  • mark an order on hold;
  • run a remote approval request.

The correct failure is small and reversible: the shopper supplies the missing value and submits again.

An oversized value should also return a field error. Silently truncating a customer-supplied business reference can create a harder support problem than rejecting it clearly.

Customer-type rules should use names, not expressions

Some stores want the PO field required for wholesale customers, optional for ordinary accounts, and hidden for guests. A bounded Pro screen can list current WordPress roles plus Guest checkout and offer four choices:

  • Use Free setting;
  • Optional;
  • Required;
  • Hide the field.

This is understandable to a non-technical store owner. It avoids arbitrary PHP, nested condition groups, regexes, and internal role text boxes.

Limit the list. Twenty customer types, including guest checkout, is enough for a focused add-on and keeps configuration, sanitation, screenshots, and tests finite.

Email and My Account are display surfaces

After checkout, the same saved value can appear in WooCommerce order emails and native My Account order details.

Those surfaces do not change what the value means. A displayed PO number still does not prove that:

  • the customer's organization issued it;
  • the buyer was authorized;
  • credit was approved;
  • an invoice was accepted;
  • payment will arrive;
  • fulfillment may begin.

Email output should use the order WooCommerce already selected. My Account output should run only inside WooCommerce's authorized order-details flow. Do not create a public endpoint where knowing an order ID reveals the reference.

Test both checkout surfaces and business-data invariants

Use disposable products and customers. Record payment method, total, status, addresses, items, stock, notes, and email behavior before the test.

Test Expected result
Optional field left empty Checkout succeeds through normal WooCommerce rules
Required field left empty Only that checkout request shows a field error
Valid value submitted Same escaped value appears on the order
Value over 64 characters Clear field validation error; no silent truncation
Classic checkout Field follows the supported native path
Checkout Blocks Field follows the supported native path
Guest Pro rule hidden Field is not registered for that checkout context
Customer role required Field is required only for that bounded role choice
Pro unavailable Free mode and order storage continue locally
Plugins deactivated New field disappears; historical values remain

After each successful order, compare the WooCommerce-owned data. The plugin should not change payment, totals, tax, status, addresses, items, quantities, stock, coupons, notes, gateways, or customer roles.

Common failure boundaries

Checkout replacement

A page builder or third-party checkout can bypass WooCommerce's supported native field API. Test with the site's actual checkout and compare with a native checkout before attributing the result.

Email customization

An email builder can replace or omit native order meta hooks. Confirm the value exists on the order first, then test the specific email template.

Role override

A Pro customer-type choice can override the Free mode. Show the selected named role on the support report rather than asking the customer to reason about internal capabilities.

API unavailable

On unsupported WooCommerce versions, do not inject a fallback field that may save inconsistently. Leave checkout unchanged and show the version requirement to the manager.

Resource and privacy boundary

The checkout path can remain lightweight:

  • one registered native text field;
  • no custom table;
  • no cron or Action Scheduler job;
  • no order scan;
  • no frontend CSS or JavaScript;
  • no telemetry;
  • no accounting API;
  • no checkout StoreFixKit request.

The PO value stays in the store's WooCommerce order. License activation is a separate administrator action; checkout must not call the StoreFixKit license service.

Market boundary

WooCommerce sells broader products for both Purchase Order payment and checkout field editing. Their existence is evidence that merchants pay to adjust B2B payment and checkout workflows.

It does not mean a small store needs either broad product. A merchant who only wants one recognizable reference field can benefit from fewer decisions, fewer permissions, and a smaller regression surface.

Rollback and historical records

Keep the current Free and Pro ZIPs and a database backup. Place one disposable order with the current release, record the PO value and all WooCommerce-owned fields, then test the known baseline packages.

Deactivation should stop new field collection immediately. Historical _wc_other/storefixkit/po-number values should remain on existing orders so an update or accidental uninstall does not silently erase business references.

Default uninstall should preserve settings. An explicit STOREFIXKIT_DELETE_DATA=true cleanup may remove only Free settings, Pro rules, and the Pro license option. It must not remove historical order values or any WooCommerce payment, total, status, address, item, stock, note, invoice, gateway, user, or customer record.

The PO Number documentation contains real screenshots, exact setup, troubleshooting, rollback, uninstall ownership, and the support evidence to collect.

FAQ

How do I add a PO number to WooCommerce checkout?

Register one bounded text field through WooCommerce's supported additional checkout field API, choose Optional or Required, and let WooCommerce save the sanitized value with the order.

Is a PO number a payment method?

No. It is customer-supplied reference text. Payment terms, credit approval, invoicing, and accounting require separate reviewed workflows.

Does it work with WooCommerce Checkout Blocks?

Yes on WooCommerce 8.9 or newer through the official additional checkout field API used for supported native classic and block checkout.

Can different customer types see different behavior?

Pro can apply Use Free setting, Optional, Required, or Hidden to guest checkout and a bounded list of named WordPress user roles.

What happens when Pro expires?

Free keeps collecting and preserving the configured field locally. Pro customer-type rules, help text, email display, and My Account display turn off.

Focused plugin

Use the one-job implementation.

Ask for one optional or required purchase order number through WooCommerce's supported native checkout-field API and preserve it on the order without changing payment.