25+ Essential WooCommerce Checkout Snippets: The Master List (No Plugins)
Stop bloating your database with heavy plugins. Here is the ultimate collection of copy-paste PHP codes to customize every inch of your checkout page manually.

As a WordPress developer, I write the same WooCommerce checkout snippets for client after client. Instead of searching Stack Overflow every time, I compiled everything into this reference page.
These are the 30 most-requested WooCommerce checkout customisations, organised by category, with a brief explanation of what each snippet does and when to use it. All snippets go in your child theme’s functions.php. They work with the Classic Checkout shortcode [woocommerce_checkout].
⚠️ WooCommerce Blocks vs Classic Checkout
All snippets on this page use PHP filter and action hooks that only work with the Classic Checkout shortcode. If your checkout page uses the WooCommerce Blocks editor (introduced in WooCommerce 8+), these hooks are not triggered and the snippets will appear to do nothing. Go to WooCommerce → Settings → Advanced and check which page is set as your checkout. For full PHP control, the page must use [woocommerce_checkout], not a block-based template.
⚠️ Always Use a Child Theme
Add all snippets to your child theme’s functions.php, never the parent theme. Parent theme updates will erase your changes. Don’t have a child theme? Create one free in 10 seconds →
📋 Jump to a Section
① Field Management
Add, remove, rename, reorder, and change the required status of any checkout field.
1. Remove Unnecessary Fields
The most common request. For B2C stores, Company Name, Address Line 2, and Order Notes are rarely needed and add visual clutter. Uncomment only the lines you want to remove.
add_filter( 'woocommerce_checkout_fields', 'musa_remove_checkout_fields' );
function musa_remove_checkout_fields( $fields ) {
unset( $fields['billing']['billing_company'] ); // Company Name
unset( $fields['billing']['billing_address_2'] ); // Address Line 2
// unset( $fields['billing']['billing_postcode'] ); // Only remove for digital products
// unset( $fields['billing']['billing_phone'] ); // Caution: used for order notifications
unset( $fields['order']['order_comments'] ); // Order Notes
return $fields;
}
2. Remove Order Notes Only (One-Liner)
When you only want to hide the Order Notes box and nothing else, this is the cleanest approach — no need to touch the full field array.
add_filter( 'woocommerce_enable_order_notes_field', '__return_false', 9999 );
3. Make Phone Number Optional
Forcing a phone number kills conversions in many markets. Making it optional keeps the field available for customers who want to provide it without blocking those who don’t.
add_filter( 'woocommerce_billing_fields', 'musa_make_phone_optional' );
function musa_make_phone_optional( $fields ) {
$fields['billing_phone']['required'] = false;
return $fields;
}
4. Make State Field Optional
In some countries the State/Region field is confusing or irrelevant. Making it optional prevents unnecessary form abandonment.
add_filter( 'woocommerce_billing_fields', 'musa_optional_state_field' );
function musa_optional_state_field( $fields ) {
$fields['billing_state']['required'] = false;
return $fields;
}
5. Move Email to the Top of the Form
For digital products and subscription stores, the email address is the most critical field. Moving it to the top ensures you capture it before a user abandons mid-form. WooCommerce renders fields in ascending priority order — lower numbers appear first.
add_filter( 'woocommerce_billing_fields', 'musa_move_email_top' );
function musa_move_email_top( $fields ) {
$fields['billing_email']['priority'] = 1;
$fields['billing_phone']['priority'] = 2;
$fields['billing_first_name']['priority'] = 10;
$fields['billing_last_name']['priority'] = 20;
return $fields;
}
6. Rename Labels and Placeholders
Default labels like “Billing First Name” sound like database columns. Friendlier labels reduce cognitive friction and feel more conversational.
add_filter( 'woocommerce_checkout_fields', 'musa_rename_checkout_labels' );
function musa_rename_checkout_labels( $fields ) {
$fields['billing']['billing_first_name']['label'] = 'First Name';
$fields['billing']['billing_first_name']['placeholder'] = 'e.g. John';
$fields['billing']['billing_email']['label'] = 'Email Address';
$fields['billing']['billing_email']['placeholder'] = 'your@email.com';
$fields['order']['order_comments']['placeholder'] = 'e.g. Leave parcel at front door';
return $fields;
}
7. Change the “Billing Details” Section Heading
Uses the gettext filter to intercept the translation string and replace it. Works with any heading text that goes through WordPress’s translation system.
add_filter( 'gettext', 'musa_change_billing_heading', 10, 3 );
function musa_change_billing_heading( $translated_text, $text, $domain ) {
if ( 'woocommerce' === $domain && 'Billing details' === $text ) {
return 'Your Information';
}
return $translated_text;
}
8. Add a “Confirm Email” Field
Reduces failed order notifications caused by typos. Adds a second email field and validates that both match before allowing checkout to complete.
// Step 1: Add the confirmation field
add_filter( 'woocommerce_checkout_fields', 'musa_add_confirm_email_field' );
function musa_add_confirm_email_field( $fields ) {
$fields['billing']['billing_email']['class'] = array( 'form-row-first' );
$fields['billing']['billing_email_confirm'] = array(
'label' => __( 'Confirm Email Address', 'woocommerce' ),
'required' => true,
'class' => array( 'form-row-last' ),
'priority' => 999,
);
return $fields;
}
// Step 2: Validate on submission
add_action( 'woocommerce_checkout_process', 'musa_validate_confirm_email' );
function musa_validate_confirm_email() {
if ( isset( $_POST['billing_email'], $_POST['billing_email_confirm'] ) ) {
if ( $_POST['billing_email'] !== $_POST['billing_email_confirm'] ) {
wc_add_notice( __( 'Email addresses do not match.', 'woocommerce' ), 'error' );
}
}
}
② UX & Conversion
Snippets that improve the checkout experience and help more customers complete their purchase.
9. Change the “Place Order” Button Text
Action-oriented button text outperforms generic labels. Match the copy to your product type — “Get Instant Access” for digital, “Confirm Booking” for services, “Complete My Order” for physical goods.
add_filter( 'woocommerce_order_button_text', 'musa_custom_checkout_btn' );
function musa_custom_checkout_btn() {
return __( 'Complete My Order →', 'woocommerce' );
// Other options:
// 'Get Instant Access →'
// 'Pay Now →'
// 'Confirm My Booking →'
}
10. Auto-Check the Terms & Conditions Box
Reduces a click in the checkout flow. Check your local legal requirements before using this — in some jurisdictions, explicit opt-in for T&C is required.
add_filter( 'woocommerce_terms_is_checked_default', '__return_true' );
11. Remove the Coupon Code Field at Checkout
The coupon field at checkout can trigger customers to open a new tab and search for discount codes — then not return. Removing it from checkout (while keeping it on the cart page) prevents that leakage.
// Removes the coupon form from checkout only — cart page is unaffected
remove_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_coupon_form', 10 );
12. Collapse “Ship to Different Address” by Default
This toggle is open by default in some themes, which makes the checkout form feel longer than it is. Force it closed — customers who need it can still expand it.
add_filter( 'woocommerce_ship_to_different_address_checked', '__return_false' );
13. Show a “You Are Saving $X” Message
Displaying the total discount value right above the payment button reinforces the purchase decision at the moment of highest intent. Only shown when there are sale items in the cart.
add_action( 'woocommerce_review_order_before_payment', 'musa_show_savings_message' );
function musa_show_savings_message() {
$total_savings = 0;
foreach ( WC()->cart->get_cart() as $cart_item ) {
$product = $cart_item['data'];
if ( $product->is_on_sale() ) {
$savings = ( (float) $product->get_regular_price() - (float) $product->get_sale_price() ) * $cart_item['quantity'];
$total_savings += $savings;
}
}
if ( $total_savings > 0 ) {
echo '
‘; } }
14. Add a Newsletter Opt-In Checkbox
Adds a checkbox to the billing section. This snippet handles the UI only — wire it to your email provider (Mailchimp, Klaviyo, etc.) via the woocommerce_checkout_update_order_meta hook.
// Add checkbox to form
add_action( 'woocommerce_after_checkout_billing_form', 'musa_newsletter_checkbox' );
function musa_newsletter_checkbox( $checkout ) {
woocommerce_form_field( 'subscribe_newsletter', array(
'type' => 'checkbox',
'class' => array( 'form-row-wide' ),
'label' => ' Yes, send me order updates and offers.',
), $checkout->get_value( 'subscribe_newsletter' ) );
}
// Save value to order meta
add_action( 'woocommerce_checkout_update_order_meta', 'musa_save_newsletter_checkbox' );
function musa_save_newsletter_checkbox( $order_id ) {
$subscribed = isset( $_POST['subscribe_newsletter'] ) ? 'yes' : 'no';
update_post_meta( $order_id, '_subscribe_newsletter', $subscribed );
}
15. Auto-Fill Fields for Logged-In Users
WooCommerce does this by default, but some themes break the behaviour. This forces previously saved billing data into fields for logged-in customers, removing the need to re-enter it.
add_filter( 'woocommerce_checkout_get_value', 'musa_autofill_checkout', 10, 2 );
function musa_autofill_checkout( $value, $input ) {
if ( is_user_logged_in() && empty( $value ) ) {
$user = wp_get_current_user();
$map = array(
'billing_first_name' => $user->user_firstname,
'billing_last_name' => $user->user_lastname,
'billing_email' => $user->user_email,
);
if ( isset( $map[ $input ] ) ) {
return $map[ $input ];
}
}
return $value;
}
③ Validation & Rules
Server-side validation that runs on form submission, before the order is created.
16. Validate Postcode is Numeric Only
Prevents customers from entering text in the ZIP/postcode field. Useful for stores shipping only to countries with numeric postcodes (US, Germany, etc.).
add_action( 'woocommerce_checkout_process', 'musa_validate_postcode' );
function musa_validate_postcode() {
if ( isset( $_POST['billing_postcode'] ) && ! preg_match( '/^[0-9]+$/', $_POST['billing_postcode'] ) ) {
wc_add_notice( __( 'Please enter a valid numeric Postcode / ZIP code.', 'woocommerce' ), 'error' );
}
}
17. Block PO Box Shipping Addresses
FedEx and UPS do not deliver to PO Boxes. This regex catches common PO Box formats (“PO Box”, “P.O. Box”, “Post Office Box”) and blocks checkout with a clear error message.
add_action( 'woocommerce_checkout_process', 'musa_block_pobox' );
function musa_block_pobox() {
$address = isset( $_POST['shipping_address_1'] ) ? $_POST['shipping_address_1'] : '';
if ( preg_match( '/(p\.?\s*o\.?\s*box|post\s+office\s+box)/i', $address ) ) {
wc_add_notice( __( 'We do not ship to PO Boxes. Please enter a physical street address.', 'woocommerce' ), 'error' );
}
}
18. Restrict Checkout to Specific Countries
For programmatic country blocking beyond WooCommerce’s built-in settings — useful when you need different rules per product category or user role. Replace the array with real ISO 3166-1 alpha-2 country codes.
add_action( 'woocommerce_checkout_process', 'musa_restrict_shipping_countries' );
function musa_restrict_shipping_countries() {
$blocked = array( 'XX', 'YY' ); // Replace with real country codes, e.g. 'RU', 'KP'
$country = WC()->customer->get_shipping_country();
if ( in_array( $country, $blocked, true ) ) {
wc_add_notice(
__( 'Sorry, we do not currently ship to your country. Please contact us if you have questions.', 'woocommerce' ),
'error'
);
}
}
19. Limit Checkout to One Item Per Order
Useful for membership sites, limited-edition products, or single-session booking funnels. Empties the cart before adding the new item, so only one product is ever in the cart at a time.
add_filter( 'woocommerce_add_to_cart_validation', 'musa_only_one_item_in_cart', 10, 2 );
function musa_only_one_item_in_cart( $passed, $product_id ) {
wc_empty_cart();
return $passed;
}
20. Require a Minimum Order Amount
Prevents processing orders below a threshold — useful when shipping costs make small orders unprofitable. Shows the error on both the cart page and the checkout page.
add_action( 'woocommerce_checkout_process', 'musa_minimum_order_amount' );
add_action( 'woocommerce_before_cart', 'musa_minimum_order_amount' );
function musa_minimum_order_amount() {
$minimum = 20.00; // Minimum order value
if ( WC()->cart->total < $minimum ) { $message = sprintf( 'A minimum order of %s is required. Your current total is %s.', wc_price( $minimum ), wc_price( WC()->cart->total )
);
if ( is_cart() ) {
wc_print_notice( $message, 'error' );
} else {
wc_add_notice( $message, 'error' );
}
}
}
④ Order Flow & Fees
Control what happens during and after checkout — fees, redirects, and order behaviour.
21. Add a Custom Fee (Handling, Surcharge, etc.)
Adds a flat fee to every order. Change the label and amount as needed. The is_admin() check prevents the fee running on the admin order screen.
add_action( 'woocommerce_cart_calculate_fees', 'musa_add_handling_fee' );
function musa_add_handling_fee() {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
WC()->cart->add_fee( 'Handling Fee', 5.00 );
}
22. Add a Percentage-Based Surcharge
Instead of a flat fee, charge a percentage of the cart total — useful for payment processing cost recovery (e.g. a 2% card surcharge). Check your local consumer law before applying surcharges.
add_action( 'woocommerce_cart_calculate_fees', 'musa_add_percentage_fee' );
function musa_add_percentage_fee() {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
$percentage = 0.02; // 2%
$fee = WC()->cart->get_cart_contents_total() * $percentage;
WC()->cart->add_fee( 'Card Processing Fee (2%)', $fee );
}
23. Redirect to a Custom Thank You Page
After a successful order, redirect to a custom page — ideal for upsell funnels, video confirmation pages, or member onboarding flows. Change the URL to your page slug.
add_action( 'woocommerce_thankyou', 'musa_custom_redirect_after_order' );
function musa_custom_redirect_after_order( $order_id ) {
$order = wc_get_order( $order_id );
if ( $order && ! $order->has_status( 'failed' ) ) {
wp_redirect( home_url( '/thank-you-special/' ) ); // Change to your page
exit;
}
}
24. Remove the Privacy Policy Text from Checkout Footer
WooCommerce adds a “Your personal data will be used to process your order…” paragraph near the Place Order button. Remove it if your theme handles this elsewhere.
remove_action( 'woocommerce_checkout_terms_and_conditions', 'wc_checkout_privacy_policy_text', 20 );
25. Remove the Coupon Field from Cart Page Too
If you want to disable coupons entirely across both cart and checkout, use both hooks together.
// Remove from cart page
remove_action( 'woocommerce_before_cart', 'woocommerce_cart_coupon', 10 );
// Remove from checkout page
remove_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_coupon_form', 10 );
26. Add Content to the Order Confirmation Email
Appends custom HTML to the customer-facing order confirmation email — great for adding download links, onboarding steps, or referral offers after purchase.
add_action( 'woocommerce_email_after_order_table', 'musa_add_content_to_order_email', 10, 4 );
function musa_add_content_to_order_email( $order, $sent_to_admin, $plain_text, $email ) {
if ( ! $sent_to_admin && 'customer_completed_order' === $email->id ) {
echo '<p style="margin-top:20px;"><strong>What happens next?</strong><br>Your order will be dispatched within 1-2 business days. You will receive a tracking email as soon as it ships.</p>';
}
}
⑤ Trust & Messaging
Add security badges, notices, and social proof to reduce checkout anxiety.
27. Add a Trust Badge Banner Above the Form
Displays a security/trust message at the very top of the checkout page. The priority value 1 ensures it appears before any other checkout elements.
add_action( 'woocommerce_before_checkout_form', 'musa_add_checkout_trust_banner', 1 );
function musa_add_checkout_trust_banner() {
echo '<div class="checkout-trust-banner" style="background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;padding:14px 18px;margin-bottom:20px;font-size:14px;color:#166534;">
🔒 <strong>Secure Checkout</strong> — All transactions are 256-bit SSL encrypted.
</div>';
}
28. Add a Countdown Timer / Urgency Message
Displays a dynamic urgency notice above the payment section. Pair it with a real offer deadline for maximum effect — do not use fake timers.
add_action( 'woocommerce_review_order_before_payment', 'musa_add_urgency_notice' );
function musa_add_urgency_notice() {
echo '<p class="woocommerce-info" style="text-align:center;">
⚡ <strong>Free shipping ends tonight.</strong> Complete your order to qualify.
</p>';
}
29. Add a Custom Image / Banner Above Checkout
Insert a trust badge image strip or promotional banner at the top of the checkout. Replace the src with your own image URL.
add_action( 'woocommerce_before_checkout_form', 'musa_add_checkout_image', 1 );
function musa_add_checkout_image() {
echo '<img src="' . esc_url( get_template_directory_uri() . '/images/trust-badges.png' ) . '"
alt="Secure payment badges"
style="width:100%;max-width:480px;display:block;margin:0 auto 20px;">';
}
30. Display a Custom Message Based on Cart Contents
Shows a conditional message — for example, a free gift notice when the cart contains a specific product. Replace 99 with your product ID.
add_action( 'woocommerce_before_checkout_form', 'musa_conditional_checkout_notice', 5 );
function musa_conditional_checkout_notice() {
$target_product_id = 99; // Replace with your product ID
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( $cart_item['product_id'] === $target_product_id ) {
echo '<div class="woocommerce-message">🎁 Your free gift will be included with this order.</div>';
break;
}
}
}
How to Add These Snippets Safely
Option A — Child theme functions.php (best for developers): Open your child theme’s functions.php, paste snippets at the bottom above any closing ?> tag. If you don’t have a child theme yet, create one first — adding code to a parent theme means it gets wiped on every theme update.
Option B — Code Snippets plugin (best for non-developers): Install the free Code Snippets plugin from WordPress.org. Each snippet gets its own on/off toggle. A syntax error in one snippet won’t crash your entire site. You can label snippets, disable them temporarily, and manage them from a clean dashboard. Highly recommended if you’re not comfortable editing PHP files directly.
After adding any snippet, clear your caching plugin’s cache and test the checkout page before sending real customers through it.
Related WooCommerce Guides
- The Ultimate Guide to Customize WooCommerce Checkout Without Plugins — beginner-friendly walkthrough of the 5 most common customisations with detailed explanations
- How to Create a WordPress Child Theme Without Plugins — required before editing functions.php
- Free WordPress Child Theme Generator — create a child theme in 10 seconds
Need something not on this list?
I Write Custom WooCommerce Solutions
Conditional checkout fields, payment gateway customisation, multi-step checkout, B2B logic, or anything that requires custom code — I build it without plugins wherever possible. Starting at $10 on Fiverr.

