Zum Inhalt springen

How tipping works

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

This page follows a tip from the moment a shopper sees the control on the checkout to where it lands on the order, and explains exactly how it behaves.

The control is added to the classic (shortcode) checkout, just above the payment methods (woocommerce_review_order_before_payment). It shows your label (heading), your optional description, a No tip button, and one button per preset. It only renders when tipping is enabled and at least one valid preset is set; otherwise nothing is output and no assets load.

The shopper clicks a button. Each button is a native <button> carrying aria-pressed, and the active one is also marked with an is-active class:

  • For a fixed type, each button shows a currency amount (wc_price), e.g. £5.00.
  • For a percentage type, each button shows a whole percentage, e.g. 10%.

On click, the script sends the choice to the server over a nonce-protected tipping_set AJAX call, stores it in the WooCommerce session, then triggers WooCommerce’s update_checkout so the totals recalculate. The tip appears as a fee line with your label, and the totals the shopper will pay update immediately, no page reload.

A percentage preset is not frozen at selection. The amount is recomputed from the pre-tip, tax-exclusive items subtotal every time the cart recalculates, so if the shopper changes a quantity or the cart total shifts, the tip follows. Fixed presets stay the same flat amount whatever the cart does.

No tip is preselected, so the shopper pays nothing extra unless they choose an amount. Clicking No tip at any point resolves the tip to zero and removes the fee line on the next recalculation. The selection lives in the session, so it survives the checkout’s AJAX refreshes, the script re-binds the buttons after each updated_checkout so the active state stays correct.

The buttons are standard, individually focusable <button> elements:

  • Tab moves between the No-tip and preset buttons; Enter or Space activates the focused one.
  • Each button shows a visible focus-visible ring (a 2px outline in the accent colour), so keyboard users can always see focus.
  • The active button is exposed with aria-pressed="true"; the others report aria-pressed="false".
  • A .tipping__status line with aria-live="polite" sits under the buttons for status messages, so assistive tech is notified of changes without a reload.

The script is progressive enhancement loaded defer in the footer. If it does not run, the buttons still render and the server-side session persistence still applies the last stored choice on the next checkout refresh, the page never shows a broken control. The script depends on jQuery only to trigger and listen for WooCommerce’s own checkout events (update_checkout / updated_checkout); the AJAX call itself uses the browser fetch API.

The chosen tip is added to the order as a standard WooCommerce fee using your label, so it flows through everything WooCommerce already does with fees:

  • it appears in the order totals the customer pays,
  • it shows on the order in the admin,
  • it is included in order emails and in reports.

The resolved amount is additionally saved as _tipping_amount order meta at checkout, giving you a clean record for auditing or for splitting out tip revenue later. This meta is deliberately kept on uninstall.

The tip fee is always added as non-taxable. Tips and donations are not taxed, and there is no setting to change this.

  • Cafés and service businesses, a quick gratuity at checkout, usually as percentage presets.
  • Charities and causes, fixed donation presets with donation-oriented copy in the label and description.
  • Creators and small makers, an optional “support our work” tip, opt-in and low-pressure.
  1. The shopper reaches the checkout and sees the tip control with No tip active.
  2. They click the 10% preset; the totals recalculate and the tip appears as a fee line.
  3. They pay. The tip is part of the order totals, shows in the confirmation email and reports, and is recorded as _tipping_amount meta.