मुख्य सामग्री के लिए छोड़ें
संस्करण: 2.x

Receipt Data

WP admin: templates are edited in WP Admin → POS → Templates; this page lists the fields they can print.

To print or email a receipt, see Receipts and the Paid Screen; to pick a template, or have AI change one for you, see Customise Your Receipt.

This page is for editing a template's code by hand. Every template, HTML or thermal, prints from the same receipt data: the store, the order, the items, the totals and the payments. The page shows how to print a field, gives three common examples, and lists every field.

Jump to: Find a field · Common examples · If something goes wrong

  1. Open the template in WP Admin → POS → Templates (Edit it by hand has the details).
  2. Where the field should print, type its path between double braces, such as {{store.name}}, {{order.number}} or {{totals.total_display}}, or insert it from the field list beside the code.
  3. Check the preview below the code, then click Update to save.

For a list, such as the items, wrap the row in a section and it repeats once per item:

{{#lines}}
{{name}} x {{qty}} —
{{line_total_display}}
{{/lines}}

A section also leaves its contents out when the field is empty, zero or false, so {{#customer.id}}…{{/customer.id}} prints only for a named customer. To print money, use the field that ends in _display; see Currency fields.

Receipts print offline too: the app builds a copy of the receipt data from the order on the device.

Why receipts can differ

Where the data comes from​

Your store's server builds the receipt data for each order, and the app builds a shorter copy from the order on the device: it has no cashier, no store opening hours, notes or policies, and no totals.paid_total or totals.change_total. An HTML or thermal template opens at once from the device's copy and switches to the server's when it arrives; offline, the device's copy is the one that prints, so those fields print empty. With WCPOS Pro, the device's copy carries the store logo too; without Pro, the logo arrives with the server's copy. A legacy PHP template is always rendered by the server. That's why a template uses the fields below and never PHP order methods. A few fields print only when the server renders the template, as it does for a PDF download; If something goes wrong lists them.

The receipt, mapped​

Each part of a printed receipt comes from one section of the receipt data. Point at a part of the receipt or at its card to light up the pair; click or tap either one to jump to that section's fields. On a phone, the cards follow the receipt in the same order, top to bottom.

The receipt below, the first two recipes and the price breakdown use the same sample order. Its item amounts are before the coupon (line_subtotal_display); the gallery's receipt templates print them after it (line_total_display, 26.10 for the espresso).

Common recipes​

Most hand edits are one of these two, shown for an HTML template, and a third under them covers reprinting older orders. Each card shows the new rows on a receipt, then their code, then where to add it in your template. The item name, amount and TOTAL come from the rest of your template.

Using these in a thermal template

The same fields and sections work unchanged: put each printed line in a <text> element and leave out <s>, because thermal XML has no strike-through and prints the price plain (Thermal Templates).

2 × Espresso Beans26.10
34.00 · Savings −5.00
Strike through the regular price
{{#lines}}
{{#line_savings}}
  <s>{{line_regular_total_display}}</s>
  {{i18n.savings}}:
  -{{line_savings_display}}
{{/line_savings}}
{{/lines}}
Inside your template's existing {{#lines}} section, add the {{#line_savings}} block after the item row. 34.00 regular price − 5.00 sale saving − 2.90 coupon = 26.10 paid. The block leaves out both rows on orders with no recorded price history.
TOTAL59.97
Total saved10.28
Add a Total saved row
{{#totals.total_saved_complete}}
{{#totals.total_saved}}
  {{i18n.total_saved}}:
  {{totals.total_saved_display}}
{{/totals.total_saved}}
{{/totals.total_saved_complete}}
Add these lines after your TOTAL row. Two sections: the row is left out when the price history is incomplete, or when nothing was saved.
Reprint an order made before WCPOS 1.9.0
1 × Espresso Beans14.50
17.00 Discount −2.50
Reprint a pre-v1.9 order safely
{{#lines}}
{{#line_savings}}
  <s>{{line_regular_total_display}}</s>
  {{^savings_in_discounts}}
    {{i18n.savings}}:
    -{{line_savings_display}}
  {{/savings_in_discounts}}
{{/line_savings}}
{{#discounts}}
  {{i18n.discount}}:
  -{{discounts_display}}
{{/discounts}}
{{/lines}}
For an order made before WCPOS 1.9.0, not the sample order. Inside your template's existing {{#lines}} section, add the {{#line_savings}} and {{#discounts}} blocks after the item row. The saving is already inside the discount, so this prints the discount and leaves the saving out.

Field reference​

Expand a section to see its fields. The first item lists every section and its type.

All sections and their types

Top-level sections​

SectionWhat it holds
order (object)Order identity, status, dates, note, and payment URL information
store (object)Store identity, address, contact details, tax IDs, logo, hours, and footer text
cashier (object)User who processed the order
customer (object)Customer display name, addresses, and tax IDs
lines (array)Product line items
fees (array)Fee rows
shipping (array)Shipping rows
discounts (array)Coupon/discount rows
totals (object)Order totals, payment totals, refund summary, and item counts
tax (object)Tax display mode flags for section guards
tax_summary (array)Per-rate tax summary rows
has_tax_summary (boolean)Convenience guard for tax_summary
payments (array)Payment rows
refunds (array)Refund records applied to the order
fiscal (object)Fiscal snapshot fields populated by fiscal integrations
register (object)The register that took the sale: id and name. Empty strings when unknown
software (object)The software that issued the receipt: name (WCPOS), plugin_version, app_version, app_build, platform
presentation_hints (object)Formatting and renderer hints
i18n (object)Translated labels for bundled and custom templates
Order number, status and dates — order

order​

FieldTypeExample / description
order.idnumber1042
order.numberstringHuman-facing order number, e.g. "1042"
order.currencystringISO currency code, e.g. "USD"
order.customer_notestringCustomer/order note
order.wc_statusstringRaw WooCommerce status slug, e.g. "processing"
order.status_labelstringLocalised status label, including custom statuses
order.created_viastringSource/channel, e.g. "woocommerce-pos"
order.needs_paymentbooleanWhether a payment section should be shown
order.payment_urlstringOrder payment URL when available
order.createddate objectOrder creation date
order.paiddate objectPaid date, empty strings when not paid
order.completeddate objectCompleted date, empty strings when incomplete
order.printeddate objectRender-time print/reprint timestamp
Store name, address, contact and hours — store

store​

FieldTypeExample / description
store.idnumberStore ID, or historical ID for deleted stores
store.namestringStore display name
store.address.address_1stringStreet address line 1
store.address.address_2stringSuite/unit line
store.address.citystringCity/locality
store.address.statestringState/region
store.address.postcodestringPostal code
store.address.countrystringISO country code
store.address_linesarrayPreformatted address lines; recommended for most templates
store.tax_idsarrayStructured business tax IDs; loop this instead of using a single tax ID
store.phonestringStore phone
store.emailstringStore email
store.logostring/nullStore logo URL or data URI: the store's own logo, or else the WordPress site logo unless the store turns that off. null when there is neither
store.opening_hoursstring/nullCompact opening-hours text
store.opening_hours_verticalstring/nullMulti-line opening-hours block
store.opening_hours_inlinestring/nullComma-separated opening-hours text
store.opening_hours_notesstring/nullFree-text opening-hours notes
store.personal_notesstring/nullReceipt footer/personal note
store.policies_and_conditionsstring/nullRefund, returns, or terms text
store.footer_imprintstring/nullLegal footer imprint

Tax ID objects​

store.tax_ids and customer.tax_ids contain objects with the same shape:

FieldTypeDescription
typestringIdentifier such as eu_vat, de_steuernummer, au_abn, br_cpf, us_ein, or other
valuestringTax ID value to print
countrystring/nullISO country code; null for eu_vat and other
labelstringLocalised display label, resolved before rendering

Example:

{{#store.tax_ids}}
{{label}}: {{value}}
{{/store.tax_ids}}
Who served the customer — cashier

cashier​

FieldTypeExample / description
cashier.idnumberWordPress user ID, 0 when unknown
cashier.namestringCashier display name
Customer name, addresses and tax IDs — customer

customer​

FieldTypeExample / description
customer.idnumber/nullCustomer ID, or null for guests
customer.namestringCustomer display name, or guest label
customer.first_namestringThe billing first name, for a greeting such as "Thanks, Nia". Empty for guests without one
customer.billing_address.*objectWooCommerce billing address fields
customer.shipping_address.*objectWooCommerce shipping address fields
customer.tax_idsarrayStructured customer tax IDs snapshotted from the order

Common address keys include first_name, last_name, company, address_1, address_2, city, state, postcode, country, email, and phone.

Items sold — lines

lines​

Loop with {{#lines}}...{{/lines}}. Sample values are the espresso line from the sample order.

Every money field comes in two: the number, for a {{#…}} section (zero and null hide it, and a null field has no _display field at all), and the _display text, for printing. Fields marked incl/excl also come with _incl and _excl versions, each with its own _display.

keyस्ट्रिंग
Stable line key / order item ID.
key"412"
skuस्ट्रिंग
Product SKU.
sku"ESP-500"
nameस्ट्रिंग
Product or line display name.
name"Espresso Beans"
qtyसंख्या
Quantity sold.
qty2
qty_refundedसंख्या
Quantity refunded for this line.
qty_refunded0
regular_priceसंख्याराशिनल करने योग्यकर सहित/कर रहित
Recorded regular unit price. null on orders without POS price history — wrap it in a section.
regular_price17
regular_price_display"$17.00"
selling_priceसंख्याराशिनल करने योग्यकर सहित/कर रहित
Pre-coupon selling unit price — the recorded POS price when available, otherwise derived from the stored line subtotal.
selling_price14.5
selling_price_display"$14.50"
unit_savingsसंख्याराशिनल करने योग्यकर सहित/कर रहित
Regular minus selling, clamped to zero. Zero is falsy, so guarded rows hide themselves.
unit_savings2.5
unit_savings_display"$2.50"
line_regular_totalसंख्याराशिनल करने योग्यकर सहित/कर रहित
Recorded regular price multiplied by quantity.
line_regular_total34
line_regular_total_display"$34.00"
line_selling_totalसंख्याराशिनल करने योग्यकर सहित/कर रहित
Pre-coupon selling price multiplied by quantity.
line_selling_total29
line_selling_total_display"$29.00"
line_savingsसंख्याराशिनल करने योग्यकर सहित/कर रहित
Total regular-to-selling-price savings for this line.
line_savings5
line_savings_display"$5.00"
savings_in_discountsबूलियन
True when the line's saving is already inside discounts, as on orders made before v1.9.0. Use it so a saving isn't printed twice.
savings_in_discountsfalse
unit_subtotalसंख्याराशिकर सहित/कर रहित
WooCommerce pre-discount unit value. Do not use this as the regular price.
unit_subtotal14.5
unit_subtotal_display"$14.50"
unit_priceसंख्याराशिकर सहित/कर रहित
Final unit value after WooCommerce discounts.
unit_price13.05
unit_price_display"$13.05"
line_subtotalसंख्याराशिकर सहित/कर रहित
Before coupon: WooCommerce's pre-discount line subtotal, the amount beside each item on the sample receipt above.
line_subtotal29
line_subtotal_display"$29.00"
discountsसंख्याराशिकर सहित/कर रहित
Native WooCommerce line discount as a positive value — coupons only on current orders.
discounts2.9
discounts_display"$2.90"
line_totalसंख्याराशिकर सहित/कर रहित
After coupon: the final line total, what the gallery's receipt templates print beside each item.
line_total26.1
line_total_display"$26.10"
total_refundedसंख्याराशि
Total refunded for this line as a positive value.
total_refunded0
total_refunded_display""
taxesऐरे
Per-rate tax rows for this line.
—
metaऐरे
Order item meta as {key, value} pairs.
—
attributesऐरे
Product/variation attributes as {key, value} pairs.
—

Displaying regular price and savings​

For a unit-price layout, show the recorded regular price, selling price, and saving like this:

{{#lines}}
{{#unit_savings}}
<span style="text-decoration: line-through;">{{regular_price_display}}</span>
<span>{{selling_price_display}}</span>
<span>{{i18n.savings}}: -{{unit_savings_display}}</span>
{{/unit_savings}}
{{/lines}}

Use the line-total fields when quantity matters:

{{#lines}}
{{#line_savings}}
<span style="text-decoration: line-through;">{{line_regular_total_display}}</span>
<span>{{i18n.savings}}: -{{line_savings_display}}</span>
{{/line_savings}}
{{/lines}}

selling_price is the price before coupons. Use unit_price or line_total for the final amount after WooCommerce discounts.

Reprinting orders created before v1.9.0

Older WCPOS orders may already include the regular-to-selling-price reduction in discounts. If your custom template prints both line savings and line discounts, use savings_in_discounts to avoid showing the same reduction twice:

{{#lines}}
{{#line_savings}}
<span style="text-decoration: line-through;">{{line_regular_total_display}}</span>
{{^savings_in_discounts}}
<span>{{i18n.savings}}: -{{line_savings_display}}</span>
{{/savings_in_discounts}}
{{/line_savings}}
{{#discounts}}
<span>{{i18n.discount}}: -{{discounts_display}}</span>
{{/discounts}}
{{/lines}}

If the template does not print a line-level discounts row, keep showing line_savings even when savings_in_discounts is true. The bundled templates handle this distinction automatically.

Fees and shipping — fees, shipping

fees and shipping​

Loop with {{#fees}}...{{/fees}} and {{#shipping}}...{{/shipping}}.

FieldTypeDescription
labelstringFee label or shipping method name
method_idstringShipping method ID (shipping only)
total / _incl / _exclnumberDisplay-side, inclusive, and exclusive totals
taxesarrayPer-rate tax rows
metaarray{key, value} meta pairs

Formatted variants: total_display, total_incl_display, and total_excl_display.

Coupons and discounts — discounts

discounts​

Loop with {{#discounts}}...{{/discounts}}.

FieldTypeDescription
labelstringCoupon description or code fallback. A discount added in the POS cart reads Discount, or Discount (10%) for a percentage
codestringCoupon code
discount_typestringWooCommerce coupon type slug, for example fixed_cart, percent, or fixed_product. Empty when the coupon no longer exists.
total / _incl / _exclnumberDiscount amount as a positive value

Formatted variants: total_display, total_incl_display, and total_excl_display. Add your own minus sign in the template if you want discounts shown as negative rows.

discount_type was added in Receipt Data v1.2. Fiscal receipt snapshots captured before then do not carry it.

Totals, amounts paid, refunds and item counts — totals

totals​

Sample values are from the sample order, which later received a $7.25 partial refund.

Money fields follow the same pairing as line items: a bare number for guards and a _display string for printing, with _incl/_excl variants where marked.

subtotalसंख्याराशिकर सहित/कर रहित
Order subtotal before discounts.
subtotal52.75
subtotal_display"$52.75"
discount_totalसंख्याराशिकर सहित/कर रहित
Order discount total as a positive value — coupons only on current orders.
discount_total5.28
discount_total_display"$5.28"
sale_savings_totalसंख्याराशिनल करने योग्यकर सहित/कर रहित
Total recorded regular-to-selling-price savings across product lines, including catalogue sales and till price changes.
sale_savings_total5
sale_savings_total_display"$5.00"
total_savedसंख्याराशिनल करने योग्यकर सहित/कर रहित
Combined WooCommerce discounts and regular-price savings, with legacy overlap removed. The one customer-facing figure for everything saved.
total_saved10.28
total_saved_display"$10.28"
total_saved_completeबूलियन
Whether the receipt has enough recorded price data to calculate the complete savings totals.
total_saved_completetrue
tax_totalसंख्याराशि
Total tax amount.
tax_total0
tax_total_display"$0.00"
totalसंख्याराशिकर सहित/कर रहित
Order grand total, following the tax display setting: with prices shown excluding tax it is the total minus tax. total_incl is always the amount charged.
total59.97
total_display"$59.97"
paid_totalसंख्याराशि
Amount paid / applied.
paid_total59.97
paid_total_display"$59.97"
change_totalसंख्याराशि
Change returned to the customer.
change_total0
change_total_display""
refund_totalसंख्याराशि
Total refunded as a positive value.
refund_total7.25
refund_total_display"$7.25"
net_totalसंख्याराशि
Total minus refunds, clamped to zero. 0 when nothing was refunded, so guard it with refund_total.
net_total52.72
net_total_display"$52.72"
total_qtyसंख्या
Sum of line item quantities.
total_qty4
line_countसंख्या
Count of product line rows.
line_count3

Use total_saved when you want one customer-facing figure for everything saved. Do not calculate it by adding discount_total and sale_savings_total in the template: orders created before v1.9.0 may already include their POS price saving in WooCommerce's discount total. The canonical total_saved field detects and removes that overlap.

Savings totals are null and total_saved_complete is false when any product line lacks enough recorded price data for a reliable aggregate. Guard the row with total_saved_complete, then use total_saved to hide a zero value:

{{#totals.total_saved_complete}}
{{#totals.total_saved}}
<span>{{i18n.total_saved}}: {{totals.total_saved_display}}</span>
{{/totals.total_saved}}
{{/totals.total_saved_complete}}

The bundled templates print Total saved from the tax-inclusive variant, totals.total_saved_incl_display, inside a single {{#totals.total_saved_incl}} guard. That one guard is enough because the value is null when the price history is incomplete and zero when nothing was saved.

Tax rows — tax, tax_summary

tax and tax_summary​

Use tax for display-mode guards and tax_summary for itemized rate rows.

Tax fieldTypeDescription
tax.displaystringincl or excl
tax.display_inclbooleanTrue when prices display inclusive of tax
tax.display_exclbooleanTrue when prices display exclusive of tax
tax.breakdownstringhidden, single, or itemized
tax.breakdown_hiddenbooleanTrue when tax rows should be hidden
tax.breakdown_singlebooleanTrue when a single tax total is preferred
tax.breakdown_itemizedbooleanTrue when per-rate rows are preferred
has_tax_summarybooleanTrue when tax_summary contains rows

Loop tax_summary with {{#tax_summary}}...{{/tax_summary}}.

FieldTypeDescription
codestringTax rate ID/code
ratenumber/nullRate percentage when resolved
labelstringTax rate label
compoundbooleanWhether the rate is compounded
taxable_amount_exclnumber/nullTaxable base excluding tax
tax_amountnumberTax collected
taxable_amount_inclnumber/nullTaxable base including tax

Formatted variants: taxable_amount_excl_display, tax_amount_display, and taxable_amount_incl_display.

Payments taken — payments

payments​

Loop with {{#payments}}...{{/payments}}.

FieldTypeDescription
method_idstringPayment method identifier
method_titlestringPayment method display title
amountnumberAmount applied to the order
transaction_idstringGateway transaction ID
tenderednumberCash amount tendered when present
changenumberCash change returned when present

Formatted variants: amount_display, tendered_display, and change_display.

Refunds — refunds

refunds​

Loop with {{#refunds}}...{{/refunds}}. Refund amounts are positive numbers: the template adds a minus sign, or prints them in their own returned-items block.

FieldTypeDescription
idnumberRefund record ID
datedate objectRefund creation date
amountnumberRefund total
subtotalnumberRefunded line subtotal
tax_totalnumberTax refunded
shipping_totalnumberShipping amount refunded
shipping_taxnumberShipping tax refunded
reasonstringRefund reason
refunded_by_idnumber/nullUser ID that issued the refund
refunded_by_namestringUser display name that issued the refund
refunded_paymentbooleanWhether the payment was refunded through the gateway
destinationstringWhere the money went back: original_method, cash or manual for a refund made in the POS; empty otherwise
gateway_idstringGateway ID used for the refund
gateway_titlestringGateway display title
processing_modestringProvider/manual processing mode
linesarrayRefunded product rows
feesarrayRefunded fee rows
shippingarrayRefunded shipping rows

Refund line fields include name, sku, qty, total, total_incl, total_excl, and taxes; templates rendered in the POS app also get line_total and unit_total. Refund fee and shipping rows use label, total, total_incl, total_excl, and taxes, and shipping rows add method_id. Display variants are added for totals and tax amounts.

Fiscal records — fiscal

fiscal​

Fiscal integrations and WCPOS Pro fill in the identity fields, such as the receipt number, hash and QR payload. The document fields say what kind of document is printing, so a template can print a refund or a register report differently from a sale.

FieldTypeDescription
fiscal.document_typestringsale by default; also refund, void, cancellation, closure, xreport or handover
fiscal.is_sale_documentbooleanTrue for a sale. Use the is_… flags as section guards
fiscal.is_refund_documentbooleanTrue for a refund
fiscal.is_void_documentbooleanTrue for a void: a sale cancelled before it was completed
fiscal.is_cancellation_documentbooleanTrue for a cancellation: a completed sale cancelled later
fiscal.is_closure_documentbooleanTrue for a register closure
fiscal.is_x_reportbooleanTrue for an X-report
fiscal.is_handoverbooleanTrue for a hand-over slip
fiscal.correctsstringOn a refund, the identity of the sale it corrects
fiscal.sale_timedate object/nullWhen the till recorded the sale, in the till's timezone
fiscal.sale_tzstringThe till's timezone, e.g. "Europe/Berlin"
fiscal.received_atdate object/nullWhen the store's server received the sale
fiscal.sale_counternumber/nullThe till's own sale counter
fiscal.immutable_idstringImmutable fiscal identifier
fiscal.receipt_numberstringFiscal receipt number
fiscal.sequencenumber/nullSequence counter
fiscal.hashstringHash/signature value
fiscal.qr_payloadstringQR payload for fiscal verification
fiscal.tax_agency_codestringTax authority code
fiscal.signed_atstringFiscal signing timestamp
fiscal.signature_excerptstringTruncated signature for display
fiscal.document_labelstringDocument label, e.g. Tax Invoice
fiscal.is_reprintbooleanWhether this render is a reprint
fiscal.reprint_countnumberReprint count
fiscal.extra_fieldsarray/objectJurisdiction-specific values, usually a list of {label, value} rows

Print the extra fields with a loop:

{{#fiscal.extra_fields}}
{{label}}: {{value}}
{{/fiscal.extra_fields}}
Formatting — presentation_hints

presentation_hints​

These fields are mostly for the app and the server, which use them to format the receipt. Templates rendered by the server can print all of them; templates rendered in the POS app get only display_tax, prices_entered_with_tax, rounding_mode, locale and order_barcode_type.

FieldTypeDescription
presentation_hints.display_taxstringincl or excl. Filled in by the app; the server leaves it out
presentation_hints.hour12boolean/nullTrue when the store's time format uses a 12-hour clock
presentation_hints.hour_tokenstring/nullThe hour pattern from the store's time format: h, hh, H or HH
presentation_hints.prices_entered_with_taxbooleanWhether catalogue prices include tax
presentation_hints.rounding_modestringWooCommerce tax rounding setting
presentation_hints.localestringLocale used for formatting
presentation_hints.timezonestringReceipt timezone
presentation_hints.currency_positionstringCurrency symbol position
presentation_hints.currency_symbolstringCurrency symbol
presentation_hints.price_thousand_separatorstringThousands separator
presentation_hints.price_decimal_separatorstringDecimal separator
presentation_hints.price_num_decimalsnumberDecimal places
presentation_hints.price_display_suffixstringWooCommerce price display suffix
presentation_hints.order_barcode_typestringBarcode type for a template that reads it: code128 (the default), qrcode, ean13, ean8 or upca. Filled in by the app; the server leaves it out, and the gallery templates set their barcode type in the template

The pre-formatted money fields (the *_display values such as totals.total_display) render amounts with the currency symbol in the order's currency, using the position and separators above — so receipts show $12.00, not USD 12.00. The raw order.currency field remains the ISO code for any logic in your template.

Receipt wording — i18n

i18n​

Use i18n labels instead of hardcoding text where possible:

{{i18n.order}} #{{order.number}}
{{i18n.cashier}}: {{cashier.name}}
{{i18n.total}}: {{totals.total_display}}

Common keys include order, date, cashier, customer, item, sku, qty, unit_price, regular_price, selling_price, savings, discount, subtotal, total_saved, total, tax, paid, tendered, change, tax_summary, refunded, net_total, customer_note, thank_you_purchase, opening_hours, the fiscal labels copy (prints COPY), reprint, register, sale_time, software, document_refund, document_void and document_cancellation, and the tax-ID label keys such as store_tax_id_label_eu_vat and customer_tax_id_label_other. Extra keys may be added by extensions.

How the prices relate​

One item on the receipt carries several prices, and the names are easiest to follow on the amounts themselves. This is the espresso line from the sample order — a $17.00 product on sale for $14.50, with a 10% coupon on top:

Espresso Beans — one unit (the order has two)
0regular price 17.00
ग्राहक कितनी राशि चुकाता हैunit_price → 13.05 · line_total → 26.10
कूपन छूट (SUMMER10)lines[].discounts → इस लाइन पर 2.90
नियमित कीमत की तुलना में बचतunit_savings → 2.50 · line_savings → 5.00
Sale savings across the ordertotals.sale_savings_total = 5.00
All coupon discounts across the ordertotals.discount_total = 5.28
Savings + discounts, legacy overlap removedtotals.total_saved = 10.28

A sale saving is the gap between the regular price and the selling price. A discount is what a coupon took off, as WooCommerce works it out. WooCommerce's order totals and reports hold only the discounts, so total_saved adds the two into one figure for the customer.

Rendering rules​

How money, prices with or without tax, and dates print. Open the one you need.

Print money, and hide zero amounts

Currency fields​

Money fields stay numbers, and each one gets a _display field formatted in the store's language and currency:

Numeric fieldDisplay field
totals.totaltotals.total_display
lines[].line_totallines[].line_total_display
payments[].amountpayments[].amount_display
tax_summary[].tax_amounttax_summary[].tax_amount_display

Print the _display field. Use the number only for a section or for machine-readable output: {{#totals.change_total}}…{{/totals.change_total}} leaves its row out when the amount is zero.

Print prices with or without tax

Tax display-aware fields​

Several fields come in three versions: with tax (_incl), without tax (_excl), and a plain one that follows the store's setting for showing prices in the cart with or without tax.

Convenience fieldInclusive fieldExclusive field
lines[].regular_pricelines[].regular_price_incllines[].regular_price_excl
lines[].selling_pricelines[].selling_price_incllines[].selling_price_excl
lines[].unit_savingslines[].unit_savings_incllines[].unit_savings_excl
lines[].line_regular_totallines[].line_regular_total_incllines[].line_regular_total_excl
lines[].line_selling_totallines[].line_selling_total_incllines[].line_selling_total_excl
lines[].line_savingslines[].line_savings_incllines[].line_savings_excl
lines[].unit_pricelines[].unit_price_incllines[].unit_price_excl
lines[].unit_subtotallines[].unit_subtotal_incllines[].unit_subtotal_excl
lines[].line_subtotallines[].line_subtotal_incllines[].line_subtotal_excl
lines[].discountslines[].discounts_incllines[].discounts_excl
lines[].line_totallines[].line_total_incllines[].line_total_excl
fees[].totalfees[].total_inclfees[].total_excl
shipping[].totalshipping[].total_inclshipping[].total_excl
discounts[].totaldiscounts[].total_incldiscounts[].total_excl
totals.subtotaltotals.subtotal_incltotals.subtotal_excl
totals.discount_totaltotals.discount_total_incltotals.discount_total_excl
totals.sale_savings_totaltotals.sale_savings_total_incltotals.sale_savings_total_excl
totals.total_savedtotals.total_saved_incltotals.total_saved_excl
totals.totaltotals.total_incltotals.total_excl
Print dates and times

Date objects​

Each date comes ready-formatted in several ways, so a template never has to format a date itself.

FieldDescription
datetime, date, timeDefault date/time strings
datetime_short, datetime_long, datetime_fullLocale-aware combined formats
date_short, date_long, date_fullLocale-aware date-only formats
date_ymd, date_dmy, date_mdyFixed-order date formats
weekday_short, weekday_longDay names
day, month, month_short, month_long, yearIndividual date parts

Available date objects: order.created, order.paid, order.completed, order.printed, refunds[].date, fiscal.sale_time, and fiscal.received_at. order.printed is refreshed at render time, which is useful for reprints. The two fiscal dates are null when the receipt has no fiscal record, so wrap them in a section.

Extending receipt data​

A plugin can add its own fields to the receipt data through the wcpos_receipt_data filter.

The filter — its arguments, the six modes and an example

WCPOS keeps the fields above free of any one plugin's data. When a plugin needs the receipt to know something WooCommerce does not model, it adds that itself through the wcpos_receipt_data filter, the same way plugins filter WooCommerce's own order totals. The filter runs on every receipt the server builds: live receipts, fiscal snapshots at payment time, PDF downloads, and legacy PHP templates. Before WCPOS 2.0 this filter was named woocommerce_pos_receipt_data; that name still works but is deprecated since 2.0 and is removed in 2.2 at the earliest (see Hook naming).

The third argument, $mode, says which document is being built: live, fiscal, refund, preview (sample receipts in the template editor and gallery), closure or xreport (register closure and X-report documents). In preview, closure and xreport the order is an unsaved one whose ID is 0; a plugin that needs a saved order should return $data unchanged when $order->get_id() is 0.

add_filter( 'wcpos_receipt_data', function ( array $data, WC_Abstract_Order $order, string $mode ) {
foreach ( $data['discounts'] as &$row ) {
if ( 'smart_coupon' === $row['discount_type'] ) {
$row['gift_card'] = true;
}
}
return $data;
}, 10, 3 );

A template can then guard on the new key like any other section:

{{#discounts}}
{{#gift_card}}Gift Card{{/gift_card}}{{^gift_card}}{{i18n.discount}}{{/gift_card}}{{#label}}: {{label}}{{/label}}
{{/discounts}}

Keys defined in the schema should keep their documented types. Added keys are not part of the schema, so they do not appear in the template editor's field picker, and fiscal snapshots only carry what the filter added at the time the order was paid. The filter is available from WCPOS 1.10.8.

Which receipts print an added key

Every added key reaches the receipts the server renders itself: PDF downloads and legacy PHP templates. HTML and thermal templates rendered in the POS app rebuild the data first: a key added inside order, store, cashier or customer comes through, but a key added anywhere else, such as on the discounts row above, is left out. On a live receipt with a fiscal snapshot, the fiscal identity, register and software are copied from the snapshot after the filter runs, so changing them in this filter has no effect; enrich the snapshot instead.

If something goes wrong​

A row prints $0.00 on one receipt and nothing on another. Some _display fields, such as totals.change_total_display, totals.refund_total_display and payments[].tendered_display, are empty at zero when the server renders the receipt, and $0.00 when the app does. Put the row inside a section on the number instead, so it is left out of both: {{#totals.change_total}}…{{/totals.change_total}}.

The Total saved row is missing. totals.total_saved_complete is false: at least one item has no recorded regular price, so the saving can't be worked out. Orders rung up before WCPOS 1.9.0 are the usual case.

The total is less than the customer paid. The store shows prices excluding tax, so totals.total is the total before tax. Print totals.total_incl_display for the amount charged. The legacy PHP receipt that ships with WCPOS prints that amount.

A field prints in the PDF download but not in the POS. Templates rendered in the app rebuild the data first and leave out a few fields, which print only in PDF downloads and legacy PHP templates. Print a field from the list below only in those, or guard it with a section so the POS receipt leaves it out.

Fields that differ between PDF and POS receipts
  • lines[].attributes, lines[].total_refunded_display and lines[].unit_subtotal_display (with its _incl and _excl twins)
  • software.platform
  • presentation_hints other than display_tax, prices_entered_with_tax, rounding_mode, locale and order_barcode_type
  • customer tax IDs of the German, Dutch, French, UK company and Swiss types
  • keys a plugin adds outside order, store, cashier and customer; see Extending receipt data

Versions​

The receipt data has its own version number, separate from the plugin's. Newer fields are missing from older receipts, such as a fiscal snapshot taken before the field existed, so guard them with a section.

VersionAdded
1.1Regular price, selling price and savings for each item, and the order's savings totals, including Total saved. None of them change the order totals or WooCommerce reports
1.2discounts[].discount_type
1.3customer.first_name and the customer display labels in i18n
1.4register, software, the fiscal document fields (fiscal.document_type, the is_… flags, sale_time, received_at, sale_tz, sale_counter, corrects) and their i18n labels