In WooCommerce, I want to add some custom fields on checkout which will be displayed under the billing section on the e-mail confirmation.
My custom fields and their values, shown on the checkout form and on the order page on back end (WooCommerce -> Orders). So far everything works great.
The problem is that the e-mail that i receive does not contain the custom fields and their values.
Code shown below:
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
function custom_override_checkout_fields( $fields ) {
$fields['billing']['billing_field_testing'] = array(
'label' => __('TestingField', 'woocommerce'),
'placeholder' => _x('TestingField', 'placeholder', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
add_action( 'woocommerce_admin_order_data_after_billing_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );
function my_custom_checkout_field_display_admin_order_meta($order)
{
echo '<p><strong>'.__('TestingField').':</strong> ' . get_post_meta( $order->id, '_billing_field_testing', true ) . '</p>';
}
Please help.
Thanks in advance
Updated: To display your custom checkout field in email notifications below the billing address, use this function hooked in woocommerce_email_customer_details action hook with a priority above 20:
add_action('woocommerce_email_customer_details','add_custom_checkout_field_to_emails_notifications', 25, 4 );
function add_custom_checkout_field_to_emails_notifications( $order, $sent_to_admin, $plain_text, $email ) {
$output = '';
$billing_field_testing = get_post_meta( $order->id, '_billing_field_testing', true );
if ( !empty($billing_field_testing) )
$output .= '<div><strong>' . __( "Some text:", "woocommerce" ) . '</strong> <span class="text">' . $billing_field_testing . '</span></div>';
echo $output;
}
The Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.
You will need to customize email templates under woocommerce/templates/emails/ to your-theme/woocommerce/emails/
Youc an override whatever template you want end add custom field there.
Alternatively, you can also add them using hook from following code:
add_filter( 'woocommerce_email_order_meta_fields', 'custom_woocommerce_email_order_meta_fields', 10, 3 );
function custom_woocommerce_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
$fields['meta_key'] = array(
'label' => __( 'Label' ),
'value' => get_post_meta( $order->id, 'meta_key', true ),
);
return $fields;
}
Related
Im looking to find some php code that will allow me to extract information (Name, address etc) from the checkout fields and add it to the order meta data.
Looking for this to be a simple as possible
Ive previously found this code which allows a custom box to be added to the checkout page, and I sort of understand how it works, however I want to capture their name when they type it into the billing first name box. I can seem to grasp how to capture this data and put it into the order meta data, Ive tried shortening the code and editing it a few times but I dont seem to be winning
// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {
$fields['shipping']['shipping_phone'] = array(
'label' => __('Phone', 'woocommerce'),
'placeholder' => _x('Phone', 'placeholder', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
/**
* Display field value on the order edit page
*/
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );
function my_custom_checkout_field_display_admin_order_meta($order){
echo '<p><strong>'.__('Phone From Checkout Form').':</strong> ' . get_post_meta( $order->get_id(), '_shipping_phone', true ) . '</p>';
}
/**
* Add the field to the checkout
*/
add_action( 'woocommerce_after_order_notes', 'my_custom_checkout_field' );
function my_custom_checkout_field( $checkout ) {
echo '<div id="my_custom_checkout_field"><h2>' . __('My Field') . '</h2>';
woocommerce_form_field( 'my_field_name', array(
'type' => 'text',
'class' => array('my-field-class form-row-wide'),
'label' => __('Fill in this field'),
'placeholder' => __('Enter something'),
), $checkout->get_value( 'my_field_name' ));
echo '</div>';
}
/**
* Process the checkout
*/
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_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' );
}
/**
* Update the order meta with field value
*/
add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta' );
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['my_field_name'] ) ) {
update_post_meta( $order_id, 'My Field', sanitize_text_field( $_POST['my_field_name'] ) );
}
}
I like this and it does work but just not in the way i need it to work. thanks for any and all help
There are some mistakes and missing things in your code… Try the following replacement code instead:
// Add shipping phone (in checkout and My account edit shipping address) and save field value
add_action( 'woocommerce_shipping_fields', 'add_shipping_phone_field' );
function add_shipping_phone_field( $fields ) {
$fields['shipping_phone'] = array(
'label' => __('Phone', 'woocommerce'),
'placeholder' => _x('Phone', 'placeholder', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
// Display shipping phone value on the order edit pages under shipping section
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'display_shipping_phone_in_admin_orders' );
function display_shipping_phone_in_admin_orders( $order ){
$phone_value = $order->get_meta('_shipping_phone');
if ( ! empty($phone_value) ) {
echo '<p><strong>'.__('Shipping phone').':</strong> ' . $phone_value . '</p>';
}
}
// Add a custom checkout field
add_action( 'woocommerce_after_order_notes', 'my_custom_checkout_field' );
function my_custom_checkout_field( $checkout ) {
echo '<div id="my_custom_checkout_field"><h2>' . __('My Field') . '</h2>';
woocommerce_form_field( 'my_field_slug', array(
'type' => 'text',
'class' => array('my-field-class form-row-wide'),
'label' => __('My custom field'),
'placeholder' => __('Enter something… '),
'required' => true,
), $checkout->get_value( 'my_field_slug' ) );
echo '</div>';
}
// Validate required checkout fields
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
// Check if set, if its not set add an error.
if ( isset($_POST['my_field_slug']) && empty($_POST['my_field_slug']) ) {
wc_add_notice( __( '"My custom field" is a required field.' ), 'error' );
}
}
// Add custom checkout field value as custom order meta data
add_action( 'woocommerce_checkout_create_order', 'my_custom_checkout_field_update_order_meta' );
function my_custom_checkout_field_update_order_meta( $order ) {
if ( isset($_POST['my_field_slug']) && ! empty($_POST['my_field_slug']) ) {
$order->update_meta_data( 'My Field', sanitize_text_field( $_POST['my_field_slug'] ) );
}
}
// Display "My field" value on the order edit pages under billing section
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_my_custom_checkout_field_in_admin_orders', 10, 1 );
function display_my_custom_checkout_field_in_admin_orders($order){
$my_field_value = $order->get_meta('My Field');
if ( ! empty($my_field_value) ) {
echo '<p><strong>'.__('My field').':</strong> ' . $my_field_value . '</p>';
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Now If you need to extract some data from Woocommerce existing checkout fields and combine it in a custom way to save it as custom order meta data, try to be more explicit:
What fields?
How you want to combine it?
What is the custom field slug to be used to save that data combination?
I foollow all he steps from this tutorial: https://docs.woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/
// Hook in
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {
$fields['shipping']['shipping_phone'] = array(
'label' => __('Phone', 'woocommerce'),
'placeholder' => _x('Phone', 'placeholder', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
/**
* Display field value on the order edit page
*/
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );
function my_custom_checkout_field_display_admin_order_meta($order){
echo '<p><strong>'.__('Phone From Checkout Form').':</strong> ' . get_post_meta( $order->get_id(), '_shipping_phone', true ) . '</p>';
}
And everything works fine, but... I want to show the value of the new field on the quickview from the order page, all the tutorials I find, only show how to show them on the detail page of the orders.
Thanks!
I found an action to show custom fields in the order preview box:
add_action( 'woocommerce_admin_order_preview_start', 'custom_display_order_data_in_admin' );
or:
add_action( 'woocommerce_admin_order_preview_end', 'custom_display_order_data_in_admin' );
But as you might noticed, these two actions will add custom fields either at the beginning or the end of it.
EDIT:
The whole code I've used in my custom plugin is this:
function custom_display_order_data_in_admin( $order ){ ?>
<div class="order_data_column">
<div class="address">
<?php
echo '<p><strong>' . __( 'billing cart' ) . ':</strong>' . get_post_meta( $order->id, '_billing_cart', true ) . '</p>';
?>
</div>
<div class="edit_address">
<?php woocommerce_wp_text_input( array( 'id' => '_billing_cart', 'label' => __( 'billing cart' ), 'wrapper_class' => '_billing_company_field' ) ); ?>
</div>
</div>
<?php }
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'custom_display_order_data_in_admin' );
add_action( 'woocommerce_admin_order_preview_end', 'custom_display_order_data_in_admin' );
You should just change the parameters as you used in you own code
I have the function in functions.php:
// Hook in
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {
$fields['billing']['billing_infos'] = array(
'type' => 'textarea',
'label' => __('Podaj NIP', 'woocommerce'),
'placeholder' => _x('Tutaj możesz wpisać NIP', 'placeholder', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
This code is adding custom field to billing form. It's working fine because I see it when I make an order like normal user. The problem is with data from this field in admin panel. I can't see it. Any help on this please?
This missing hooked function will display your custom fields in Order edit page, below Billing details:
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_billing_infos_to_admin_order_meta', 20, 1 );
function display_billing_infos_to_admin_order_meta( $order ){
echo '<p><strong>'.__('Podaj NIP').':</strong> ' . get_post_meta( $order->get_id(), '_billing_infos', true ) . '</p>';
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
I have a similar like in here: I don't understand why the value of this custom field is not saved. Here's my code:
add_filter( 'woocommerce_checkout_fields' , 'altri_campi' );
function altri_campi( $fields ) {
$fields['billing']['codice_fiscale'] = array(
'class' => array('form-row-wide'),
'label' => __('Codice Fiscale', 'woocommerce'),
'placeholder' => _x('Scrivere anche il Codice Fiscale', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array('form-row-wide')
);
return $fields;
}
// like LoizTheAztec above
add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta', 10, 1 );
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['codice_fiscale'] ) ) {
update_post_meta( $order_id, 'Codice Fiscale', sanitize_text_field( $_POST['codice_fiscale'] ) );
}
}
// then I'm expecting that custom field value will be saved somehow, but won't
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );
function my_custom_checkout_field_display_admin_order_meta($order){
echo '<p><strong>'.__('Codice Fiscale', 'woocommerce').':</strong> ' . get_post_meta( $order->get_id(), '_codice_fiscale', true ) . '</p>';
}
Meta field is correctly saved and printed, but I cannot add the custom field value in the order data view.
What I am doing wrong and how to display this custom field value in the Order edit view?
Otherwise the text I expect to find after Customer's billing and shipping data is void, since I read only the html part of the latest snippet.
Here is the correct commented and explained code:
// Creating and displaying the custom checkout field in checkout page
add_filter( 'woocommerce_checkout_fields' , 'altri_campi' );
function altri_campi( $fields ) {
$fields['billing']['codice_fiscale'] = array(
'class' => array('form-row-wide'),
'label' => __('Codice Fiscale', 'woocommerce'),
'placeholder' => _x('Scrivere anche il Codice Fiscale', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array('form-row-wide')
);
return $fields;
}
// Saving the custom checkout field value in the order meta data
add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta', 10, 1 );
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['codice_fiscale'] ) ){
update_post_meta( $order_id, 'codice_fiscale', sanitize_text_field( $_POST['codice_fiscale'] ) );
// get the customer ID
$customer_id = get_post_meta( $order_id, '_customer_user', true );
// Update customer user data
update_user_meta( $customer_id, 'codice_fiscale', true );
}
}
// Displaying the custom checkout field value in the order edit page (backend)
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'custom_checkout_field_display_admin_order_meta', 10, 1 );
function custom_checkout_field_display_admin_order_meta( $order ){
$codice_fiscale = get_post_meta( $order->get_id(), 'codice_fiscale', true );
if( ! empty( $codice_fiscale ))
echo '<p><strong>'.__('Codice Fiscale', 'woocommerce').':</strong> ' . $codice_fiscale . '</p>';
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works. You will get in backend order edit page something like (below addresses):
I'm adding WooCommerce custom checkout fields in a Storefront child theme functions.php file.
They have a "required" attribute.
The aim is to have these fields appear at the top of the page, before the billing fields.
when clicking the submit button to proceed to payment, I'm getting the required custom field validation error ('please fill in your name') and can't continue with payment, even though filling the field with valid data.
Any clue how to fix this or where to start debugging ?
here is the code in functions.php:
add_action( 'woocommerce_before_checkout_form', 'my_custom_checkout_fields' );
function my_custom_checkout_fields( $checkout ) {
echo '<div id="my_custom_checkout_field" class="col4-set"><h2>' . __('name') . '</h2>';
woocommerce_form_field( 'developer_name', array(
'type' => 'text',
'class' => array('developer_name-class form-row form-row-first'),
'label' => __('name'),
'placeholder' => __('fill in your name'),
'required' => true,
), $checkout->get_value( 'developer_name' ));
echo '</div>';
}
/**
* Process the checkout
*/
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['developer_name'] )
wc_add_notice( __( 'please fill in your name' ), 'error' );
}
I tried the following but none of them helped:
1. changing:
if ( ! $_POST['developer_name'] )
to
if ( empty( $_POST['developer_name']) )
2. changing the trigger from:
add_action( 'woocommerce_before_checkout_form', 'my_custom_checkout_fields' );
to
add_action( 'woocommerce_after_checkout_form', 'my_custom_checkout_fields' );
3. updating to latest Woocomerce 3.0.5 version
I'm running Wordpress 4.7.4
additional related active plugins:
Uni CPO - WooCommerce Options and Price Calculation Formulas
As you can read in woocommerce_before_checkout_form hook, it's before checkout form (so outside the checkout form). For this reason this custom field can't work in this hook.
You can use instead woocommerce_checkout_update_order_meta action hook, making some little changes in your code as there is no $checkout argument available in it.
This will display the field "at the top of the page, before the billing fields"…
So your complete code should be now:
/**
* Add the field to the checkout
*/
add_action( 'woocommerce_checkout_before_customer_details', 'my_custom_checkout_fields' );
function my_custom_checkout_fields() {
echo '<div id="my_custom_checkout_field" class="col4-set"><h2>' . __('name') . '</h2>';
woocommerce_form_field( 'developer_name', array(
'type' => 'text',
'class' => array('developer_name-class form-row form-row-first'),
'label' => __('name'),
'placeholder' => __('fill in your name'),
'required' => true,
), WC()->checkout->get_value( 'developer_name' ));
echo '</div>';
}
/**
* Process the checkout
*/
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['developer_name'] )
wc_add_notice( __( 'Please fill in your name.' ), 'error' );
}
// Update the order meta with field value
add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta', 10, 1 );
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['developer_name'] ) ) {
update_post_meta( $order_id, 'Developer name', sanitize_text_field( $_POST['developer_name'] ) );
}
}
// Display the custom-field in orders view
add_action( 'woocommerce_order_details_after_customer_details', 'display_my_custom_field_in_orde_details', 10, 1 );
function display_my_custom_field_in_orde_details( $order ) {
$developer_name = get_post_meta( $order->get_id(), 'Developer name', true );
if ( ! empty( $developer_name ) ):
?>
<table class="woocommerce-table woocommerce-table--customer-details shop_table customer_details">
<tbody><tr>
<th>Developer name:</th>
<td><?php echo $developer_name; ?></td>
</tr></tbody>
</table>
<?php
endif;
}
This code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works for WooCommerce version 3.0+
You try this code. Tested Ok
add_action( 'woocommerce_billing_fields', 'my_custom_checkout_fields' );
function my_custom_checkout_fields( $fields ) {
$fields['billing_developer_name'] = array(
'label' => __('Developer name', 'woocommerce'),
'placeholder' => _x('Developer name', 'placeholder', 'woocommerce'),
'required' => TRUE,
'clear' => false,
'type' => 'text',
'class' => array('my-css')
);
return $fields;
}
You can arrange it with this snippet
add_filter("woocommerce_checkout_fields", "order_fields");
function order_fields($fields) {
$order = array(
"billing_developer_name",
"billing_first_name",
"billing_last_name",
"billing_company",
"billing_address_1",
"billing_address_2",
"billing_postcode",
"billing_country",
"billing_email",
"billing_phone"
);
foreach($order as $field)
{
$ordered_fields[$field] = $fields["billing"][$field];
}
$fields["billing"] = $ordered_fields;
return $fields;
}
See screenshot
**/* If You Have Created Your Custom Field at the checkout page */**
add_action( 'woocommerce_after_checkout_validation', 'shipping_time_optionss', 9999, 2);
function shipping_time_optionss( $fields, $errors ){
// if any validation errors
if ( empty( $_POST['woo_shipping_time'] ) ) {
$errors->add( 'woocommerce_password_error', __( 'Please Select Shipping Time Option.' ) );
} `enter code here`
}