WooCommerce Checkout Shortcode: How to Add and Customize It

WooCommerce Checkout Shortcode: How to Add and Customize It

If your checkout page is showing a blank screen, a broken layout, or nothing at all, the fix usually comes down to one shortcode and one setting most people forget to check. Here is exactly how the WooCommerce checkout shortcode works, where it goes, and how to customize the fields it renders.

The Code

To display the checkout form on any page, add this shortcode to the page content:

[woocommerce_checkout]

That’s the entire shortcode. No parameters, no attributes. It renders the full checkout process: billing fields, shipping fields, order review, and available payment gateways.

If you also need to customize which fields appear on that form, here is a snippet that removes the company field, makes the phone number required, and adds a custom “Delivery notes” field to billing:

add_filter( 'woocommerce_checkout_fields', 'fixelar_custom_checkout_fields' );

function fixelar_custom_checkout_fields( $fields ) {
    // Remove a field you don't need
    unset( $fields['billing']['billing_company'] );

    // Make phone required
    $fields['billing']['billing_phone']['required'] = true;

    // Add a custom field
    $fields['billing']['billing_delivery_notes'] = array(
        'type'        => 'textarea',
        'label'       => __( 'Delivery notes', 'woocommerce' ),
        'placeholder' => __( 'Gate code, preferred delivery time, etc.', 'woocommerce' ),
        'required'    => false,
        'class'       => array( 'form-row-wide' ),
        'priority'    => 120,
    );

    return $fields;
}

Where to Put This Code

The [woocommerce_checkout] shortcode goes directly in the content editor of the page you want to use as checkout, not in functions.php.

The PHP snippet is different. That one goes in your child theme’s functions.php, or in a snippets plugin like Code Snippets if you’d rather not touch theme files directly. Never add custom code to a parent theme’s functions.php. A single theme update will wipe it out, and you’ll spend an afternoon figuring out why your checkout suddenly reverted.

One setting trips up more stores than the shortcode itself: WooCommerce doesn’t scan your site looking for the checkout shortcode. It needs the page explicitly assigned as the checkout page under WooCommerce → Settings → Advanced → Page setup. Without that assignment, order processing, payment handling, and order emails won’t fire correctly, even if the shortcode is rendering fine on the front end.

Also worth noting: this filter only applies to the classic (shortcode-based) checkout. If your theme is running the block-based Checkout Block instead, field customization works through the Checkout Blocks API, not woocommerce_checkout_fields. Check which checkout your store is actually using before you spend time debugging a filter that isn’t being read.

How the Filter Works, Line by Line

add_filter( 'woocommerce_checkout_fields', 'fixelar_custom_checkout_fields' ); hooks your function into the array WooCommerce uses to build the checkout form.

The $fields array WooCommerce passes in is organized into groups: billing, shipping, account, and order. Every field you see on checkout lives inside one of those groups, addressed by its field key, for example billing_phone or billing_company.

unset( $fields['billing']['billing_company'] ); removes a field entirely by deleting its entry from the array.

$fields['billing']['billing_phone']['required'] = true; changes a property of an existing field without touching the rest of it. You can do the same with label, placeholder, or class.

Adding a new field means giving it a new key inside the group, plus a type, label, and priority. The priority number controls the order it appears in relative to other fields. Lower numbers show up first.

Real Use Cases

A checkout page that suddenly went blank after a redesign. This is almost always a missing shortcode or a page assignment that got reset when someone cloned a page or restored a backup. Re-adding [woocommerce_checkout] and reassigning the page under Advanced settings fixes it in under five minutes.

A store collecting a company field it never uses. B2C stores inherit a full B2B-style checkout by default. Removing fields like company name shortens the form, and shorter checkouts convert better.

A store that needs delivery instructions, a tax ID, or a gift message at checkout. Rather than installing a plugin for one extra field, adding it directly through the filter keeps the checkout lean and avoids one more dependency that could conflict with your payment gateway.

A store migrating from a page builder checkout back to native WooCommerce. If a builder plugin gets removed and checkout breaks, the shortcode approach is the fastest way back to a working, gateway-compatible checkout.

Common Issues

The shortcode shows nothing. Confirm the page is actually assigned as the checkout page in WooCommerce → Settings → Advanced. A shortcode sitting on the right-looking page with the wrong assignment renders empty.

The custom field isn’t saving to the order. Adding a field with woocommerce_checkout_fields displays it, but saving the value to order meta requires a separate action, woocommerce_checkout_update_order_meta. Skipping that step means the field shows up but the data disappears after checkout.

The filter runs but nothing changes. Check whether the store is on the Checkout Block instead of the classic shortcode checkout. The woocommerce_checkout_fields filter has no effect there.

Two plugins are fighting over the same field. If another plugin or your theme also hooks into woocommerce_checkout_fields, load order matters. Whichever runs last wins, so conflicting changes can look random until you check what else is hooked into that same filter.

If you’d rather not touch checkout code yourself, especially on a live store processing real orders, this is exactly the kind of work Fixelar handles as part of our WooCommerce custom development services. We build and test checkout changes on a clone of your store first, so nothing breaks on production.