Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

WooCommerce Custom Checkout Fields with Validation

By Kokil Thapa | Last reviewed: September 2026

Most store owners need more than the default billing and shipping boxes at checkout. WooCommerce Custom Checkout Fields with Validation lets you collect VAT numbers, delivery notes, gift messages, or Nepal-specific details like PAN without breaking the order flow. The work sits in theme or plugin code on WooCommerce eCommerce builds, not in page builders alone. This guide walks through field registration, server-side validation, sanitization, admin visibility, and the mistakes I see on production florist and grocery stores.

What Are WooCommerce Custom Checkout Fields and Why Do You Need Validation?

Checkout fields are an associative array grouped into billing, shipping, order, and custom sections. WooCommerce renders them from that array. You change labels, add inputs, or hide defaults through filters—not by editing core templates when a hook exists.

Validation matters because checkout is where money moves. A missing PAN on a B2B invoice, an invalid phone for SMS alerts, or a blank delivery slot breaks fulfilment. On stores like international WooCommerce florist projects, custom fields often carry date and message data that must be correct before payment.

Custom Checkout Field PipelineRegistercheckout_fieldsRendercheckout formValidatecheckout_processSaveorder metaServer-Side Rules RequiredNever trust browser-only checksSanitize before saveShow errors with wc_add_notice()Display saved values in admin + emails
WooCommerce custom checkout fields with validation follow a register → render → validate → save pipeline on every order.

Put logic in a custom plugin or child theme functions.php. Child themes work for single-store tweaks. Plugins survive theme switches—better for client handoffs on WordPress store maintenance.

How Do You Register Custom Checkout Fields in WooCommerce?

Use the woocommerce_checkout_fields filter. Each field needs a key, type, label, and priority. Place business-only fields in the order group or a custom section.

Minimal field registration example

Create wp-content/plugins/my-store-checkout-fields/my-store-checkout-fields.php:

<?php
/**
 * Plugin Name: My Store Checkout Fields
 * Requires Plugins: woocommerce
 * Requires at least: 7.1
 * WC requires at least: 11.1
 */

defined( 'ABSPATH' ) || exit;

add_filter( 'woocommerce_checkout_fields', 'mscf_add_checkout_fields' );

function mscf_add_checkout_fields( $fields ) {
    $fields['order']['billing_pan'] = [
        'type'        => 'text',
        'label'       => __( 'PAN / VAT Number', 'mscf' ),
        'placeholder' => __( '9-digit PAN', 'mscf' ),
        'required'    => false,
        'class'       => [ 'form-row-wide' ],
        'priority'    => 25,
        'custom_attributes' => [
            'maxlength' => '9',
            'pattern'   => '[0-9]{9}',
        ],
    ];

    $fields['order']['delivery_note'] = [
        'type'     => 'textarea',
        'label'    => __( 'Delivery instructions', 'mscf' ),
        'required' => true,
        'class'    => [ 'form-row-wide' ],
        'priority' => 30,
    ];

    return $fields;
}

The required flag adds HTML5 validation. WooCommerce also checks empties on required fields. Custom rules still need explicit PHP validation—covered next.

Field types and layout classes

  • text, email, tel, number, textarea, select, checkbox, radio — supported natively.
  • form-row-first / form-row-last — two columns on desktop.
  • form-row-wide — full width.
  • priority — controls order within the section; lower numbers appear first.

For Nepal NPR stores, pair custom fields with WooCommerce localization for NPR so labels and currency stay consistent.

How Do You Add Server-Side Validation to WooCommerce Checkout Fields?

Hook woocommerce_checkout_process. Read $_POST, validate, and call wc_add_notice() on failure. WooCommerce stops order creation when error notices exist.

Validation Decision FlowPOST submittedField empty and required?Yeswc_add_notice errorBlock checkoutNoFormat / regex checkPass or failCreate orderSave sanitized meta
Server-side validation for WooCommerce custom checkout fields blocks invalid POST data before order creation.
add_action( 'woocommerce_checkout_process', 'mscf_validate_checkout_fields' );

