Collect extra customer details at checkout
I was digging around in WooCommerce while trying to come up with a quote for a client. Part of the scope had me wondering if you could remove some fields from the checkout process. If you aren’t selling physical products a billing address can be too much information and could even be off-putting to potential customers.
I eventually tracked the fields down from the checkout template, to the checkout class to the get_address_fields()
method in the WC_Countries
class.
Removing Billing Address
Like a lot of things in WooCommerce you can modify values via filter. To remove all the physical address fields from the billing address here is the code I used:
// Remove some checkout billing fields
function kia_filter_billing_fields($fields){
unset( $fields["billing_country"] );
unset( $fields["billing_company"] );
unset( $fields["billing_address_1"] );
unset( $fields["billing_address_2"] );
unset( $fields["billing_city"] );
unset( $fields["billing_state"] );
unset( $fields["billing_postcode"] );
unset( $fields["billing_phone"] );
return $fields;
}
add_filter( 'woocommerce_billing_fields', 'kia_filter_billing_fields' );
Yes this could go in functions.php
but that kind of locks you into a specific theme. If this is a permanent change then you probably want to create a site-specific plugin and put it in the wp-content/mu-plugins/
folder.
Add a Custom Checkout Field
While I was fooling around I figured I would see if I could add a custom checkout field. Turns out this is a bit more complex, but ultimately do-able. The following code will add the field to the checkout page, save the data to order meta and display the order meta in the orders admin.
Update: After receiving multiple contacts about adding more than one field I have modified the sample code to add 2 fields.
// Add a new checkout field
function kia_filter_checkout_fields($fields){
$fields['extra_fields'] = array(
'some_field' => array(
'type' => 'text',
'required' => true,
'label' => __( 'Some field' )
),
'another_field' => array(
'type' => 'select',
'options' => array( 'a' => __( 'apple' ),
'b' => __( 'bacon' ), 'c' => __( 'chocolate' ) ),
'required' => true,
'label' => __( 'Another field' )
)
);
return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'kia_filter_checkout_fields' );
// display the extra field on the checkout form
function kia_extra_checkout_fields(){
$checkout = WC()->checkout(); ?>
<div class="extra-fields">
<h3><?php _e( 'Additional Fields' ); ?></h3>
<?php
// because of this foreach, everything added to the array in the previous
function will display automagically
foreach ( $checkout->checkout_fields['extra_fields'] as $key => $field ) : ?>
<?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?>
<?php endforeach; ?>
</div>
<?php }
add_action( 'woocommerce_checkout_after_customer_details' ,
'kia_extra_checkout_fields' );
Note: there is no foreach()
in the rest of the function so we must save and
display each field individually
// save the extra field when checkout is processed
function kia_save_extra_checkout_fields( $order_id, $posted ){
// don't forget appropriate sanitization if you are using a different field type
if( isset( $posted['some_field'] ) ) {
update_post_meta( $order_id, '_some_field', sanitize_text_field( $posted['some_field'] ) );
}
if( isset( $posted['another_field'] ) && in_array( $posted['another_field'], array( 'a', 'b', 'c' ) ) ) {
update_post_meta( $order_id, '_another_field', $posted['another_field'] );
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'kia_save_extra_checkout_fields', 10, 2 );
// display the extra data on order recieved page and my-account order review
function kia_display_order_data( $order_id ){ ?>
<h2><?php _e( 'Additional Info' ); ?></h2>
<table class="shop_table shop_table_responsive additional_info">
<tbody>
<tr>
<th><?php _e( 'Some Field:' ); ?></th>
<td><?php echo get_post_meta( $order_id, '_some_field', true ); ?></td>
</tr>
<tr>
<th><?php _e( 'Another Field:' ); ?></th>
<td><?php echo get_post_meta( $order_id, '_another_field', true ); ?></td>
</tr>
</tbody>
</table>
<?php }
add_action( 'woocommerce_thankyou', 'kia_display_order_data', 20 );
add_action( 'woocommerce_view_order', 'kia_display_order_data', 20 );
// display the extra data in the order admin panel
function kia_display_order_data_in_admin( $order ){ ?>
<div class="order_data_column">
<h4><?php _e( 'Extra Details', 'woocommerce' ); ?></h4>
<?php
echo '<p><strong>' . __( 'Some field' ) . ':</strong>' . get_post_meta( $order->id, '_some_field', true ) . '</p>';
echo '<p><strong>' . __( 'Another field' ) . ':</strong>' . get_post_meta( $order->id, '_another_field', true ) . '</p>'; ?>
</div>
<?php }
add_action( 'woocommerce_admin_order_data_after_order_details', 'kia_display_order_data_in_admin' );
Add the field to order emails
The easiest way to add data to the emails is to add our meta to the list of meta that WooCommerce will print out automatically. For WooCommerce 2.2, this can be achieved as follows:
// pre-WooCommerce 2.3
function kia_email_order_meta_keys( $keys ) {
$keys['Some field'] = '_some_field';
$keys['Another field'] = '_another_field';
return $keys;
}
add_filter('woocommerce_email_order_meta_keys', 'kia_email_order_meta_keys');
But note, that this approach has been deprecated and starting with WooCommerce 2.3, you will do it the following way:
// WooCommerce 2.3+
function kia_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
$fields['some_field'] = array(
'label' => __( 'Some field' ),
'value' => get_post_meta( $order->id, '_some_field', true ),
);
$fields['another_field'] = array(
'label' => __( 'Another field' ),
'value' => get_post_meta( $order->id, '_another_field', true ),
);
return $fields;
}
add_filter('woocommerce_email_order_meta_fields', 'kia_email_order_meta_keys', 10, 3 );