Dark Light

How to Edit WooCommerce Checkout Page (2026): Complete Guide

Varun Dubey 7 min read

Editing the WooCommerce checkout page at the code level gives you complete control over fields, validation, layout, and behavior. Unlike no-code plugins, custom code edits are lightweight, performant, and survive theme changes when placed in the right location.

This guide covers the developer approach to editing WooCommerce checkout using PHP hooks, filters, and custom validation. For no-code and visual customization methods, see our companion guide on customizing the WooCommerce checkout page.

Where to Place Custom Checkout Code

Never edit WooCommerce core files or your parent theme’s functions.php directly. Use one of these approaches:

  • Custom plugin (recommended): Create a simple plugin file in wp-content/plugins/my-checkout-edits/. This survives theme changes and is easy to disable
  • Child theme functions.php: Works but ties your customizations to one specific theme
  • Code Snippets plugin: Quick for testing but harder to manage long-term
<?php
/**
 * Plugin Name: Custom Checkout Edits
 * Description: WooCommerce checkout field and validation customizations
 * Version: 1.0.0
 */

if ( ! defined( 'ABSPATH' ) ) exit;

// Your checkout code goes here

The woocommerce_checkout_fields Filter

This is the most important hook for editing checkout fields. It gives you access to all billing, shipping, and order fields before they render.

Remove Fields

add_filter( 'woocommerce_checkout_fields', 'custom_remove_checkout_fields' );
function custom_remove_checkout_fields( $fields ) {
    // Remove company name
    unset( $fields['billing']['billing_company'] );
    
    // Remove phone (use cautiously - some shipping providers need it)
    unset( $fields['billing']['billing_phone'] );
    
    // Remove order notes
    unset( $fields['order']['order_comments'] );
    
    // Remove Address Line 2
    unset( $fields['billing']['billing_address_2'] );
    unset( $fields['shipping']['shipping_address_2'] );
    
    return $fields;
}

Make Fields Optional

add_filter( 'woocommerce_checkout_fields', 'custom_optional_fields' );
function custom_optional_fields( $fields ) {
    // Make phone optional instead of removing it
    $fields['billing']['billing_phone']['required'] = false;
    
    // Make company optional
    $fields['billing']['billing_company']['required'] = false;
    
    return $fields;
}

Reorder Fields

add_filter( 'woocommerce_checkout_fields', 'custom_reorder_fields' );
function custom_reorder_fields( $fields ) {
    // Move email to the top (lower priority = higher position)
    $fields['billing']['billing_email']['priority'] = 5;
    
    // Move phone after email
    $fields['billing']['billing_phone']['priority'] = 6;
    
    // Move first name after phone
    $fields['billing']['billing_first_name']['priority'] = 10;
    
    return $fields;
}

Add Custom Fields

add_filter( 'woocommerce_checkout_fields', 'custom_add_checkout_fields' );
function custom_add_checkout_fields( $fields ) {
    $fields['billing']['billing_delivery_date'] = array(
        'type'        => 'date',
        'label'       => 'Preferred Delivery Date',
        'required'    => false,
        'class'       => array( 'form-row-wide' ),
        'priority'    => 120,
    );
    
    $fields['order']['gift_message'] = array(
        'type'        => 'textarea',
        'label'       => 'Gift Message',
        'required'    => false,
        'class'       => array( 'form-row-wide' ),
        'placeholder' => 'Add a personal message (optional)',
    );
    
    return $fields;
}

// Save custom field values to order meta
add_action( 'woocommerce_checkout_update_order_meta', 'save_custom_checkout_fields' );
function save_custom_checkout_fields( $order_id ) {
    if ( ! empty( $_POST['billing_delivery_date'] ) ) {
        update_post_meta( $order_id, '_delivery_date', 
            sanitize_text_field( $_POST['billing_delivery_date'] ) );
    }
    if ( ! empty( $_POST['gift_message'] ) ) {
        update_post_meta( $order_id, '_gift_message', 
            sanitize_textarea_field( $_POST['gift_message'] ) );
    }
}