function mscf_validate_checkout_fields() {
    $pan = isset( $_POST['billing_pan'] )
        ? wp_unslash( $_POST['billing_pan'] )
        : '';

    if ( $pan !== '' && ! preg_match( '/^[0-9]{9}$/', $pan ) ) {
        wc_add_notice(
            __( 'PAN must be exactly 9 digits.', 'mscf' ),
            'error'
        );
    }

    $note = isset( $_POST['delivery_note'] )
        ? wp_unslash( $_POST['delivery_note'] )
        : '';

    if ( trim( $note ) === '' ) {
        wc_add_notice(
            __( 'Delivery instructions are required.', 'mscf' ),
            'error'
        );
    }

    if ( strlen( $note ) > 500 ) {
        wc_add_notice(
            __( 'Delivery note cannot exceed 500 characters.', 'mscf' ),
            'error'
        );
    }
}

Test regex patterns in a regex tester before deploying. Match Nepal PAN rules to your accountant's spec—not every store needs PAN at checkout.

Sanitize posted data before save

Filter woocommerce_checkout_posted_data to normalize values early:

add_filter( 'woocommerce_checkout_posted_data', 'mscf_sanitize_posted_data' );

function mscf_sanitize_posted_data( $data ) {
    if ( isset( $data['billing_pan'] ) ) {
        $data['billing_pan'] = sanitize_text_field( $data['billing_pan'] );
    }
    if ( isset( $data['delivery_note'] ) ) {
        $data['delivery_note'] = sanitize_textarea_field( $data['delivery_note'] );
    }
    return $data;
}

WordPress sanitization functions strip unsafe input. See the WordPress sanitization handbook for field-type mapping.

Where Should Custom Checkout Field Logic Live—Theme, Plugin, or ACF?

Three common approaches exist. Pick based on maintainability, not speed alone.

ApproachBest forValidation controlRisk on theme change
Custom pluginClient stores, multi-site reuseFull PHP hooksLow
Child theme functions.phpSingle-store tweaksFull PHP hooksMedium—lost if parent theme breaks
ACF / field UI pluginsNon-dev content teamsLimited unless extendedDepends on plugin

For pure checkout fields, code beats UI plugins. ACF shines on product or page meta—not checkout POST handling. Read ACF vs custom fields comparison for context. On agency builds I default to a small dedicated plugin named after the store.

How Do You Save and Display Custom Checkout Fields on Orders and Emails?

After validation, persist values as order meta. Then surface them in admin, emails, and optionally the REST API.

Save to order meta

add_action(
    'woocommerce_checkout_update_order_meta',
    'mscf_save_checkout_fields',
    10,
    2
);

function mscf_save_checkout_fields( $order_id, $data ) {
    if ( ! empty( $data['billing_pan'] ) ) {
        update_post_meta(
            $order_id,
            '_billing_pan',
            sanitize_text_field( $data['billing_pan'] )
        );
    }
    if ( ! empty( $data['delivery_note'] ) ) {
        update_post_meta(
            $order_id,
            '_delivery_note',
            sanitize_textarea_field( $data['delivery_note'] )
        );
    }
}

WooCommerce 11.x still uses post meta for orders on many installs. HPOS (High-Performance Order Storage) uses WC_Order->update_meta_data() instead—check your store setting under WooCommerce → Settings → Advanced → Features.

Show fields in admin order screen

add_action(
    'woocommerce_admin_order_data_after_billing_address',
    'mscf_display_admin_order_fields',
    10,
    1
);

function mscf_display_admin_order_fields( $order ) {
    $pan = $order->get_meta( '_billing_pan' );
    if ( $pan ) {
        echo '<p><strong>' . esc_html__( 'PAN:', 'mscf' ) . '</strong> '
            . esc_html( $pan ) . '</p>';
    }
    $note = $order->get_meta( '_delivery_note' );
    if ( $note ) {
        echo '<p><strong>' . esc_html__( 'Delivery note:', 'mscf' )
            . '</strong> ' . esc_html( $note ) . '</p>';
    }
}

