How to Add Additional Custom Fields into WooCommerce Checkout Page
Home » BLOG » WordPress » How to Add Additional Custom Fields to WooCommerce Checkout Page

How to Add Additional Custom Fields to WooCommerce Checkout Page

category:  WordPress

Woocommerce plugin is one of the most popular e-commerce plugins for WordPress. The core fields on the checkout page are very common. Most of the time, my clients ask for adding new fields and remove the core fields from the checkout page. Today I gonna share how to add new custom fields and remove the core fields from the checkout page.

Below is what we gonna do

  • create a new custom plugin
  • remove some core fields from the checkout page
  • add new custom fields to the checkout page
  • change the text label on the checkout page
  • add validation for new custom fields
  • add new custom fields on the order edit page at the backend
  • add new custom fields on the order received page (thank you page)
  • add new custom fields into the email notifications for the store site and clients

Create a new custom plugin

Optionally, you can add the snippet code into functions.php if you like but I prefer to add new custom fields via the plugin. So clients and I can disable it if we want without breaking the site.

  • Create the new folder calls woo-custom-fields under the plugins folder.
  • Then create a woo-custom-fields.php under woo-custom-fields folder. The woo-custom-fields.php is our main file for our new plugin.
  • Next, create a new folder calls classes. Later, we will create our class file and put it in this folder.
  • Now your new plugin folder will look at this
    • plugins/woo-custom-fields/woo-custom-fields.php
    • plugins/woo-custom-fields/classes/
woo-custom-fields.php

add the snippet code below into the woo-custom-fields.php file

/*
  Plugin Name: Add New Custom Fields into Checkout page
  Description: This plugin adds new custom fields into Checkout page for Woocommerce plugin
  Version: 1.0
  Author: <a  href="http://applerinquest.com" target="_BLANK">AppleRinquest</a>
  Text Domain: YOUR-TEXT-DOMAIN
  Domain Path: /languages/  
 */

// # declare the constant
// define('WOO_CUSTOMFIELDS_PLUGIN_PATH', dirname(__FILE__));  // this constant uses in the class files
// define('WOO_CUSTOMFIELDS_PLUGIN_URL', WP_PLUGIN_URL . '/woo-custom-fields/'); // this constant uses in enqueue file and style
// define('WOO_CUSTOMFIELDS_LANG_PATH', basename(dirname(__FILE__)));  // this constant uses for language

// our classes
require_once(dirname(__FILE__) . '/classes/class-woocommerce.php');

hint: If you want to use the path and URL of our new plugin in your class files, you can uncomment the constant declaration in the snippet code and use those constants in your class files.

Now the main file for our plugins is done. Next, we will add the snippet code to our classes folder.

Create class-woocommerce.php

Create the class-woocommerce.php under the classes folder. Then add the snippet code below to this file.

// If this file is called directly, abort.
if (!defined('ABSPATH')) die("No cheating!");

