Home / Blog / Customizing WooCommerce checkout: from hooks to Blocks, the modern take

Customizing WooCommerce checkout: from hooks to Blocks, the modern take

WooCommerce checkout customization is shifting from hooks to Block-based. Which approach makes sense in 2025?

With WooCommerce 8.x, checkout is fully Block-based. WordPress Gutenberg blocks run inside checkout. The old shortcode and action hooks are still around, but on a deprecation trajectory.

I have been building on WooCommerce for more than 15 years. The shift to Block-based checkout is a big one. Here is a comparison of the old and new approaches, and a pragmatic guide.

The old hook-based checkout

For years, checkout customization meant WooCommerce action and filter hooks.

Hook example: add a checkout field:

add_filter('woocommerce_checkout_fields', function($fields) {
    $fields['billing']['billing_company_tax_id'] = array(
        'label' => 'Tax ID',
        'required' => true,
        'class' => array('form-row-wide'),
    );
    return $fields;
});

Hook example: add validation:

add_action('woocommerce_checkout_process', function() {
    if (empty($_POST['billing_company_tax_id'])) {
        wc_add_notice('Tax ID is required.', 'error');
    }
});

Hook example: save the field on the order:

add_action('woocommerce_checkout_create_order', function($order, $data) {
    if (!empty($_POST['billing_company_tax_id'])) {
        $order->update_meta_data('billing_company_tax_id', sanitize_text_field($_POST['billing_company_tax_id']));
    }
}, 10, 2);

This pattern was standard through 2024. It only works with the classic checkout shortcode ([woocommerce_checkout]).

The new Block-based checkout

The WooCommerce Blocks plugin integrates with the WordPress 6.x Block editor. Checkout is now a Block on a WordPress page:

  • A woocommerce/checkout block.
  • Inside it, sub-blocks: shipping fields, payment methods, order review, etc.

Customization is different:

Adding a field:

// Using Store API extension

use AutomatticWooCommerceBlocksPackage;
use AutomatticWooCommerceBlocksDomainServicesExtendSchema;

add_action('woocommerce_blocks_loaded', function() {
    Package::container()->get(ExtendSchema::class)->register_endpoint_data([
        'endpoint' => AutomatticWooCommerceStoreApiSchemasV1CheckoutSchema::IDENTIFIER,
        'namespace' => 'my-plugin-namespace',
        'data_callback' => function() {
            return ['company_tax_id' => ''];
        },
        'schema_callback' => function() {
            return [
                'company_tax_id' => [
                    'description' => 'Tax ID',
                    'type' => 'string',
                ],
            ];
        },
    ]);
});

StoreAPI extension pattern. Stricter, type safe, React compatible.

JavaScript on the UI side:

import { registerCheckoutBlock } from '@woocommerce/blocks-checkout';

registerCheckoutBlock({
    metadata: {
        name: 'my-plugin/company-tax-id',
        parent: ['woocommerce/checkout-billing-address-block'],
    },
    component: ({ cart, extensions }) => {
        // Custom field component
        return <TextInput label="Tax ID" />;
    },
});

PHP and JavaScript combined. React component for UI, PHP Store API for data.

Which approach, when?

Hook-based (classic):

  • An existing site running the classic shortcode checkout.
  • You need a quick fix or customization.
  • The developer is not comfortable with React.

Block-based (modern):

  • New project, clean slate.
  • Block-based UI required (advanced layout).
  • Team at home in the React ecosystem.
  • Future proof strategy.

Right now (2025) WooCommerce 8+ defaults to Block-based. On a new project, Block-based is the way. Existing sites can stay on classic in the short term.

Hybrid scenario

Your existing site uses classic checkout, but the new feature wants Block-based. Migrating is a lot of work.

Option 1: stay on classic. If the requirement does not fit Block, solve it the classic way.

Option 2: migrate checkout to Block (during low-traffic hours, with staging testing), then do the Block customization.

Option 3: coexistence. Support both checkouts. A/B test with a feature flag.