// Display custom fields in admin order view
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_custom_fields_admin' );
function display_custom_fields_admin( $order ) {
    $delivery = get_post_meta( $order->get_id(), '_delivery_date', true );
    $gift     = get_post_meta( $order->get_id(), '_gift_message', true );
    
    if ( $delivery ) {
        echo '<p><strong>Delivery Date:</strong> ' . esc_html( $delivery ) . '</p>';
    }
    if ( $gift ) {
        echo '<p><strong>Gift Message:</strong> ' . esc_html( $gift ) . '</p>';
    }
}

Custom Checkout Validation

WooCommerce provides hooks to add custom validation rules before an order is placed.

Basic Validation Example

add_action( 'woocommerce_checkout_process', 'custom_checkout_validation' );
function custom_checkout_validation() {
    // Require phone for physical products only
    if ( WC()->cart->needs_shipping() && empty( $_POST['billing_phone'] ) ) {
        wc_add_notice( 'Phone number is required for orders that need shipping.', 'error' );
    }
    
    // Validate delivery date is in the future
    if ( ! empty( $_POST['billing_delivery_date'] ) ) {
        $date = strtotime( sanitize_text_field( $_POST['billing_delivery_date'] ) );
        if ( $date && $date < strtotime( 'tomorrow' ) ) {
            wc_add_notice( 'Delivery date must be at least one day from now.', 'error' );
        }
    }
}

Conditional Validation Based on Cart Contents

add_action( 'woocommerce_checkout_process', 'validate_by_cart_contents' );
function validate_by_cart_contents() {
    $has_subscription = false;
    foreach ( WC()->cart->get_cart() as $item ) {
        $product = $item['data'];
        if ( $product->is_type( 'subscription' ) ) {
            $has_subscription = true;
            break;
        }
    }
    
    // Require account creation for subscription products
    if ( $has_subscription && ! is_user_logged_in() && empty( $_POST['createaccount'] ) ) {
        wc_add_notice( 'An account is required for subscription products. Please check "Create an account".', 'error' );
    }
}

Checkout Action Hooks for Custom Content

WooCommerce provides action hooks at specific positions in the checkout form. Use these to inject content without modifying templates.

Available Checkout Hooks

HookPositionUse Case
woocommerce_before_checkout_formBefore the entire formSecurity notice, login prompt
woocommerce_checkout_before_customer_detailsBefore billing/shippingExpress checkout buttons
woocommerce_before_checkout_billing_formBefore billing fieldsBilling instructions
woocommerce_after_checkout_billing_formAfter billing fieldsAdditional billing info
woocommerce_before_checkout_shipping_formBefore shipping fieldsShipping notes
woocommerce_before_order_notesBefore order notesCustom sections
woocommerce_review_order_before_submitBefore Place Order buttonTerms, trust badges
woocommerce_review_order_after_submitAfter Place Order buttonGuarantee text

Adding Trust Badges Before the Payment Button

add_action( 'woocommerce_review_order_before_submit', 'add_trust_badges_checkout' );
function add_trust_badges_checkout() {
    echo '<div class="checkout-trust-badges" style="text-align:center; padding:15px 0; margin:10px 0; border-top:1px solid #eee;">';
    echo '<p style="font-size:13px; color:#666;">Secure checkout powered by 256-bit SSL encryption</p>';
    echo '<p style="font-size:12px; color:#888;">30-day money-back guarantee | Free shipping over $75</p>';
    echo '</div>';
}

Modifying the Checkout Template

For major layout changes, you can override WooCommerce templates in your child theme.

How to Override Checkout Templates

  1. Copy wp-content/plugins/woocommerce/templates/checkout/form-checkout.php
  2. Paste to wp-content/themes/your-child-theme/woocommerce/checkout/form-checkout.php
  3. Edit the copied file

