# EU VAT Number Field With Format Check

> Adds an optional VAT number field to the classic checkout, checks it matches the official format for the billing country, and saves it to the order and emails.

- Type: PHP
- Runs: Run everywhere
- Category: [WooCommerce](https://wpide.com/library/category/woocommerce/)
- Requires: WooCommerce
- Tags: woocommerce, vat, checkout, b2b
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/woo-vat-number-field/

## Code

```php
$wpide_vat_formats = array( // Country => pattern for the part after the country prefix.
    'AT' => 'U\d{8}', 'BE' => '[01]\d{9}', 'BG' => '\d{9,10}', 'CY' => '\d{8}[A-Z]', 'CZ' => '\d{8,10}',
    'DE' => '\d{9}', 'DK' => '\d{8}', 'EE' => '\d{9}', 'EL' => '\d{9}', 'ES' => '[A-Z0-9]\d{7}[A-Z0-9]',
    'FI' => '\d{8}', 'FR' => '[A-HJ-NP-Z0-9]{2}\d{9}', 'HR' => '\d{11}', 'HU' => '\d{8}', 'IE' => '\d{7}[A-W][A-I]?|\d[A-Z+*]\d{5}[A-W]',
    'IT' => '\d{11}', 'LT' => '\d{9}|\d{12}', 'LU' => '\d{8}', 'LV' => '\d{11}', 'MT' => '\d{8}', 'NL' => '\d{9}B\d{2}',
    'PL' => '\d{10}', 'PT' => '\d{9}', 'RO' => '\d{2,10}', 'SE' => '\d{12}', 'SI' => '\d{8}', 'SK' => '\d{10}', 'XI' => '\d{9}|\d{12}',
);

add_filter( 'woocommerce_billing_fields', function ( $fields ) {
    $fields['billing_vat_number'] = array(
        'type'     => 'text',
        'label'    => 'VAT number',
        'required' => false,
        'class'    => array( 'form-row-wide' ),
        'priority' => 35,
    );

    return $fields;
} );

add_action( 'woocommerce_after_checkout_validation', function ( $data, $errors ) use ( $wpide_vat_formats ) {
    $vat = strtoupper( preg_replace( '/[\s.\-]/', '', (string) ( $data['billing_vat_number'] ?? '' ) ) );

    if ( '' === $vat ) {
        return;
    }

    $country = (string) ( $data['billing_country'] ?? '' );
    $prefix  = 'GR' === $country ? 'EL' : $country;

    if ( ! isset( $wpide_vat_formats[ $prefix ] ) ) {
        return;
    }

    if ( 0 === strpos( $vat, $prefix ) ) {
        $vat = substr( $vat, strlen( $prefix ) );
    }

    if ( ! preg_match( '/^(' . $wpide_vat_formats[ $prefix ] . ')$/', $vat ) ) {
        $errors->add( 'validation', sprintf( 'The VAT number does not look like a valid %s VAT number. Please check it or leave the field empty.', esc_html( $prefix ) ) );
    }
}, 10, 2 );

add_filter( 'woocommerce_order_formatted_billing_address', function ( $address, $order ) {
    $vat = $order->get_meta( '_billing_vat_number' );

    if ( $vat ) {
        $address['company'] = trim( ( $address['company'] ?? '' ) . "\nVAT: " . $vat );
    }

    return $address;
}, 10, 2 );

add_action( 'woocommerce_admin_order_data_after_billing_address', function ( $order ) {
    $vat = $order->get_meta( '_billing_vat_number' );

    if ( $vat ) {
        printf( '<p><strong>VAT number:</strong> %s</p>', esc_html( $vat ) );
    }
} );
```

## Notes

Checks the number's format only (it does not contact VIES) and stores it as _billing_vat_number under the billing address.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "EU VAT Number Field With Format Check" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