Include the same values in transactional emails via woocommerce_email_order_meta_fields. Fulfilment teams on WooCommerce florist stores rely on email copies when admin access is limited.

Common Validation MistakesWrongJS-only validationNo sanitize stepInvalid orders slip throughCorrectPHP checkout_processSanitize posted dataBlock bad orders earlyProduction RuleNever create orders with bad dataValidate before payment captureTest with empty and malformed POST
WooCommerce custom checkout fields with validation fail in production when teams skip server-side checks and sanitization.

How Do You Conditionally Show or Require Checkout Fields?

Business rules often depend on cart contents, shipping zone, or user role. Use woocommerce_checkout_fields with cart inspection—not JavaScript toggles alone.

add_filter( 'woocommerce_checkout_fields', 'mscf_conditional_pan_field' );

function mscf_conditional_pan_field( $fields ) {
    $needs_pan = false;

    foreach ( WC()->cart->get_cart() as $item ) {
        $product = $item['data'];
        if ( $product && $product->is_taxable() ) {
            $needs_pan = true;
            break;
        }
    }

    if ( isset( $fields['order']['billing_pan'] ) ) {
        $fields['order']['billing_pan']['required'] = $needs_pan;
        if ( ! $needs_pan ) {
            unset( $fields['order']['billing_pan'] );
        }
    }

    return $fields;
}

Mirror the same rule in woocommerce_checkout_process. Mismatched UI and validation confuses buyers and support staff.

Block checkout for specific shipping methods

Local pickup might need a phone number. Express delivery might need a time slot. Read WC()->session->get('chosen_shipping_methods') inside both the filter and the validation hook.

For payment-specific rules, see WooCommerce custom payment gateway development. Gateway callbacks and checkout fields should agree on required data.

What Advanced Patterns Work for WooCommerce 11.1 in 2026?

Modern stores need more than static text boxes. These patterns appear on production builds I maintain.

  1. Nonce-safe AJAX validation — validate PAN or coupon eligibility before submit using wp_ajax_ handlers with nonces. Improves UX; still keep server validation on submit.
  2. Block checkout compatibility — Block-based checkout uses different extension points. Classic checkout hooks above remain standard for most custom stores on WooCommerce 11.1.
  3. HPOS-safe meta — Use $order->update_meta_data() and $order->save() when custom order tables are enabled.
  4. REST exposure — Mobile apps reading orders need meta registered for the REST API. See WooCommerce REST API for mobile apps.
  5. Export and reporting — Prefix meta keys with _ for internal fields; document keys for CSV export plugins.
Key WooCommerce Hookswoocommerce_checkout_fieldsRegister and modify fieldscheckout_posted_dataSanitize posted valueswoocommerce_checkout_processValidate before order createcheckout_update_order_metaPersist to order metaadmin_order_data_after_billingShow in admin order screenemail_order_meta_fieldsInclude in order emailsHook order matches checkout request lifecycle
Primary hooks for WooCommerce custom checkout fields with validation, sanitization, persistence, and display.

HPOS-compatible save snippet

add_action( 'woocommerce_checkout_create_order', 'mscf_hpos_save_fields', 10, 2 );

function mscf_hpos_save_fields( $order, $data ) {
    if ( ! empty( $data['billing_pan'] ) ) {
        $order->update_meta_data(
            '_billing_pan',
            sanitize_text_field( $data['billing_pan'] )
        );
    }
    if ( ! empty( $data['delivery_note'] ) ) {
        $order->update_meta_data(
            '_delivery_note',
            sanitize_textarea_field( $data['delivery_note'] )
        );
    }
}

Official reference: the WooCommerce customise checkout fields documentation covers core field keys. Cross-check hook names against the WooCommerce hooks code reference when upgrading major versions.