I recommend option 2 to most clients. Move to Block. The migration is 1 to 2 weeks of work and it is the long-term strategic move.

Common customization scenarios

1. An extra billing field (tax ID, passport)

  • Classic: woocommerce_checkout_fields filter plus validation and save hooks.
  • Block: StoreAPI schema extension plus a React component.

Classic is around 30 lines of code, Block is 150+. Block is heavier but type safe and testable.

2. Changing the checkout flow (2-step, multi-page)

  • Classic: heavy hook customization plus template overrides.
  • Block: a custom Block variation, reorganize checkout parts.

Block is cleaner here. You design the layout in the visual editor.

3. Conditional logic (ask for tax ID for companies, not for individuals)

  • Classic: JavaScript conditional show/hide plus backend validation.
  • Block: conditional rendering in the React component’s state.

Block feels more natural (state management in React). But the setup cost is higher.

4. Third party integration (payment, shipping)

  • Classic: write a gateway or shipping method class.
  • Block: gateway plus a React PaymentMethod block.

Block lets you customize payment UI more. But it requires both PHP and JS implementation.

Block development stack

What you need for Block-based development:

  • @wordpress/scripts: build toolchain (webpack, Babel).
  • @woocommerce/blocks-checkout: WC-specific block utilities.
  • @wordpress/components: UI components.
  • React knowledge: component-based development.

npx @wordpress/create-block for boilerplate. Modern plugin structure.

Not like writing an old hook-based plugin. WordPress development discipline has changed.

Performance considerations

Classic checkout:

Server-side rendered, full page load. Minimal JavaScript. Fast first paint. Interactive time lags a bit.

Block-based checkout:

React app, hydration process. Big JavaScript bundle. Slightly slower first paint. Interactive immediately.

Net impact: Block checkout is 20 to 30% slower on first page load. But ongoing interaction (field validation, payment selection) is 50% faster.

Watch out for JavaScript-heavy Block checkout on mobile. Low-end devices see performance issues.

Migration strategy

Classic to Block migration:

Phase 1: audit. Which hooks are in use? What is the Block equivalent for each? Are any impossible to migrate?

Phase 2: staging test. Enable Block-based checkout on staging. Create test orders, end-to-end test. Verify payment gateways.

Phase 3: feature parity. Re-implement old hook functionality as the Block equivalent. Custom fields, validation, third party integrations.

Phase 4: A/B test (optional). Route 10% of traffic to Block checkout. Compare conversion rates. Catch issues.

Phase 5: switchover. Block checkout as the default. Keep classic as a backup for a while (a WooCommerce setting).

1 to 3 month project depending on complexity.

Known issues in Block-based

Block checkout is still maturing. Some pain points I have run into:

  1. Coupon UI is limited. Classic had a flexible coupon field, Block has it fixed.
  2. Custom validation errors are awkward. The hook-based validation pattern does not translate cleanly into Block.
  3. Payment gateway compatibility. Some older gateways still do not support Block checkout.
  4. Plugin ecosystem catching up. Popular add-ons are moving to Block-based, but not all.

This list shrinks with every WC release. By the end of 2025 moving to Block checkout is safer.

Theme compatibility

Block checkout works well with WP Block themes (Twenty Twenty-Three+). Classic themes can show visual glitches.

If you run Block checkout on a legacy theme site, watch your CSS overrides. Do not rely on WooCommerce default styles, write explicit styling.

Takeaway

WooCommerce checkout customization is heading toward a Block-based future. The hook-based pattern will be supported for another 2 to 3 years, but strategically moving to Block makes sense.

New project: Block-based by default. Existing project: a phased migration aligned to priorities. Do not forget the classic pattern, it still works on legacy systems.

React skills matter as much to a modern WordPress developer as they do to an iOS developer. The ecosystem is shifting, so adapt.

Have a project on this topic?

Leave a brief summary — I’ll get back to you within 24 hours.

Get in touch