Skip to content

Instantly share code, notes, and snippets.

@maddisondesigns
Last active February 7, 2024 13:42
Show Gist options
  • Save maddisondesigns/e7ee7eef7588bbba2f6d024a11e8875a to your computer and use it in GitHub Desktop.
Save maddisondesigns/e7ee7eef7588bbba2f6d024a11e8875a to your computer and use it in GitHub Desktop.
WooCommerce Custom Fields for Simple & Variable Products
/*
* Add our Custom Fields to simple products
*/
function mytheme_woo_add_custom_fields() {
global $woocommerce, $post;
echo '<div class="options_group">';
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_text_field',
'label' => __( 'My Text Field', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => true,
'description' => __( "Here's some really helpful tooltip text.", "woocommerce" )
)
);
// Number Field
woocommerce_wp_text_input(
array(
'id' => '_number_field',
'label' => __( 'My Number Field', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => false,
'description' => __( "Here's some really helpful text that appears next to the field.", 'woocommerce' ),
'type' => 'number',
'custom_attributes' => array(
'step' => 'any',
'min' => '0'
)
)
);
// Textarea
woocommerce_wp_textarea_input(
array(
'id' => '_textarea',
'label' => __( 'My Textarea', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => true,
'description' => __( "Here's some really helpful tooltip text.", "woocommerce" )
)
);
// Select
woocommerce_wp_select(
array(
'id' => '_select',
'label' => __( 'My Select Field', 'woocommerce' ),
'options' => array(
'one' => __( 'Option 1', 'woocommerce' ),
'two' => __( 'Option 2', 'woocommerce' ),
'three' => __( 'Option 3', 'woocommerce' )
)
)
);
// Checkbox
woocommerce_wp_checkbox(
array(
'id' => '_checkbox',
'wrapper_class' => 'show_if_simple',
'label' => __('My Checkbox Field', 'woocommerce' ),
'description' => __( 'Check me!', 'woocommerce' )
)
);
// Hidden field
woocommerce_wp_hidden_input(
array(
'id' => '_hidden_field',
'value' => 'hidden_value'
)
);
// Custom field Type
?>
<p class="form-field custom_field_type">
<label for="custom_field_type"><?php echo __( 'Custom Field Type', 'woocommerce' ); ?></label>
<span class="wrap">
<?php $custom_field_type = get_post_meta( $post->ID, '_custom_field_type', true ); ?>
<input placeholder="<?php _e( 'Field One', 'woocommerce' ); ?>" class="" type="number" name="_field_one" value="<?php echo $custom_field_type[0]; ?>" step="any" min="0" style="width: 100px;" />
<input placeholder="<?php _e( 'Field Two', 'woocommerce' ); ?>" type="number" name="_field_two" value="<?php echo $custom_field_type[1]; ?>" step="any" min="0" style="width: 100px;" />
</span>
<span class="description"><?php _e( 'Place your own description here!', 'woocommerce' ); ?></span>
</p>
<?php
echo '</div>';
}
// General Tab
//add_action( 'woocommerce_product_options_pricing', 'mytheme_woo_add_custom_fields' ); // After pricing fields
//add_action( 'woocommerce_product_options_downloads', 'mytheme_woo_add_custom_fields' ); // After downloadable file fields and only visible when it's a downloable product
//add_action( 'woocommerce_product_options_tax', 'mytheme_woo_add_custom_fields' ); // After tax fields
add_action( 'woocommerce_product_options_general_product_data', 'mytheme_woo_add_custom_fields' ); // After all General default fields
// Inventory tab
//add_action( 'woocommerce_product_options_sku', 'mytheme_woo_add_custom_fields' ); // After SKU field
//add_action( 'woocommerce_product_options_stock', 'mytheme_woo_add_custom_fields' ); // After Manage Stock field
//add_action( 'woocommerce_product_options_stock_fields', 'mytheme_woo_add_custom_fields' ); // After Manage Stock field but only visible is checked
//add_action( 'woocommerce_product_options_stock_status', 'mytheme_woo_add_custom_fields' ); // After Stock Status field
//add_action( 'woocommerce_product_options_sold_individually', 'mytheme_woo_add_custom_fields' ); // After Sold Individually field
//add_action( 'woocommerce_product_options_inventory_product_data', 'mytheme_woo_add_custom_fields' ); // After all Inventory default fields
// Shipping tab
//add_action( 'woocommerce_product_options_dimensions', 'mytheme_woo_add_custom_fields' ); // After Dimensions field
//add_action( 'woocommerce_product_options_shipping', 'mytheme_woo_add_custom_fields' ); // After all Shipping default fields
// Linked Products tab
//add_action( 'woocommerce_product_options_related', 'mytheme_woo_add_custom_fields' ); // After all Linked Products default fields
// Attributes tab
//add_action( 'woocommerce_product_options_attributes', 'mytheme_woo_add_custom_fields' ); // After all Attributes default fields
// Advanced tab
//add_action( 'woocommerce_product_options_reviews', 'mytheme_woo_add_custom_fields' ); // After Enable Reviews field
//add_action( 'woocommerce_product_options_advanced', 'mytheme_woo_add_custom_fields' ); // After all Advanced default fields
/*
* Save our simple product fields
*/
function mytheme_woo_add_custom_fields_save( $post_id ){
// Text Field
$woocommerce_text_field = $_POST['_text_field'];
update_post_meta( $post_id, '_text_field', esc_attr( $woocommerce_text_field ) );
// Number Field
$woocommerce_number_field = $_POST['_number_field'];
update_post_meta( $post_id, '_number_field', esc_attr( $woocommerce_number_field ) );
// Textarea
$woocommerce_textarea = $_POST['_textarea'];
update_post_meta( $post_id, '_textarea', esc_html( $woocommerce_textarea ) );
// Select
$woocommerce_select = $_POST['_select'];
update_post_meta( $post_id, '_select', esc_attr( $woocommerce_select ) );
// Checkbox
$woocommerce_checkbox = isset( $_POST['_checkbox'] ) ? 'yes' : 'no';
update_post_meta( $post_id, '_checkbox', $woocommerce_checkbox );
// Hidden Field
$woocommerce_hidden_field = $_POST['_hidden_field'];
update_post_meta( $post_id, '_hidden_field', esc_attr( $woocommerce_hidden_field ) );
// Custom Field
$custom_field_type = array( esc_attr( $_POST['_field_one'] ), esc_attr( $_POST['_field_two'] ) );
update_post_meta( $post_id, '_custom_field_type', $custom_field_type );
}
add_action( 'woocommerce_process_product_meta', 'mytheme_woo_add_custom_fields_save' );
/*
* Add our Custom Fields to variable products
*/
function mytheme_woo_add_custom_variation_fields( $loop, $variation_data, $variation ) {
echo '<div class="options_group form-row form-row-full">';
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_variable_text_field[' . $variation->ID . ']',
'label' => __( 'My Text Field', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => true,
'description' => __( "Here's some really helpful tooltip text.", "woocommerce" ),
'value' => get_post_meta( $variation->ID, '_variable_text_field', true )
)
);
// Add extra custom fields here as necessary...
echo '</div>';
}
// Variations tab
//add_action( 'woocommerce_variation_options', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After variation Enabled/Downloadable/Virtual/Manage Stock checkboxes
//add_action( 'woocommerce_variation_options_pricing', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Price fields
//add_action( 'woocommerce_variation_options_inventory', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Manage Stock fields
//add_action( 'woocommerce_variation_options_dimensions', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Weight/Dimension fields
//add_action( 'woocommerce_variation_options_tax', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Shipping/Tax Class fields
//add_action( 'woocommerce_variation_options_download', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Download fields
add_action( 'woocommerce_product_after_variable_attributes', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After all Variation fields
/*
* Save our variable product fields
*/
function mytheme_woo_add_custom_variation_fields_save( $post_id ){
// Text Field
$woocommerce_text_field = $_POST['_variable_text_field'][ $post_id ];
update_post_meta( $post_id, '_variable_text_field', esc_attr( $woocommerce_text_field ) );
}
add_action( 'woocommerce_save_product_variation', 'mytheme_woo_add_custom_variation_fields_save', 10, 2 );
/*
* Display our example custom field above the summary on the Single Product Page
*/
function mytheme_display_woo_custom_fields() {
global $post;
$ourTextField = get_post_meta( $post->ID, '_text_field', true );
if ( !empty( $ourTextField ) ) {
echo '<div>Our Text Field: ' . $ourTextField . '</div>';
}
}
add_action( 'woocommerce_single_product_summary', 'mytheme_display_woo_custom_fields', 15 );
@luigiventu
Copy link

Hello, I would need a little help!

I have a similar scenario but with custom input text fields that the customer is supposed to type in (sucha as name, date and other free text)

So far I am able to:

  • declare the custom attributes
  • show them in the product variation form
  • validate them
  • pass them to the cart item and display them in the cart page
  • change the product price according to certain attribute values (e.g. text length)

What I cannot do:

  • pass them (the attributes) throught the checkout into the order, so that
    • they can be displayed in the checkout page
    • but most importantly they are received on the backend in the wocommerce/"orders" tab and showed along other variations attributes of the product (I need them for customizing the product with the text the customer typed in)

I would like to understand if this is feasible or not, or if maybe I am getting something wrong about the wocommerce flow.

when you shop, all product objects are added to the cart. I was expecting something similar on the checkout: like copying these product objects from the cart and create the "order" object.
Does it work like that? Are there some filter and hooks (frontend and backend) to access/modify this object (if it exists)?

I am not finding much documentation about it so any kind of help is appreciated.

Thank you.

@eskruolis
Copy link

This is by far best explanation i found on this topic. Legend.

@adam-jones-net
Copy link

This is a great reference but it doesn't seem to cover one thing that is vital I feel... searching and including these custom fields in the standard wordpress search results. I've been trying to get up to date code that works on current WP for this but so far no luck.

@maddisondesigns
Copy link
Author

This is a great reference but it doesn't seem to cover one thing that is vital I feel... searching and including these custom fields in the standard wordpress search results. I've been trying to get up to date code that works on current WP for this but so far no luck.

@Arkid Thanks for the kind words. If you'd like to include your custom fields in the standard WP search, then I recommend installing Relevanssi. It's a free plugin on dot org. It allows you to include comments, tags, categories and custom fields within your searches.

@adam-jones-net
Copy link

@maddisondesigns good idea but it doesn't work with woocommerce properly, causing the search template used by woocommerce to be ignored. So this and similar plugins I've tested aren't any good for me hence wanting to do it manually myself with a minimal hook

@Anas-Nagati
Copy link

Awesome reference, but I'm facing a weird issue and tried another website I have and it always happens I can't add more than two custom fields. when I add three or more the product data tab acts weird and you can't edit any thing. any help?

@shmaltz
Copy link

shmaltz commented Jan 31, 2020

Quick question: I need to add a custom field to regular and variable products. Can I use the same field name for both?

@maddisondesigns
Copy link
Author

Quick question: I need to add a custom field to regular and variable products. Can I use the same field name for both?

@shmaltz The fields are similar but you'll notice if you look at the code above, the ID for the custom field in the Variable Product is specified slightly different. Depending where it's placed, the surrounding div might also be slightly different. On top of that, the hooks for saving the field are different as well.

@shmaltz
Copy link

shmaltz commented Feb 3, 2020 via email

@maddisondesigns
Copy link
Author

@shmaltz That probably depends on your import plugin. Using the standard WooCommerce import, I've been able to import data into custom fields that I've created, that have the same name, but different product types (i.e. Simple Products and Variable Products). So yeah, it is possible.

@shmaltz
Copy link

shmaltz commented Feb 3, 2020 via email

@nguyenhuy517
Copy link

Thanks!

@costidima
Copy link

Hi! Is there any way to validate the fields before saving them?

@maddisondesigns
Copy link
Author

Hi! Is there any way to validate the fields before saving them?

@costidima You can sanitize the data before you save it, but I've never found a way that allows you properly validate the data, before saving. This is something that has frustrated me as well, so if you find out how to do it, I'd love to know.

@niladri-raychaudhuri
Copy link

niladri-raychaudhuri commented Dec 24, 2020

Hi,

First, I want to thank you for this tutorial.
Using your tutorial I am trying to add a background color to the individual product cards in a woocommerce app.
I need to get the selected color on change of selection to display a color visual cue as below:

Screenshot 2020-12-24 at 2 39 59 PM

I am getting the value on hitting update, but not on selection change.
$bgcolor = get_post_meta( get_the_ID(), 'product_bg', true );
Any suggestions?
A code snippet will help me.

@eartisan-uk
Copy link

Thanks! Really appreciate it.

@boutzamat
Copy link

Crazy how much code must be written to add an extra field to a product. Especially because single and variation has their own hooks instead of a parameter to choose which product type it should be added to.

Thanks for this helpful snippet!

@oracle1979
Copy link

Hello,
first of all many thanks for this code which helps me a lot with my woocommerce installation.

However, i would like to have one "custom text field" which is displayed for single as well as variable products like the "regular price". My custom field name is "discount".

With the code above i can created two different fields with the same name. If i use the same field name for the single and variable field i get the replay "Array". How can i solve it?

Many thanks

@maddisondesigns
Copy link
Author

maddisondesigns commented Aug 27, 2021

Hello,
first of all many thanks for this code which helps me a lot with my woocommerce installation.

However, i would like to have one "custom text field" which is displayed for single as well as variable products like the "regular price". My custom field name is "discount".

With the code above i can created two different fields with the same name. If i use the same field name for the single and variable field i get the replay "Array". How can i solve it?

Many thanks

@oracle1979 You can create two custom text fields that have the same label (e.g. Product discount), but they need to have different ID's. You can't have two fields with the same ID. A custom field for a simple product is different to a custom field for a variable product.

@oracle1979
Copy link

Hello,
first of all many thanks for this code which helps me a lot with my woocommerce installation.
However, i would like to have one "custom text field" which is displayed for single as well as variable products like the "regular price". My custom field name is "discount".
With the code above i can created two different fields with the same name. If i use the same field name for the single and variable field i get the replay "Array". How can i solve it?
Many thanks

@oracle1979 You can create two custom text fields that have the same label (e.g. Product discount), but they need to have different ID's. You can't have two fields with the same ID. A custom field for a simple product is different to a custom field for a variable product.

@maddisondesigns Ok, I thought it works like the existing woocommerce fields like regualr price.
If i export the exiting field "regular price" for all products it will be shown in excel as one column and i can maintain the values for single as well as variable field prices in one column and import it again.

Currently i have two columns with the same name and i have to maintain both price columns. But it´s also ok. Thank you

@oracle1979
Copy link

Hello,
with the code below i can display a custom field on the product page which is great.

function lieferart_display_woo_custom_fields() {
global $post;

$ourTextField = get_post_meta( $post->ID, '_text_lieferart', true );

if ( !empty( $ourTextField ) ) {
	echo '<div>Lieferart: ' . $ourTextField . '</div>';
}

}
add_action( 'woocommerce_single_product_summary', 'lieferart_display_woo_custom_fields', 15 );

How can i display an exisitng woocommerce field for example "shipping class" on the product page?

Thanks

@maddisondesigns
Copy link
Author

maddisondesigns commented Aug 27, 2021

How can i display an exisitng woocommerce field for example "shipping class" on the product page?

@oracle1979 This stackoverflow answer should help you.

Depending on where you want to display it, you should familiarise yourself with all various WooCommerce Hooks and Filters.

@chris-paganon
Copy link

chris-paganon commented Nov 26, 2021

Hello,
first of all many thanks for this code which helps me a lot with my woocommerce installation.
However, i would like to have one "custom text field" which is displayed for single as well as variable products like the "regular price". My custom field name is "discount".
With the code above i can created two different fields with the same name. If i use the same field name for the single and variable field i get the replay "Array". How can i solve it?
Many thanks

@oracle1979 You can create two custom text fields that have the same label (e.g. Product discount), but they need to have different ID's. You can't have two fields with the same ID. A custom field for a simple product is different to a custom field for a variable product.

@maddisondesigns Ok, I thought it works like the existing woocommerce fields like regualr price. If i export the exiting field "regular price" for all products it will be shown in excel as one column and i can maintain the values for single as well as variable field prices in one column and import it again.

Currently i have two columns with the same name and i have to maintain both price columns. But it´s also ok. Thank you

@oracle1979 So actually you can have two fields with the same ID in the database, they just can't have the same ID on the product data page. So all you have to do is use the same ID in update_post_meta in the mytheme_woo_add_custom_variation_fields_save function.

So update_post_meta( $post_id, '_variable_text_field', esc_attr( $woocommerce_text_field ) ) would become update_post_meta( $post_id, '_text_field', esc_attr( $woocommerce_text_field ) ) and everything else stays the same.

@Yorlinq
Copy link

Yorlinq commented Aug 10, 2022

Seriously....

You're a genius!

Many many tnx for this code.

For those who're interested in adding EAN codes to products.... The code below adds a EAN number field right below the SKU (for simple products only) or a EAN number field for each variation (for variable products only).

/*

  • Add our Custom Fields to simple products
    */
    function yl_woo_add_custom_fields() {

    global $woocommerce, $product, $post;

    $product = wc_get_product( get_the_id() );

    if ($product->is_type( 'simple' )) {

     echo '<div class="options_group">';
    
     // Number Field
     woocommerce_wp_text_input(
     	array(
     		'id'                => '_ean_code',
     		'label'             => __( 'EAN code', 'yorlinq' ),
     		'placeholder'       => '',
     		'desc_tip'    		=> true,
     		'description'       => __( "Enter the official EAN code.", 'yorlinq' ),
     		'type'              => 'number',
     		'custom_attributes' => array(
     				'step' 	=> 'any',
     				'min'	=> '0'
     			)
     	)
     );
    
     echo '</div>';
    

    }

}
// General Tab
//add_action( 'woocommerce_product_options_pricing', 'yl_woo_add_custom_fields' ); // After pricing fields
//add_action( 'woocommerce_product_options_downloads', 'yl_woo_add_custom_fields' ); // After downloadable file fields and only visible when it's a downloable product
//add_action( 'woocommerce_product_options_tax', 'yl_woo_add_custom_fields' ); // After tax fields
//add_action( 'woocommerce_product_options_general_product_data', 'yl_woo_add_custom_fields' ); // After all General default fields

// Inventory tab
add_action( 'woocommerce_product_options_sku', 'yl_woo_add_custom_fields' ); // After SKU field
//add_action( 'woocommerce_product_options_stock', 'yl_woo_add_custom_fields' ); // After Manage Stock field
//add_action( 'woocommerce_product_options_stock_fields', 'yl_woo_add_custom_fields' ); // After Manage Stock field but only visible is checked
//add_action( 'woocommerce_product_options_stock_status', 'yl_woo_add_custom_fields' ); // After Stock Status field
//add_action( 'woocommerce_product_options_sold_individually', 'yl_woo_add_custom_fields' ); // After Sold Individually field
//add_action( 'woocommerce_product_options_inventory_product_data', 'yl_woo_add_custom_fields' ); // After all Inventory default fields

// Shipping tab
//add_action( 'woocommerce_product_options_dimensions', 'yl_woo_add_custom_fields' ); // After Dimensions field
//add_action( 'woocommerce_product_options_shipping', 'yl_woo_add_custom_fields' ); // After all Shipping default fields

// Linked Products tab
//add_action( 'woocommerce_product_options_related', 'yl_woo_add_custom_fields' ); // After all Linked Products default fields

// Attributes tab
//add_action( 'woocommerce_product_options_attributes', 'yl_woo_add_custom_fields' ); // After all Attributes default fields

// Advanced tab
//add_action( 'woocommerce_product_options_reviews', 'yl_woo_add_custom_fields' ); // After Enable Reviews field
//add_action( 'woocommerce_product_options_advanced', 'yl_woo_add_custom_fields' ); // After all Advanced default fields

/*

  • Save our simple product fields
    */
    function yl_woo_add_custom_fields_save( $post_id ){

    global $product;

    $product = wc_get_product( get_the_id() );

    if ($product->is_type('simple')) {
    // Number Field
    $woocommerce_ean_code = $_POST['_ean_code'];
    update_post_meta( $post_id, '_ean_code', esc_attr( $woocommerce_ean_code ) );
    }

}
add_action( 'woocommerce_process_product_meta', 'yl_woo_add_custom_fields_save' );

/*

  • Add our Custom Fields to variable products
    */
    function yl_woo_add_custom_variation_fields( $loop, $variation_data, $variation ) {

    echo '

    ';

    // Text Field
    woocommerce_wp_text_input(
    array(
    'id' => '_variable_ean_code[' . $variation->ID . ']',
    'label' => __( 'EAN code', 'yorlinq' ),
    'placeholder' => '',
    'desc_tip' => true,
    'description' => __( "Enter the official EAN code, for each product variation individually.", "yorlinq" ),
    'type' => 'number',
    'value' => get_post_meta( $variation->ID, '_variable_ean_code', true )
    )
    );

    // Add extra custom fields here as necessary...

    echo '

    ';

}
// Variations tab
add_action( 'woocommerce_variation_options', 'yl_woo_add_custom_variation_fields', 10, 3 ); // After variation Enabled/Downloadable/Virtual/Manage Stock checkboxes
//add_action( 'woocommerce_variation_options_pricing', 'yl_woo_add_custom_variation_fields', 10, 3 ); // After Price fields
//add_action( 'woocommerce_variation_options_inventory', 'yl_woo_add_custom_variation_fields', 10, 3 ); // After Manage Stock fields
//add_action( 'woocommerce_variation_options_dimensions', 'yl_woo_add_custom_variation_fields', 10, 3 ); // After Weight/Dimension fields
//add_action( 'woocommerce_variation_options_tax', 'yl_woo_add_custom_variation_fields', 10, 3 ); // After Shipping/Tax Class fields
//add_action( 'woocommerce_variation_options_download', 'yl_woo_add_custom_variation_fields', 10, 3 ); // After Download fields
//add_action( 'woocommerce_product_after_variable_attributes', 'yl_woo_add_custom_variation_fields', 10, 3 ); // After all Variation fields

/*

  • Save our variable product fields
    */
    function yl_woo_add_custom_variation_fields_save( $post_id ){

    // Text Field
    $woocommerce_variable_ean_code = $_POST['_variable_ean_code'][ $post_id ];
    update_post_meta( $post_id, '_variable_ean_code', esc_attr( $woocommerce_variable_ean_code ) );

}
add_action( 'woocommerce_save_product_variation', 'yl_woo_add_custom_variation_fields_save', 10, 2 );

@maddisondesigns
Copy link
Author

@Yorlinq Thanks for the kind words. Glad you found it useful 🙂

@Yorlinq
Copy link

Yorlinq commented Sep 5, 2022

@maddisondesigns Me again, but this time with a question:

How can I populate a custom select field with all categories? I know how to add a custom select field and how to populate it with custom options but how can I dynamically populate it with all categories?

Thanks so much (again) for this Wonderfull code.

Hope to hear from you (or anyone else with the answer) soon :)

