How to Add Custom Fields to Product Variations

Long time ago I published a tutorial where I described how to add custom fields to WooCommerce products. Now it is time to dive deep into product variations and add a couple settings fields there as well.

Also recommend you my plugin Simple Variation Swatches, because it is really simple!

Where Exactly We Can Display a Variation Custom Field?

The same way, as with the products themselves it is possible to place a field in a different location related to the other variation fields. Let’s figure out what options do we have here.

woocommerce_variation_options_pricing

Let’s begin with the first hook that displays custom fields (or anything you want) at the very beginning of variation settings block, just after the prices.

Let’s try it this way:

add_action( 'woocommerce_variation_options_pricing', 'rudr_v_fields', 10, 3 );

function rudr_v_fields( $loop, $variation_data, $variation ) {
	echo '<p class="form-row form-row-full">hey there</p>';
}

There are you can also see 3 arguments available inside the function:

  • $loop – it is just an iteration count of a variation we are currently editing. If it is the first one in the list, it will be 0, the second one – 1 and so on.
  • $variation_data – an array with all variation fields settings the same way as they are stored in post meta. For example $variation_data[ '_regular_price' ][0].
  • $variation – WP_Post object of this specific variation. For example it allows to get a variation ID easily with $variation->ID.

Do not know where to insert the code by the way?

And here we are:

example of using woocommerce_variation_options_pricing
As you can see our custom text got displayed just after the price fields.

woocommerce_variation_options_inventory

This hook is going to display your field in “Inventory” field group which is shown only if Manage stock? checkbox is checked.

add_action( 'woocommerce_variation_options_inventory', 'rudr_v_fields' );

function rudr_v_fields( $loop ) {
	echo '<p class="form-row form-row-full">hey there</p>';
}
woocommerce_variation_options_inventory hook example

woocommerce_variation_options_dimensions

This hook will going to display your field just under “Weight” and “Dimensions” fields which are displayed only if Virtual checkbox is unchecked.

woocommerce_variation_options_download

This hook will going to display your field just under “Download limit” and “Download expiry” fields which are displayed only if Downloadable checkbox is checked.

woocommerce_product_after_variable_attributes

This hook will display your fields at the very end of all variation settings, under the “Description” field.

Add a Custom Field

Creating a field for variation settings is quite simple, the only thing to keep in mind is that you do not have to use regular HTML like <input type="text"/>, but instead – special WooCommerce functions. For a text field it would be woocommerce_wp_text_input().

add_action( 'woocommerce_product_after_variable_attributes', 'rudr_field', 10, 3 );

function rudr_field( $loop, $variation_data, $variation ) {

	woocommerce_wp_text_input(
		array(
			'id'            => 'text_field[' . $loop . ']',
			'label'         => 'Text field value',
			'wrapper_class' => 'form-row',
			'placeholder'   => 'Type here...',
			'desc_tip'      => true,
			'description'   => 'We can add some description for a field.',
			'value'         => get_post_meta( $variation->ID, 'rudr_text_field', true )
		)
	);

}

There are a couple moments to highlight in the code above:

  • I recommend to add class form-row to the wrapper, otherwise the field is not going to have the same styles as the rest of the fields. You can also use form-row-first and form-row-last when displaying the fields in two columns.
  • The description of the field is going to be displayed when you hover on a question mark in case 'desc_tip' => true and is going to be displayed under the field otherwise.
Add a custom field to WooCommerce product variations

Field Types

Above we have added just a simple text field using woocommerce_wp_text_input() function, but of course the other field types are also can be added here. But we need to use an according function for every type.

  • woocommerce_wp_textarea_input() – for textarea fields,
  • woocommerce_wp_select() – for select fields,
  • woocommerce_wp_radio() – for radio fields,
  • woocommerce_wp_checkbox() – for checkbox fields,
  • woocommerce_wp_hidden_input() – for hidden fields.

But checkboxes and radio buttons look like they aren’t supported as variation settings, I mean they will be displayed of course and will work also, but the styling needs some customization, you will see it on the screenshot below.

All the functions have almost the same arguments, but of course there are some differences as well. In order to make it clear let’s take a look at the example.

add_action( 'woocommerce_product_after_variable_attributes', 'rudr_fields', 10, 3 );

