How to Save CPT Data to the WooCommerce Order Based on a Custom Checkout Select Field
In the world of ecommerce, providing a seamless checkout experience is crucial for driving conversions and keeping customers satisfied. One way to enhance the checkout process is by offering customers the ability to select from a list of pre-defined addresses, often referred to as an "address book."
When a customer selects an address from the address book, it's important to save the corresponding data to the WooCommerce order for future reference and processing. In this blog post, we'll explore how to accomplish this using custom post types (CPTs) and a custom checkout select field.
Understanding the Problem
The original issue pointed out in the problem statement was that using the ACF (Advanced Custom Fields) function the_field()
to display the value of the custom checkout field would echo the value, rather than storing it in a variable or PHP code. This makes it difficult to save the data to the order.
Additionally, the problem statement mentioned that it's not possible to load all the data from the CPT into the <option>
elements of the custom checkout field. Instead, we need to choose a specific piece of data (such as the complete name) to display in the options.
The Solution
To address these challenges, we'll follow these steps:
- Add the Custom Checkout Field: We'll use the
woocommerce_checkout_fields
filter to add a custom select field to the checkout form, populated with options from the CPT.
- Validate the Custom Field: We'll use the
woocommerce_checkout_process
action to ensure the customer selects a value from the custom checkout field.
- Save the CPT Data to the Order: We'll use the
woocommerce_checkout_create_order
action to retrieve the selected CPT data and save it as custom order meta.
Let's dive into the code:
// Ad 'addressbook' custom checkout select field
add_filter('woocommerce_checkout_fields', 'add_address_book_checkout_field', 20, 1);
function add_address_book_checkout_field($fields)
{
if (!is_ssl()) return $fields; // if needed (?)
// Get 'addressbook' posts
$addressbook_posts = get_posts(array('post_type' => 'addressbook', 'posts_per_page' => -1));
// First option
$options = array('' => 'Please select something...');
// Loop through 'addressbook' posts (to set all other select options)
foreach ($addressbook_posts as $post) {
// Set each complete name as an option (Where key is the post ID)
$options[$post->ID] = get_field('fname', $post->ID) . ' ' . get_field('lname', $post->ID);
}
$fields['shipping']['address_book'] = array(
'type' => 'select',
'label' => __('Address Book', 'woocommerce'),
'placeholder' => _x('Pick an address', 'placeholder', 'woocommerce'),
'options' => $options, // Here we set the options
'required' => false,
'priority' => 1,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
// process custom checkout field
add_action('woocommerce_checkout_process', 'check_address_book_checkout_field', 20);
function check_address_book_checkout_field($order, $data)
{
if (isset($_POST['address_book']) && empty($_POST['address_book']))
wc_add_notice(__("Please pick an address from the Address Book"), 'error');
}
// Add custom meta data (or existing change data) to the order before saving it
add_action('woocommerce_checkout_create_order', 'set_meta_data_in_checkout_create_order', 20, 2);
function set_meta_data_in_checkout_create_order($order, $data)
{
if (isset($_POST['address_book'])) {
// The selected "Adress book" Post ID
$post_id = $_POST['address_book'];
// Get the data for the selected "Adress book" Post ID
$fname = get_field('fname', $post_id);
$lname = get_field('lname', $post_id);
$company = get_field('company', $post_id);
$addr1 = get_field('address_line_1', $post_id);
$addr2 = get_field('address_line_2', $post_id);
$city = get_field('city', $post_id);
$state = get_field('state', $post_id);
$zip = get_field('zip', $post_id);
// Set the meta data in the order
if (!empty($fname))
$order->update_meta_data('ab_fname', esc_attr($fname));
if (!empty($lname))
$order->update_meta_data('ab_lname', esc_attr($lname));
if (!empty($company))
$order->update_meta_data('ab_company', esc_attr($company));
if (!empty($addr1))
$order->update_meta_data('ab_addr1', esc_attr($addr1));
if (!empty($addr2))
$order->update_meta_data('ab_addr2', esc_attr($addr2));
if (!empty($city))
$order->update_meta_data('ab_city', esc_attr($city));
if (!empty($state))
$order->update_meta_data('ab_state', esc_attr($state));
if (!empty($zip))
$order->update_meta_data('ab_zip', esc_attr($zip));
}
}
Let's break down the code:
-
Adding the Custom Checkout Field: We use the woocommerce_checkout_fields
filter to add a new address_book
field to the shipping
section of the checkout form. We retrieve all the addressbook
posts (assuming this is the custom post type used for the address book), loop through them, and set the complete name (first and last name) as the option text, with the post ID as the option value.
-
Validating the Custom Field: We use the woocommerce_checkout_process
action to check if the address_book
field is empty. If it is, we add an error notice to the checkout process.
-
Saving the CPT Data to the Order: Finally, we use the woocommerce_checkout_create_order
action to retrieve the selected addressbook
post ID from the form submission. We then use the get_field()
function from ACF to retrieve the relevant data (first name, last name, company, address lines, city, state, and zip code) and save it as custom order meta using the update_meta_data()
method of the $order
object.
By following this approach, you can now save the custom post type data to the WooCommerce order based on the customer's selection in the custom checkout field. This information can be used for various purposes, such as pre-filling address fields, providing order history, or integrating with shipping providers.
Remember, this code should be placed in the functions.php
file of your active child theme (or active theme) for it to work correctly.
For more information on how Flowpoint.ai can help you identify and fix technical errors that are impacting your website's conversion rates, be sure to check out our website.