// Check the exists class before creating one
if (!class_exists('YOURCLASS_WooCommerce')) {

  class YOURCLASS_WooCommerce
  {
    /**
     * Start up
     */
    public function __construct()
    {
      // remove the core fields from Checkout page
      add_filter('woocommerce_checkout_fields', array($this, 'woo_override_checkout_fields'));

      // add new custom fields to Checkout page
      add_filter('woocommerce_checkout_fields', array($this, 'woo_add_checkout_fields'));

      // validate the new custom fields on Checkout page
      // add_action('woocommerce_checkout_process', array($this, 'woo_checkout_field_process'));

      // Update the order meta with field value - save new custom fields to order custom fields
      add_action('woocommerce_checkout_update_order_meta', array($this, 'woo_checkout_field_update_order_meta'));

      // Display field value on the order edit page
      add_action('woocommerce_admin_order_data_after_billing_address', array($this, 'woo_checkout_field_display_admin_order_meta'), 10, 1);

      // Display custom fields on order recieved page(thank you page) after customer detail section
      add_action('woocommerce_order_details_after_customer_details', array($this, 'woo_display_custom_fields_on_order_detail_page'));


      // # Email notification
      // Adding custom fields to emails
      add_filter('woocommerce_email_after_order_table', array($this, 'woo_email_custom_fields_detials'), 10, 4);
    }


    /**
     * Change the label text
     * using "gettext" filter will help you change the text from payment gatway and other button text without losing the text translation of them
     */
    function woo_custom_cart_button_text($translated_text, $text, $domain)
    {
      switch ($translated_text) {
        case 'Proceed to checkout': // on cart page at frontend
          $translated_text = __('Inquire booking', 'woocommerce');
          break;
        case 'Billing details':  // on checkout page at frontend
          $translated_text = __('Inquire Details', 'woocommerce');
          break;
        case 'Place order': 
          $translated_text = __('Inquire Booking', 'woocommerce');
          break;
        case 'Billing address': // on thank you page at frontend
          $translated_text = __('Inquire Details', 'woocommerce');
          break;
        case 'Billing':  // on order edit page at admin panel
          $translated_text = __('Inquire Details', 'woocommerce');
          break;
      }

      return $translated_text;
    }


    /**
     * Remove the core fields from Checkout page
     * note: $fields is passed via the filter
     */
    public function woo_override_checkout_fields($fields)
    {
      // remove core fields from Billing 
      unset($fields['billing']['billing_company']);
      unset($fields['billing']['billing_country']);
      unset($fields['billing']['billing_address_1']);
      unset($fields['billing']['billing_address_2']);
      unset($fields['billing']['billing_city']);
      unset($fields['billing']['billing_state']);
      unset($fields['billing']['billing_city']);
      unset($fields['billing']['billing_postcode']);

      // remove core fields from Shipping
      unset($fields['shipping']['billing_company']);
      unset($fields['shipping']['billing_country']);
      unset($fields['shipping']['billing_address_1']);
      unset($fields['shipping']['billing_address_2']);
      unset($fields['shipping']['billing_city']);
      unset($fields['shipping']['billing_state']);
      unset($fields['shipping']['billing_city']);
      unset($fields['shipping']['billing_postcode']);

      // Removes Order Notes Title - Additional Information & Notes Field
      add_filter('woocommerce_enable_order_notes_field', '__return_false', 9999);

      return $fields;
    }


    /**
     * Add new custom fields to Checkout page
     * note: $fields is passed via the filter!
     */
    public function woo_add_checkout_fields($fields)
    {
      $fields['billing']['billing_excursion_date'] = array(
        'type'      => 'date',
        'label'     => __('Excursion Date', 'woocommerce'),
        'required'  => true,
        'class'     => array('form-row-wide'),
        'clear'     => true,
        'priority' => 30
      );

      $fields['billing']['billing_time_session'] = array(
        'type'      => 'select',
        'label'     => __('Time Session', 'woocommerce'),
        'required'  => true,
        'class'     => array('form-row-wide'),
        'clear'     => true,
        'priority' => 40,
        'options' => array(
          '9:00am' => '9:00am',
          '12:00pm' => '12:00pm',
          '14:00pm' => '14:00pm'
        )
      );

      $fields['billing']['billing_hotel_name'] = array(
        'label'     => __('Hotel Name', 'woocommerce'),
        'placeholder'   => _x('Hotel Name', 'placeholder', 'woocommerce'),
        'required'  => true,
        'class'     => array('form-row-wide'),
        'clear'     => true,
        'priority' => 50
      );

      $fields['billing']['billing_hotel_room_no'] = array(
        'label'     => __('Hotel Room No.', 'woocommerce'),
        'placeholder'   => _x('Hotel Room No.', 'placeholder', 'woocommerce'),
        'required'  => true,
        'class'     => array('form-row-wide'),
        'clear'     => true,
        'priority' => 60
      );

      $fields['billing']['billing_email'] = array(
        'label'     => __('Email', 'woocommerce'),
        'placeholder'   => _x('Email', 'placeholder', 'woocommerce'),
        'required'  => true,
        'class'     => array('form-row-wide'),
        'clear'     => true,
        'priority' => 70
      );

      $fields['billing']['billing_phone'] = array(
        'label'     => __('Phone', 'woocommerce'),
        'placeholder'   => _x('Phone', 'placeholder', 'woocommerce'),
        'required'  => true,
        'class'     => array('form-row-wide'),
        'clear'     => true,
        'priority' => 80
      );

      $fields['billing']['billing_whatapp'] = array(
        'label'     => __('WhatApp', 'woocommerce'),
        'placeholder'   => _x('WhatApp', 'placeholder', 'woocommerce'),
        'required'  => true,
        'class'     => array('form-row-wide'),
        'clear'     => true,
        'priority' => 90
      );


      $fields['billing']['billing_special_inquire'] = array(
        'type'          => 'textarea',
        'label'     => __('Special Inquire', 'woocommerce'),
        'placeholder'   => _x('Special Inquire', 'placeholder', 'woocommerce'),
        'required'  => true,
        'class'     => array('form-row-wide'),
        'clear'     => true,
        'priority' => 100
      );

      return $fields;
    }


    /**
     * Add new custom fields to Order custom fields
     */
    public function woo_checkout_field_update_order_meta($order_id)
    {
      if (!empty($_POST['billing_excursion_date'])) {
        update_post_meta($order_id, 'billing_excursion_date', sanitize_text_field($_POST['billing_excursion_date']));
      }

      if (!empty($_POST['billing_time_session'])) {
        update_post_meta($order_id, 'billing_time_session', sanitize_text_field($_POST['billing_time_session']));
      }

      if (!empty($_POST['billing_hotel_name'])) {
        update_post_meta($order_id, 'billing_hotel_name', sanitize_text_field($_POST['billing_hotel_name']));
      }

      if (!empty($_POST['billing_hotel_room_no'])) {
        update_post_meta($order_id, 'billing_hotel_room_no', sanitize_text_field($_POST['billing_hotel_room_no']));
      }

      if (!empty($_POST['billing_whatapp'])) {
        update_post_meta($order_id, 'billing_whatapp', sanitize_text_field($_POST['billing_whatapp']));
      }

      if (!empty($_POST['billing_special_inquire'])) {
        update_post_meta($order_id, 'billing_special_inquire', sanitize_text_field($_POST['billing_special_inquire']));
      }
    }


    /**
     * Display field value on the order edit page - admin page
     */
    public function woo_checkout_field_display_admin_order_meta($order)
    {
      echo '<p><strong>' . __('Excursion Date') . ':</strong> ' . get_post_meta($order->id, 'billing_excursion_date', true) . '</p>';
      echo '<p><strong>' . __('Time Session') . ':</strong> ' . get_post_meta($order->id, 'billing_time_session', true) . '</p>';
      echo '<p><strong>' . __('Hotel Name') . ':</strong> ' . get_post_meta($order->id, 'billing_hotel_name', true) . '</p>';
      echo '<p><strong>' . __('Hotel Room No.') . ':</strong> ' . get_post_meta($order->id, 'billing_hotel_room_no', true) . '</p>';
      echo '<p><strong>' . __('WhatApp') . ':</strong> ' . get_post_meta($order->id, 'billing_whatapp', true) . '</p>';
      echo '<p><strong>' . __('Special Inquire') . ':</strong> ' . get_post_meta($order->id, 'billing_special_inquire', true) . '</p>';
    }


    /**
     * Adding custom fields to emails
     */
    public function woo_email_custom_fields_detials($order, $sent_to_admin, $plain_text, $email)
    {
      echo '<h2>' . __('Inquire Details') . '</h2>';
      echo '<p><strong>' . __('Name') . ':</strong> ' . $order->billing_first_name . '  ' . $order->billing_last_name . '</p>';
      echo '<p><strong>' . __('Phone') . ':</strong> ' . $order->billing_phone . '</p>';
      echo '<p><strong>' . __('Email') . ':</strong> ' . $order->billing_email . '</p>';

      echo '<p><strong>' . __('Excursion Date') . ':</strong> ' . get_post_meta($order->id, 'billing_excursion_date', true) . '</p>';
      echo '<p><strong>' . __('Time Session') . ':</strong> ' . get_post_meta($order->id, 'billing_time_session', true) . '</p>';
      echo '<p><strong>' . __('Hotel Name') . ':</strong> ' . get_post_meta($order->id, 'billing_hotel_name', true) . '</p>';
      echo '<p><strong>' . __('Hotel Roome No.') . ':</strong> ' . get_post_meta($order->id, 'billing_hotel_room_no', true) . '</p>';
      echo '<p><strong>' . __('WhatApp') . ':</strong> ' . get_post_meta($order->id, 'billing_whatapp', true) . '</p>';
      echo '<p><strong>' . __('Special Inquire') . ':</strong> ' . get_post_meta($order->id, 'billing_special_inquire', true) . '</p>';
      echo '<br><br>';
    }


    /**
     * Display custom fields on order detail page (order recieved page)     
     */
    public function woo_display_custom_fields_on_order_detail_page($order)
    {
      echo '<p><strong>' . __('Excursion Date') . ':</strong> ' . get_post_meta($order->id, 'billing_excursion_date', true) . '</p>';
      echo '<p><strong>' . __('Time Session') . ':</strong> ' . get_post_meta($order->id, 'billing_time_session', true) . '</p>';
      echo '<p><strong>' . __('Hotel Name') . ':</strong> ' . get_post_meta($order->id, 'billing_hotel_name', true) . '</p>';
      echo '<p><strong>' . __('Hotel Roome No.') . ':</strong> ' . get_post_meta($order->id, 'billing_hotel_room_no', true) . '</p>';
      echo '<p><strong>' . __('WhatApp') . ':</strong> ' . get_post_meta($order->id, 'billing_whatapp', true) . '</p>';
      echo '<p><strong>' . __('Special Inquire') . ':</strong> ' . get_post_meta($order->id, 'billing_special_inquire', true) . '</p>';
    }


/**
 * Process the checkout
 * validation on submit form
 * note: I add the sample code for validation for you here. Check the woocommerce_checkout_process hook for more detail. You can adjust as your need.
 */
add_action('woocommerce_checkout_process', 'woo_checkout_field_process');

function woo_checkout_field_process() {
    // Check if set, if its not set add an error.
    if ( ! $_POST['my_field_name'] )
        wc_add_notice( __( 'Please enter something into this new shiny field.' ), 'error' );
}

  } // class ends


  // initialize our class
  // DON'T FORGET TO ADD THIS CODE LINE otherwise, the snippet code won't work. 
  $YOURCLASS_WooCommerce = new YOURCLASS_WooCommerce;
}