Testing checklist before go-live

  • Submit with all fields empty—confirm required errors appear.
  • Submit malformed PAN, phone, or email—confirm regex messages.
  • Complete a valid order—confirm admin and email display.
  • Test logged-in and guest checkout.
  • Test with caching and page-speed plugins enabled.
  • Re-test after WooCommerce or WordPress updates on staging first.

Run through testing and optimization before peak season. Dashain order spikes expose weak validation fast on Nepal stores.

Compare platform trade-offs in Magento vs Shopify vs WooCommerce if checkout complexity pushes you toward another stack. Shopify's model differs—see Shopify checkout extensions for custom fields.

On multi-vendor builds, vendor-specific fields need namespace prefixes to avoid meta collisions. Read WooCommerce multi-vendor marketplace setup before adding global checkout fields.

For order workflow after checkout, tie fields into custom order notifications and refund workflows so ops teams see the same data everywhere.

I've shipped similar patterns on Laravel and WooCommerce grocery stores where delivery zones and notes drive fulfilment. The principle is identical: collect once, validate server-side, display everywhere downstream.

Bulk catalog work stays separate—use CSV product import for SKUs, not checkout fields. Keep checkout code in its own plugin for clean ongoing maintenance.

Key Takeaways

  • Register fields with woocommerce_checkout_fields; never edit WooCommerce core templates.
  • Validate on woocommerce_checkout_process—HTML5 required alone is insufficient.
  • Sanitize via woocommerce_checkout_posted_data before values reach order meta.
  • Save with order meta APIs compatible with HPOS when custom tables are enabled.
  • Display the same values in admin, emails, and exports so fulfilment teams stay aligned.
  • Package logic in a dedicated plugin so theme changes do not wipe custom checkout rules.

People Also Ask

Can I add custom checkout fields without a plugin?

Yes. Add code to your child theme's functions.php using the same hooks. A small custom plugin is safer for client handoffs because it survives theme updates and keeps checkout logic isolated from design changes.

Does WooCommerce validate custom fields automatically?

Only basic checks apply—mainly the required flag and type hints like email. Format rules, cross-field logic, and business constraints need custom PHP in woocommerce_checkout_process.

Will custom checkout fields work with WooCommerce Blocks checkout?

Classic hook-based fields target the traditional shortcode checkout. Block checkout uses the Cart and Checkout blocks with different extension APIs. Confirm which checkout your theme renders before deploying custom field code.

How do I show custom checkout field values on the thank-you page?

Hook woocommerce_thankyou or woocommerce_order_details_after_order_table. Read order meta with $order->get_meta() and output escaped values so customers see what was captured.

Ship Checkout Fields That Survive Production Traffic

WooCommerce Custom Checkout Fields with Validation is straightforward when you follow the hook chain: register, sanitize, validate, save, display. Skipping server-side validation is the mistake that creates refund calls and manual order fixes. Start with one required field, test guest and logged-in flows, then expand. Need checkout fields built for a Nepal or international store on WooCommerce 11.1? Contact us or review our WooCommerce portfolio work to see how custom checkout data feeds real fulfilment workflows.

Frequently Asked Questions

They are extra inputs added to the checkout form—billing, shipping, order, or custom sections—beyond WooCommerce defaults. Stores use them for VAT numbers, delivery notes, gift messages, or Nepal-specific PAN data before payment completes.

Use the woocommerce_checkout_fields filter. Each field needs a key, type, label, and priority. Place business-only fields in the order group or a custom section. Set required, class arrays like form-row-wide, and custom_attributes such as maxlength or pattern. WooCommerce renders the form from that associative array—do not edit core templates when this hook exists. Put the code in a dedicated plugin or child theme functions.php.

HTML5 required flags and WooCommerce’s basic empty checks are not enough for format rules, length limits, or business logic. Checkout is where money moves—a bad PAN, phone, or delivery slot breaks fulfilment and creates refund calls. Hook woocommerce_checkout_process, read posted data, and call wc_add_notice() on failure. WooCommerce stops order creation when error notices exist. Client-side JavaScript alone cannot protect production stores.