@maddisondesigns
Copy link
Author

@Yorlinq You can use the get_categories() function to get a list of all Categories. You'd then simply loop through them and add each one to your select field. There's examples at the bottom of the page, in the User Contributed Notes, that show you how you can loop through them.

See: https://developer.wordpress.org/reference/functions/get_categories/

@Yorlinq
Copy link

Yorlinq commented Sep 7, 2022

Oke, I got all categories visible in a select field but when I update, nothing gets saved.....?

/*

  • Add our Custom Field to all products
    */
    function yl_woo_add_main_category_field( $post_id ) {

    echo '

    ';

    // Get product categories
    $terms = get_terms( array('taxonomy' => 'product_cat') );
    $options = []; // Initializing

    // Loop through each wp_term object and set term names in an array
    foreach ($terms as $term) {
    $term_name = __( $term->name, 'woocommerce' );
    $options[$term_name] = $term_name;
    }

    // Select
    woocommerce_wp_select( array(
    'id' => '_main_category',
    'label' => __( 'Main category', 'yorlinq' ),
    'placeholder' => '',
    'desc_tip' => true,
    'description' => __( 'Select a category to display above the product title on shop page.', 'yorlinq' ),
    'options' => $options,
    'value' => get_post_meta( $post_id, '_main_category', true ),
    ) );

    echo '

    ';

}
// General Tab
//add_action( 'woocommerce_product_options_pricing', 'yl_woo_add_main_category_field' ); // After pricing fields
//add_action( 'woocommerce_product_options_downloads', 'yl_woo_add_main_category_field' ); // After downloadable file fields and only visible when it's a downloable product
//add_action( 'woocommerce_product_options_tax', 'yl_woo_add_main_category_field' ); // After tax fields
add_action( 'woocommerce_product_options_general_product_data', 'yl_woo_add_main_category_field', 2 ); // After all General default fields

