Add a required checkbox field in WooCommerce checkout page

Here is how you can add a required checkbox field in the WooCommerce checkout page that forces a user to checkbox the request before they can proceed to payment, similar to the terms and condition checkbox.

Add Checkbox Woocommerce Checkout Page

WooCommerce Form Field

Add the code in your functions.php – the example uses the a new checkbox field named ‘checkout_checkbox

add_action( 'woocommerce_review_order_before_submit', 'bt_add_checkout_checkbox', 10 );
/**
 * Add WooCommerce additional Checkbox checkout field
 */
function bt_add_checkout_checkbox() {
   
    woocommerce_form_field( 'checkout_checkbox', array( // CSS ID
       'type'          => 'checkbox',
       'class'         => array('form-row mycheckbox'), // CSS Class
       'label_class'   => array('woocommerce-form__label woocommerce-form__label-for-checkbox checkbox'),
       'input_class'   => array('woocommerce-form__input woocommerce-form__input-checkbox input-checkbox'),
       'required'      => true, // Mandatory or Optional
       'label'         => 'Ok I agree with <a href="/checkout-checkbox" target="_blank" rel="noopener">Checkout Checkbox Page</a>', // Label and Link
    ));    
}

add_action( 'woocommerce_checkout_process', 'bt_add_checkout_checkbox_warning' );
/**
 * Alert if checkbox not checked
 */ 
function bt_add_checkout_checkbox_warning() {
    if ( ! (int) isset( $_POST['checkout_checkbox'] ) ) {
        wc_add_notice( __( 'Please acknowledge the Checkbox' ), 'error' );
    }
}

If you don’t want a warning and leave the checkbox as optional leave out the 2nd code block and change the required value in the 1st code block to false.

So change the CSS ID (checkout-checkbox)  to what you want, optional to add a secondary CSS Class and change your text Label and Link

CSS

.woocommerce-invalid #checkout-checkbox {
    outline: 2px solid red;
    outline-offset: 2px;
}

Add a bit of CSS to get the failed validation style of red box around the checkbox, use the same CSS ID.

So far the checkbox just displays on screen – see the 3 steps below to save that value to the database and display it on the backend and display it in emails.

 

Add Custom Field to Database as Order Meta

To add this field and value to the WordPress database

add_action( 'woocommerce_checkout_update_order_meta', 'bt_checkout_field_order_meta_db' );
/**
 * Add custom field as order meta with field value to database
 */
function bt_checkout_field_order_meta_db( $order_id ) {
    if ( ! empty( $_POST['checkout_checkbox'] ) ) {
        update_post_meta( $order_id, 'checkout_checkbox', sanitize_text_field( $_POST['checkout_checkbox'] ) );
    }
}

Retreive and display Custom Field to back end in WooCommerce Order Screen

To display the field and label in the backend WooCommerce order.

add_action( 'woocommerce_admin_order_data_after_billing_address', 'bt_checkout_field_display_admin_order_meta', 10, 1 );
/**
 * Display field value on the backend WooCOmmerce order
 */
function bt_checkout_field_display_admin_order_meta($order){
    echo '<p><strong>'.__('Checkout Checkbox Label').':</strong> ' . get_post_meta( $order->get_id(), 'checkout_checkbox', true ) . '<p>'; 
}

Add Custom Field to WooCommerce Emails

To display the field in emails:

add_filter('woocommerce_email_order_meta_keys', 'bt_custom_order_meta_email');

function bt_custom_order_meta_email( $keys ) {
     $keys[] = 'checkout_checkbox'; // This will look for a custom field called 'checkout_checkbox' and add it to WooCommerce emails
     return $keys;
}


The above code will drop the checkbox in as is, you may though want to use some arbitrary label and text instead, in which case you can use the woocommerce_email_order_meta_fields filter.

add_filter( 'woocommerce_email_order_meta_fields', 'bt_woocommerce_email_order_meta_fields', 10, 3 );
/**
 * Add a custom field (in an order) to the emails with text and label
 */

function bt_woocommerce_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
    
    $checkbox = get_post_meta( $order->get_id(), 'checkout_checkbox', true );
    
    if( $checkbox == 1 ) {
        $fields['checkout_checkbox'] = array(
            'label' => __( 'Member' ),
            'value' => __( 'Welcome Aboard' ),
        );
        return $fields;
    }
    else {
        $fields['checkout_checkbox'] = array(
            'label' => __( 'Member' ),
            'value' => __( 'See You Later' ),
        );
        return $fields;
    }
}

So we are assigning our custom field to a variable $checkbox and if that variable is checked (value of 1) it will output Member: Welcome Aboard if it is not checked it will output Member: See You Later

Ref