function rudr_fields( $loop, $variation_data, $variation ) {

	woocommerce_wp_text_input(
		array(
			'id'            => 'text_field[' . $loop . ']',
			'label'         => 'Text field value',
			'wrapper_class' => 'form-row',
			'placeholder'   => 'Type here...',
			'desc_tip'      => 'true',
			'description'   => 'We can add some description for a field.',
			'value'         => get_post_meta( $variation->ID, 'rudr_text', true )
		)
	);

	// Textarea
	woocommerce_wp_textarea_input(
		array(
			'id'            => 'textarea_field[' . $loop . ']',
			'label'         => 'Textarea field',
			'wrapper_class' => 'form-row',
			'value'         => get_post_meta( $variation->ID, 'rudr_textarea', true ),
		)
	);

	// Select
	woocommerce_wp_select(
		array(
			'id'            => 'select_field[' . $loop . ']',
			'label'         => 'Select field',
			'wrapper_class' => 'form-row',
			'description'   => 'We can add some description for a field.',
			'value'         => get_post_meta( $variation->ID, 'rudr_select', true ),
			'options'       => array(
				'one'   => 'Option 1',
				'two'   => 'Option 2',
				'three' => 'Option 3'
			)
		)
	);

	woocommerce_wp_radio(
		array(
			'id'            => 'radio_field[' . $loop . ']',
			'label'         => 'Radio field',
			'wrapper_class' => 'form-row',
			'value'         => get_post_meta( $variation->ID, 'rudr_radio', true ),
			'options'       => array(
				'one'   => 'Option 1',
				'two'   => 'Option 2',
				'three' => 'Option 3'
			)
		)
	);

	woocommerce_wp_checkbox(
		array(
			'id'            => 'my_check[' . $loop . ']',
			'label'         => 'Checkbox field',
			'wrapper_class' => 'form-row',
			'value'         => get_post_meta( $variation->ID, 'rudr_check', true ),
		)
	);

	woocommerce_wp_hidden_input(
		array(
			'id'    => 'hidden_field[' . $loop . ']',
			'value' => 'hey there'
		)
	);

}

Result:

custom fields in variations
Ok, the checkbox and radio fields are requiring some custom styling I assume.

Save Custom Field Values as a Variation Metadata

In order to save fields into post meta we are going to use a hook, which is woocommerce_save_product_variation and a function update_post_meta().

Also always remember about sanitizing field values and use appropriate functions for that.

add_action( 'woocommerce_save_product_variation', 'rudr_save_fields', 10, 2 );

function rudr_save_fields( $variation_id, $loop ) {

	// Text Field
	$text_field = ! empty( $_POST[ 'text_field' ][ $loop ] ) ? $_POST[ 'text_field' ][ $loop ] : '';
	update_post_meta( $variation_id, 'rudr_text', sanitize_text_field( $text_field ) );

	// Textarea Field
	$textarea_field = ! empty( $_POST[ 'textarea_field' ][ $loop ] ) ? $_POST[ 'textarea_field' ][ $loop ] : '';
	update_post_meta( $variation_id, 'rudr_textarea', sanitize_textarea_field( $textarea_field ) );

	// Select Field
	$select_field = ! empty( $_POST[ 'select_field' ][ $loop ] ) ? $_POST[ 'select_field' ][ $loop ] : '';
	update_post_meta( $variation_id, 'rudr_select', sanitize_text_field( $select_field ) );


	// Radio Field
	$radio_field = ! empty( $_POST[ 'radio_field' ][ $loop ] ) ? $_POST[ 'radio_field' ][ $loop ] : '';
	update_post_meta( $variation_id, 'rudr_radio', sanitize_text_field( $radio_field ) );

	// Checkbox field
	$checkbox_field = ! empty( $_POST[ 'my_check' ][ $loop ] ) ? 'yes' : 'no';
	update_post_meta( $variation_id, 'rudr_check', $checkbox_field );

	// Hidden
	update_post_meta( $variation_id, '_hidden', $_POST[ 'hidden_field' ][ $loop ] );

}

Showing the fields conditionally

You remember, a little bit above in this tutorial, when I show you the action hooks, I said that some of the hooks will display the fields only if a specific checkbox “Virtual”, “Manage Stock?” etc is checked or unchecked?

We can configure this conditional displaying for the specific fields only. All we need to do is to add a specific CSS class to wrapper_class parameter.

For example if you add:

woocommerce_wp_checkbox(
	array(
		'id'            => 'my_check[' . $loop . ']',
		'label'         => 'Checkbox field',
		'wrapper_class' => 'form-row show_if_variation_virtual',

		...

Then this checkbox field is going to be displayed for Virtual products only! There are a couple more of them:

  • show_if_variation_virtual, hide_if_variation_virtual – show or hide the field for virtual products only.
  • show_if_variation_downloadable, hide_if_variation_downloadable – show or hide for downloadable products only.
  • show_if_variation_manage_stock, hide_if_variation_manage_stock.

Displaying Field Values on the Frontend

Because we store the variation data in post meta, we can get the field values anytime and almost anywhere using get_post_meta() function. Just like that:

$text_field = get_post_meta( $variation_id, 'rudr_text', true );

As an example let’s display the field value here:

display WooCommerce variation custom field value on the frontend

In order to do that we have to do two things. The first one is to add our custom field in woocommerce_available_variation hook.

add_filter( 'woocommerce_available_variation', function( $variation ) {

	$variation[ 'text_field_anything' ] = get_post_meta( $variation[ 'variation_id' ], 'rudr_text', true );
	return $variation;

} );

Then we have to alter a WooCommerce template variation.php from templates/single-product/add-to-cart of a plugin to woocommerce/single-product/add-to-cart of your theme. And then add a line with the field in the duplicated file:

...

<div class="woocommerce-variation-availability">{{{ data.variation.availability_html }}}</div>
<div class="woocommerce-variation-textfdsf">{{{ data.variation.text_field_anything }}}</div>

...
Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on Twitter