// Inventory tab
//add_action( 'woocommerce_product_options_sku', 'yl_woo_add_main_category_field' ); // After SKU field
//add_action( 'woocommerce_product_options_stock', 'yl_woo_add_main_category_field' ); // After Manage Stock field
//add_action( 'woocommerce_product_options_stock_fields', 'yl_woo_add_main_category_field' ); // After Manage Stock field but only visible is checked
//add_action( 'woocommerce_product_options_stock_status', 'yl_woo_add_main_category_field' ); // After Stock Status field
//add_action( 'woocommerce_product_options_sold_individually', 'yl_woo_add_main_category_field' ); // After Sold Individually field
//add_action( 'woocommerce_product_options_inventory_product_data', 'yl_woo_add_main_category_field' ); // After all Inventory default fields

// Shipping tab
//add_action( 'woocommerce_product_options_dimensions', 'yl_woo_add_main_category_field' ); // After Dimensions field
//add_action( 'woocommerce_product_options_shipping', 'yl_woo_add_main_category_field' ); // After all Shipping default fields

// Linked Products tab
//add_action( 'woocommerce_product_options_related', 'yl_woo_add_main_category_field' ); // After all Linked Products default fields

// Attributes tab
//add_action( 'woocommerce_product_options_attributes', 'yl_woo_add_main_category_field' ); // After all Attributes default fields

