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 data on checkout
// 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 to users
// 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 extra data in admin
// 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' );
Alternatively, display extra data as editable data (and save)
This should function like the shipping and billing address data and reveal inputs when the little pencil icon is clicked. Make sure to delete the previous function as two functions with the same name will cause a PHP error.
// 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' ); ?><a href="#" class="edit_address"><?php _e( 'Edit', 'woocommerce' ); ?></a></h4> <div class="address"> <?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> <div class="edit_address"> <?php woocommerce_wp_text_input( array( 'id' => '_some_field', 'label' => __( 'Some field' ), 'wrapper_class' => '_billing_company_field' ) ); ?> <?php woocommerce_wp_text_input( array( 'id' => '_another_field', 'label' => __( 'Another field' ), 'wrapper_class' => '_billing_company_field' ) ); ?> </div> </div> <?php } add_action( 'woocommerce_admin_order_data_after_order_details', 'kia_display_order_data_in_admin' ); function kia_save_extra_details( $post_id, $post ){ update_post_meta( $post_id, '_some_field', wc_clean( $_POST[ '_some_field' ] ) ); update_post_meta( $post_id, '_another_field', wc_clean( $_POST[ '_another_field' ] ) ); } add_action( 'woocommerce_process_shop_order_meta', 'kia_save_extra_details', 45, 2 );
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.3 and after, you will do it the following way:
// WooCommerce 2.3+ function kia_email_order_meta_fields( $fields, $sent_to_admin, $order ) { $fields['instagram'] = array( 'label' => __( 'Some field' ), 'value' => get_post_meta( $order->id, '_some_field', true ), ); $fields['licence'] = 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_fields', 10, 3 );
If you’d rather customize the output in the emails you can add some text to any of the hooks available in the email templates.
function kia_display_email_order_meta( $order, $sent_to_admin, $plain_text ) { $some_field = get_post_meta( $order->id, '_some_field', true ); $another_field = get_post_meta( $order->id, '_another_field', true ); if( $plain_text ){ echo 'The value for some field is ' . $some_field . ' while the value of another field is ' . $another_field; } else { echo '<p>The value for <strong>some field</strong> is ' . $some_field. ' while the value of <strong>another field</strong> is ' . $another_field . '</p>'; } } add_action('woocommerce_email_customer_details', 'kia_display_email_order_meta', 30, 3 );
Hope that helps you. I think there are a few plugins out there now if this was too intimidating, so I would suggest using one of those.
Note: This was tested with WooCommerce 2.2. Any prior or later versions, I can’t promise will be exactly the same.