WooCommerce Blocks Checkout: Adding Custom Fields with Slot Fills

WooCommerce Blocks ships a Checkout block that replaces the shortcode-based checkout. Customising it requires a different approach to adding fields — instead of PHP action hooks, you use the @woocommerce/blocks-checkout JavaScript package and its slot-fill system.

Problem: The classic WooCommerce checkout does not have a structured API for adding custom fields (delivery notes, VAT number, company name) — the standard approach using woocommerce_checkout_fields filter is not compatible with the WooCommerce Blocks checkout.

Solution: Implement IntegrationInterface from the WooCommerce Blocks package — register your integration with register_checkout_field() (WooCommerce 8.6+), define the field location (contact, address, or order), handle validation with the woocommerce_blocks_validate_location_*_fields action, and persist the value to order meta.

The examples below add a custom "Order Notes" field to the block checkout using the ExperimentalOrderMeta slot, save the value to order meta, and display it in the admin order page.

// checkout-fields.js — compiled and enqueued via block.json viewScript
import { __, sprintf } from '@wordpress/i18n';
import { TextareaControl } from '@wordpress/components';
import { useEffect, useState } from '@wordpress/element';
import {
    registerPlugin,
    extensionCartUpdate,
} from '@woocommerce/blocks-checkout';

// ExperimentalOrderMeta renders inside the Order Summary sidebar
const MyOrderNotes = () => {
    const [ notes, setNotes ] = useState( '' );

    useEffect( () => {
        // Sync value to the cart extensions data so the server can read it
        extensionCartUpdate( {
            namespace: 'myplugin-checkout',
            data: { order_notes: notes },
        } );
    }, [ notes ] );

    return (
        
    );
};

registerPlugin( 'myplugin-order-notes', {
    render: () => (
        
            
        
    ),
    scope: 'woocommerce-checkout',
} );

Register the server-side callback to persist the extension data to order meta:

 'myplugin-checkout',
        'callback'  => function( array $data ): void {
            $notes = sanitize_textarea_field( $data['order_notes'] ?? '' );
            WC()->session?->set( 'myplugin_order_notes', $notes );
        },
    ] );
} );

// Save notes from session to order meta when the order is placed
add_action( 'woocommerce_store_api_checkout_order_processed', function( WC_Order $order ) {
    $notes = WC()->session?->get( 'myplugin_order_notes', '' );
    if ( $notes ) {
        $order->update_meta_data( '_myplugin_order_notes', sanitize_textarea_field( $notes ) );
        $order->save();
    }
} );

// Display in admin order screen
add_action( 'woocommerce_admin_order_data_after_billing_address', function( WC_Order $order ) {
    $notes = $order->get_meta( '_myplugin_order_notes' );
    if ( $notes ) {
        echo '

' . esc_html__( 'Customer Notes:', 'myplugin' ) . '
' . esc_html( $notes ) . '

'; } } );

NOTE: The WooCommerce Blocks checkout uses ExperimentalOrderMeta, ExperimentalOrderLocalPickupPackages, and ExperimentalDiscountsMeta as slot-fill insertion points. The "Experimental" prefix indicates these APIs may change — track the WooCommerce Blocks extensibility docs for updates after WooCommerce 9.x.

Leave Comment

Your email address will not be published. Required fields are marked *