Hook woocommerce_checkout_process. Inside your callback, read values from the posted checkout form, run your regex or business rules, and call wc_add_notice() with type error when validation fails. WooCommerce blocks order creation if any error notices exist. Mirror conditional UI rules here too—if a field is required only for certain cart contents or shipping methods, enforce the same logic in this hook, not only in woocommerce_checkout_fields.

After validation, persist values as order meta. On classic setups, hook woocommerce_checkout_update_order_meta and call update_post_meta with prefixed keys like _billing_pan. When High-Performance Order Storage is enabled under WooCommerce Settings → Advanced → Features, use woocommerce_checkout_create_order and $order->update_meta_data() followed by $order->save(). Prefix internal keys with underscore and document them for exports.

Yes. Add the same hooks to your child theme functions.php. A small custom plugin is safer for client handoffs because it survives theme updates.

Only basic checks—mainly the required flag and native type hints like email. Custom format rules need woocommerce_checkout_process.

For pure checkout fields, code beats UI plugins. A custom plugin gives full PHP hook control and low risk on theme change—best for client stores and multi-site reuse. Child theme functions.php works for single-store tweaks but logic can be lost if the parent theme breaks. ACF suits product or page meta, not checkout POST handling, unless heavily extended. On agency builds, a small dedicated plugin named after the store is the maintainable default.

Filter woocommerce_checkout_posted_data to normalize values before they reach order meta. Map field types to WordPress sanitizers: sanitize_text_field for text inputs like PAN, sanitize_textarea_field for delivery notes. This strips unsafe input early in the pipeline. Sanitization complements validation—it does not replace server-side checks in woocommerce_checkout_process. Both steps belong in the register, sanitize, validate, save chain on every order.

Classic hook-based fields target traditional shortcode checkout. Block-based checkout uses Cart and Checkout blocks with different extension APIs. Confirm which checkout your theme renders before deploying custom field code. Most custom stores on WooCommerce 11.1 still rely on classic hooks. If your storefront uses blocks, the registration and validation patterns in this guide will not apply without block-specific extensions.

Save values to order meta first, then surface them downstream. In admin, hook woocommerce_admin_order_data_after_billing_address and read $order->get_meta() with escaped output. For transactional emails, use woocommerce_email_order_meta_fields so fulfilment teams see PAN, delivery notes, or gift messages when admin access is limited. Keep the same meta keys across admin, emails, and exports so ops teams stay aligned on every order.

Inspect the cart inside woocommerce_checkout_fields—set required true, unset the field, or hide it based on product tax status, shipping zone, or user role. For shipping-method rules, read WC()->session->get('chosen_shipping_methods') inside both the filter and validation hook. Never rely on JavaScript toggles alone. Mirror every UI rule in woocommerce_checkout_process. Mismatched display and validation confuses buyers and creates support tickets on production florist and grocery stores.

Hook woocommerce_thankyou or woocommerce_order_details_after_order_table. Read saved order meta with $order->get_meta() and output escaped values so customers confirm what was captured before payment completed.

Native types include text, email, tel, number, textarea, select, checkbox, and radio. Layout classes control presentation: form-row-first and form-row-last create two columns on desktop, form-row-wide spans full width. The priority integer controls order within a section—lower numbers appear first. Combine type, class, and priority with custom_attributes like maxlength and pattern for HTML5 hints, but still add PHP validation for anything business-critical.

Submit with all fields empty and confirm required errors appear. Submit malformed PAN, phone, or email and verify regex messages. Complete a valid order and check admin display and email copies. Test logged-in and guest checkout. Re-test with caching and page-speed plugins enabled. Run everything on staging after WooCommerce or WordPress updates before peak season—Dashain order spikes on Nepal stores expose weak validation fast when server-side checks or sanitization were skipped.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: