WooCommerce Custom Fields for Variations

How to add custom fields to products variations

Hooks

To achieve this, will need to create 3 functions: a first one to register the fields, a second one to create the fields when you click on “add variation” (javascript purpose), and a last one to save the fields data within the database.
Each function will be hooked to these specific actions:

  • woocommerce_product_after_variable_attributes
  • woocommerce_save_product_variation
  • woocommerce_product_after_variable_attributes_js
  • woocommerce_process_product_meta_variable

Fields Types

I will cover only 6 fields types for the moment, and I will probably create a new post for advanced fields later. In this tutorial, you will learn how to add these custom fields to variations:

  • Text Field
  • Number Field
  • Textarea
  • Dropdown Select
  • Checkbox
  • Hidden field

 A quick explanation

Basically the method is more or less the same what i explained in my previous post regarding custom fields for products, but in the case of variations, there’s something different that you need to take into account: when you click the “add variation” button, a new div is loaded by a javascript bit of code. The consequence is that when you register fields for variations, you need to register them twice, once for the “regular process”, and one for the javascript method. That’s why we use the two hooks: woocommerce_product_after_variable_attributesand woocommerce_product_after_variable_attributes_js.
Since WooCommerce 2.4+ you can now define only two hooks, and there is no need to register fields for javascript use anymore!

<?php
// Add Variation Settings
add_action( 'woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3 );
// Save Variation Settings
add_action( 'woocommerce_save_product_variation', 'save_variation_settings_fields', 10, 2 );
/**
 * Create new fields for variations
 *
*/
function variation_settings_fields( $loop, $variation_data, $variation ) {
	// Text Field
	woocommerce_wp_text_input(
		array(
			'id'          => '_text_field[' . $variation->ID . ']',
			'label'       => __( 'My Text Field', 'woocommerce' ),
			'placeholder' => 'http://',
			'desc_tip'    => 'true',
			'description' => __( 'Enter the custom value here.', 'woocommerce' ),
			'value'       => get_post_meta( $variation->ID, '_text_field', true )
		)
	);
	// Number Field
	woocommerce_wp_text_input(
		array(
			'id'          => '_number_field[' . $variation->ID . ']',
			'label'       => __( 'My Number Field', 'woocommerce' ),
			'desc_tip'    => 'true',
			'description' => __( 'Enter the custom number here.', 'woocommerce' ),
			'value'       => get_post_meta( $variation->ID, '_number_field', true ),
			'custom_attributes' => array(
							'step' 	=> 'any',
							'min'	=> '0'
						)
		)
	);
	// Textarea
	woocommerce_wp_textarea_input(
		array(
			'id'          => '_textarea[' . $variation->ID . ']',
			'label'       => __( 'My Textarea', 'woocommerce' ),
			'placeholder' => '',
			'description' => __( 'Enter the custom value here.', 'woocommerce' ),
			'value'       => get_post_meta( $variation->ID, '_textarea', true ),
		)
	);
	// Select
	woocommerce_wp_select(
	array(
		'id'          => '_select[' . $variation->ID . ']',
		'label'       => __( 'My Select Field', 'woocommerce' ),
		'description' => __( 'Choose a value.', 'woocommerce' ),
		'value'       => get_post_meta( $variation->ID, '_select', true ),
		'options' => array(
			'one'   => __( 'Option 1', 'woocommerce' ),
			'two'   => __( 'Option 2', 'woocommerce' ),
			'three' => __( 'Option 3', 'woocommerce' )
			)
		)
	);
	// Checkbox
	woocommerce_wp_checkbox(
	array(
		'id'            => '_checkbox[' . $variation->ID . ']',
		'label'         => __('My Checkbox Field', 'woocommerce' ),
		'description'   => __( 'Check me!', 'woocommerce' ),
		'value'         => get_post_meta( $variation->ID, '_checkbox', true ),
		)
	);
	// Hidden field
	woocommerce_wp_hidden_input(
	array(
		'id'    => '_hidden_field[' . $variation->ID . ']',
		'value' => 'hidden_value'
		)
	);
}
/**
 * Save new fields for variations
 *
*/
function save_variation_settings_fields( $post_id ) {
	// Text Field
	$text_field = $_POST['_text_field'][ $post_id ];
	if( ! empty( $text_field ) ) {
		update_post_meta( $post_id, '_text_field', esc_attr( $text_field ) );
	}
	// Number Field
	$number_field = $_POST['_number_field'][ $post_id ];
	if( ! empty( $number_field ) ) {
		update_post_meta( $post_id, '_number_field', esc_attr( $number_field ) );
	}
	// Textarea
	$textarea = $_POST['_textarea'][ $post_id ];
	if( ! empty( $textarea ) ) {
		update_post_meta( $post_id, '_textarea', esc_attr( $textarea ) );
	}
	// Select
	$select = $_POST['_select'][ $post_id ];
	if( ! empty( $select ) ) {
		update_post_meta( $post_id, '_select', esc_attr( $select ) );
	}
	// Checkbox
	$checkbox = isset( $_POST['_checkbox'][ $post_id ] ) ? 'yes' : 'no';
	update_post_meta( $post_id, '_checkbox', $checkbox );
	// Hidden field
	$hidden = $_POST['_hidden_field'][ $post_id ];
	if( ! empty( $hidden ) ) {
		update_post_meta( $post_id, '_hidden_field', esc_attr( $hidden ) );
	}
}

Registering fields is pretty basic as you see we use the WooCommerce builtin functions (All these functions are located in WooCommerce/Admin/WritePanels/writepanels-init.php.):

Finally, the only “tricky” part is the within the save_variation_settings_fields() function, where you need to make sure that each field uses the update_post_meta() function, otherwise your field won’t be saved. The use of a “for” loop is needed to loop through all variations.
To get those values on the frontend we just need to use the popular get_post_meta() function. That’s pretty much all you need.

Displaying Fields Values on the Frontend with WooCommerce 2.5+

WooCommerce introduced wp.template, and it’s now easier to display variations custom fields values based on the selection of the attribute value in the dropdown select. You need to add the following function to functions.php:

<?php
// Add New Variation Settings
add_filter( 'woocommerce_available_variation', 'load_variation_settings_fields' );
/**
 * Add custom fields for variations
 *
*/
function load_variation_settings_fields( $variations ) {
	// duplicate the line for each field
	$variations['text_field'] = get_post_meta( $variations[ 'variation_id' ], '_text_field', true );
	return $variations;
}

And now you need to edit the custom template that display the variation fields. This file is called variation.php and is located in wp-plugins/plugins/woocommerce/templates/single-product/add-to-cart/. Do not edit this file directly but instead, duplicate it and place it in a folder called woocommerce/templates/single-product/add-to-cart/ in your theme folder (Keep in mind: never edit core files). Add this code:

    <div class="woocommerce-variation-custom-text-field">
        {{{ data.variation.text_field }}}
    </div>