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.