Warning: Template overrides require maintenance. After every WooCommerce update, check if the original template changed and merge any differences. WooCommerce marks template version in the file header comment.

Disabling Fields for Digital Products

If you sell only digital products (downloads, licenses, courses), you can remove all shipping fields and simplify billing:

add_filter( 'woocommerce_checkout_fields', 'simplify_digital_checkout' );
function simplify_digital_checkout( $fields ) {
    // Only simplify if cart has no physical products
    if ( ! WC()->cart->needs_shipping() ) {
        // Remove all shipping fields
        unset( $fields['shipping'] );
        
        // Remove unnecessary billing fields for digital
        unset( $fields['billing']['billing_company'] );
        unset( $fields['billing']['billing_address_1'] );
        unset( $fields['billing']['billing_address_2'] );
        unset( $fields['billing']['billing_city'] );
        unset( $fields['billing']['billing_postcode'] );
        unset( $fields['billing']['billing_country'] );
        unset( $fields['billing']['billing_state'] );
        unset( $fields['billing']['billing_phone'] );
    }
    
    return $fields;
}

HPOS Compatibility Note

If your store uses HPOS (High-Performance Order Storage), replace update_post_meta() and get_post_meta() with WooCommerce's order object methods:

// Instead of: update_post_meta( $order_id, '_delivery_date', $value );
// Use:
$order = wc_get_order( $order_id );
$order->update_meta_data( '_delivery_date', $value );
$order->save();

// Instead of: get_post_meta( $order_id, '_delivery_date', true );
// Use:
$order = wc_get_order( $order_id );
$delivery = $order->get_meta( '_delivery_date' );

This ensures your code works with both the legacy post-based storage and the new custom order tables. For more on HPOS and performance, see our guide on speeding up WooCommerce.

Testing Checkout Edits Safely

  • Always test on staging first: Never deploy checkout code directly to production
  • Test all payment gateways: Each gateway renders differently and may conflict with custom fields
  • Test guest and logged-in checkout: Some hooks behave differently for authenticated users
  • Test mobile devices: Custom fields must render correctly on small screens
  • Monitor after WooCommerce updates: Major updates can change hook behavior or add new fields

FAQ

What is the main hook for editing WooCommerce checkout fields?

The woocommerce_checkout_fields filter gives you access to all checkout fields (billing, shipping, order). You can add, remove, reorder, or modify any field through this single filter.

How do I save custom checkout field data?

Use the woocommerce_checkout_update_order_meta action hook. Access the posted data from $_POST, sanitize it, and save with update_post_meta() or the HPOS-compatible $order->update_meta_data().

Can I add validation to checkout without a plugin?

Yes. Hook into woocommerce_checkout_process and use wc_add_notice() with type error to block checkout when validation fails.

Will custom code break after WooCommerce updates?

Hooks and filters are stable across updates. Template overrides may need updating when WooCommerce changes the original template. Always test on staging after major WooCommerce updates.

Should I use hooks or template overrides?

Use hooks whenever possible. They are more maintainable and less likely to break on updates. Only override templates when you need to fundamentally change the checkout HTML structure.

How do I make checkout edits compatible with block checkout?

The block checkout uses a different rendering system. Legacy woocommerce_checkout_fields filters do not apply to block checkout. For block checkout customization, use WooCommerce's Checkout Block Extension API or the Store API filters. This is still evolving in 2026.

Conclusion

Editing WooCommerce checkout with code gives you precise control that plugins cannot match. Start with the woocommerce_checkout_fields filter for field management, use action hooks for injecting content, and add custom validation to enforce business rules.

Keep your code in a custom plugin, test thoroughly on staging, and ensure HPOS compatibility for future-proof implementations.

Related reading: Customize Checkout (No-Code Methods) | WooCommerce Custom Product Fields | WooCommerce Fashion Store Setup

Varun Dubey

Shaping Ideas into Digital Reality | Founder @wbcomdesigns | Custom solutions for membership sites, eLearning & communities | #WordPress #BuddyPress