// Advanced tab
//add_action( 'woocommerce_product_options_reviews', 'yl_woo_add_main_category_field' ); // After Enable Reviews field
//add_action( 'woocommerce_product_options_advanced', 'yl_woo_add_main_category_field' ); // After all Advanced default fields

/*

  • Save our simple product fields
    */
    function yl_woo_add_main_category_field_save( $post_id ){

    // Select
    $woocommerce_select = $_POST['_main_category'];
    update_post_meta( $post_id, '_main_category', esc_attr( $woocommerce_select ) );

}
add_action( 'woocommerce_process_product_meta', 'yl_woo_add_main_category_field_save' );

@Yorlinq
Copy link

Yorlinq commented Sep 7, 2022

just had to remove 1 line: 'value' => get_post_meta( $post_id, '_main_category', true ),

And now it works :)

@dulanga91
Copy link

dulanga91 commented Nov 9, 2022

@maddisondesigns Hi Thank you very much for your code, it's beneficial to understand how to add custom fields for WC, and Thank you again.
Actually, I need to get variable data to display on single product page like this
/*

  • Add our Custom Fields to variable products
    */
    function mytheme_woo_add_custom_variation_fields( $loop, $variation_data, $variation ) {

    echo '

    ';

    // Text Field
    woocommerce_wp_text_input(
    array(
    'id' => '_variable_text_field[' . $variation->ID . ']',
    'label' => __( 'My Text Field', 'woocommerce' ),
    'placeholder' => 'http://',
    'desc_tip' => true,
    'description' => __( "Here's some really helpful tooltip text.", "woocommerce" ),
    'value' => get_post_meta( $variation->ID, '_variable_text_field', true )
    )
    );

    // Add extra custom fields here as necessary...
    ?>

    ID, '_variable_custom_field_type', true ); ?>

    echo '
    ';

}
// Variations tab
//add_action( 'woocommerce_variation_options', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After variation Enabled/Downloadable/Virtual/Manage Stock checkboxes
//add_action( 'woocommerce_variation_options_pricing', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Price fields
//add_action( 'woocommerce_variation_options_inventory', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Manage Stock fields
//add_action( 'woocommerce_variation_options_dimensions', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Weight/Dimension fields
//add_action( 'woocommerce_variation_options_tax', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Shipping/Tax Class fields
//add_action( 'woocommerce_variation_options_download', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Download fields
add_action( 'woocommerce_product_after_variable_attributes', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After all Variation fields

/*

  • Save our variable product fields
    */
    function mytheme_woo_add_custom_variation_fields_save( $post_id ){

    // Text Field
    $woocommerce_text_field = $_POST['_variable_text_field'][ $post_id ];
    update_post_meta( $post_id, '_variable_text_field', esc_attr( $woocommerce_text_field ) );

    $variable_custom_field_type = array( esc_attr( $_POST['_field_one'] ), esc_attr( $_POST['_field_two'] ) );
    update_post_meta( $post_id, '_variable_custom_field_type', $variable_custom_field_type );

}
add_action( 'woocommerce_save_product_variation', 'mytheme_woo_add_custom_variation_fields_save', 10, 2 );

/*

  • Display our example custom field above the summary on the Single Product Page
    */
    function mytheme_display_woo_custom_fields() {
    global $post;

    $ourTextField = get_post_meta( $post->ID, '_variable_text_field', true );

    if ( !empty( $ourTextField ) ) {
    echo '

    ';
    }
    }
    add_action( 'woocommerce_single_product_summary', 'mytheme_display_woo_custom_fields', 15 );
    I added a text field to the variable product and added a file URL to the text field. this process correctly works in the simple product, but variable products did not show correctly. how can I get correctly variable data to here( <a href="' . $ourTextField . '">Download Report</a> ).but all variable data save correctly in DB. @maddisondesigns can you please help me to fix this
    Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment