Quantcast
Channel: Tutorial Archives - Kathy is Awesome
Viewing all articles
Browse latest Browse all 14

WooCommerce Customize Checkout Fields

$
0
0

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.


Viewing all articles
Browse latest Browse all 14

Trending Articles