Now your checkout page will look like this

Add custom fields to the email

Finally, we will add new custom fields to the email. As the last snippet code above, the new custom fields are already added to the email. But we need to override the email file in order to display only our new custom fields and remove the core fields that we don’t want.

Create the new folder calls woocommerce under your active theme folder. Then create new folder called emails. Finally, create a new email-addresses.php file. We create the new folder and files in order to override the default woocommerce template.

The folder structure now will look like this:

themes/your-active-theme/woocommerce/emails/email-addresses.php

Next, add the snippet code below into email-addresses.php

/**
 * Email Addresses
 *
 * overide from plugin/woocommerce/emails/email-addresses.php.
 *
 * @see https://docs.woocommerce.com/document/template-structure/
 * @package WooCommerce/Templates/Emails
 * @version 3.5.4
 */

if (!defined('ABSPATH')) {
  exit;
}

$text_align = is_rtl() ? 'right' : 'left';

When you place an order and see the thank you page, you will receive the email from the store and the email with new custom fields and override code in it will look like this.

And that’s it! This is a very simple code for customization. If you are looking for more advanced. You may want to check the useful links below.

WooCommerce Hooks: Actions and filters

Introduction to Hooks: a basic WordPress building block

Hook Reference

Customizing checkout fields using actions and filters

Hope this post will help you have an idea of how to customize the checkout page without any premium plugins.