WooCommerce Custom Meta Fields Solution

This solution allows you to add custom fields to WooCommerce products that will appear:

  • In the product's General tab
  • On the frontend product detail page
  • In the admin order view
  • On order confirmation pages
  • In order confirmation emails

Implementation Steps

1. Add this code to your theme's functions.php or a custom plugin

/**
 * WooCommerce Custom Product Meta Fields
 */

// 1. Add custom fields to product general tab
add_action('woocommerce_product_options_general_product_data', 'add_custom_product_fields');
function add_custom_product_fields() {
    global $post;
    
    echo '<div class="options_group">';
    
    // Define your custom fields here
    $custom_fields = array(
        'custom_field_1' => array(
            'id'          => '_custom_field_1',
            'label'       => __('Custom Field 1', 'text-domain'),
            'placeholder' => __('Enter value', 'text-domain'),
            'desc_tip'    => true,
            'description' => __('Description for field 1', 'text-domain'),
        ),
        'custom_field_2' => array(
            'id'          => '_custom_field_2',
            'label'       => __('Custom Field 2', 'text-domain'),
            'placeholder' => __('Enter value', 'text-domain'),
            'desc_tip'    => true,
            'description' => __('Description for field 2', 'text-domain'),
        ),
        // Add more fields as needed
    );
    
    foreach ($custom_fields as $field) {
        woocommerce_wp_text_input($field);
    }
    
    echo '</div>';
}

// 2. Save custom fields
add_action('woocommerce_process_product_meta', 'save_custom_product_fields');
function save_custom_product_fields($post_id) {
    $custom_fields = array(
        '_custom_field_1',
        '_custom_field_2',
        // Add more field IDs here
    );
    
    foreach ($custom_fields as $field) {
        if (isset($_POST[$field])) {
            update_post_meta($post_id, $field, sanitize_text_field($_POST[$field]));
        }
    }
}

// 3. Display on frontend product page
add_action('woocommerce_product_meta_start', 'display_custom_fields_frontend');
function display_custom_fields_frontend() {
    global $product;
    
    $custom_fields = array(
        '_custom_field_1' => __('Custom Field 1', 'text-domain'),
        '_custom_field_2' => __('Custom Field 2', 'text-domain'),
        // Add more fields here
    );
    
    foreach ($custom_fields as $key => $label) {
        $value = get_post_meta($product->get_id(), $key, true);
        if ($value) {
            echo '<div class="custom-product-field">';
            echo '<span class="label">' . esc_html($label) . ':</span> ';
            echo '<span class="value">' . esc_html($value) . '</span>';
            echo '</div>';
        }
    }
}

// 4. Display in admin order and emails
add_action('woocommerce_order_item_meta_start', 'display_custom_fields_in_order', 10, 3);
function display_custom_fields_in_order($item_id, $item, $order) {
    $product = $item->get_product();
    if (!$product) return;
    
    $custom_fields = array(
        '_custom_field_1' => __('Custom Field 1', 'text-domain'),
        '_custom_field_2' => __('Custom Field 2', 'text-domain'),
        // Add more fields here
    );
    
    foreach ($custom_fields as $key => $label) {
        $value = get_post_meta($product->get_id(), $key, true);
        if ($value) {
            echo '<div class="custom-product-field">';
            echo '<span class="label">' . esc_html($label) . ':</span> ';
            echo '<span class="value">' . esc_html($value) . '</span>';
            echo '</div>';
        }
    }
}

Last Step - Show all fields on admin edit order edit page

  	
    // 5. Display custom fields in admin order edit page (fixed)
add_action('woocommerce_after_order_itemmeta', 'display_custom_fields_in_admin_order', 10, 3);
function display_custom_fields_in_admin_order($item_id, $item, $product) {
    // Only for "line_item" items (products)
    if ($item->get_type() !== 'line_item') return;
    
    // Get product ID directly from item data
    $product_id = $item->get_product_id();
    if (!$product_id) return;
    
    $custom_fields = array(
        '_custom_field_1' => __('Custom Field 1', 'text-domain'),
        '_custom_field_2' => __('Custom Field 2', 'text-domain'),
        // Add more fields here
    );
    
    foreach ($custom_fields as $key => $label) {
        $value = get_post_meta($product_id, $key, true);
        if ($value) {
            echo '<div class="custom-product-field" style="margin-top:5px;">';
            echo '<strong class="label">' . esc_html($label) . ':</strong> ';
            echo '<span class="value">' . esc_html($value) . '</span>';
            echo '</div>';
        }
    }
}
    
   

Customization Options

Adding More Fields

To add more fields, simply extend the arrays in each function:

  1. Add to the $custom_fields array in add_custom_product_fields()
  2. Add the field ID to the array in save_custom_product_fields()
  3. Add to the $custom_fields arrays in display_custom_fields_frontend() and display_custom_fields_in_order()

Styling the Output

Add this CSS to your theme to style the output:

.custom-product-field {
    margin: 5px 0;
    font-size: 0.9em;
}
.custom-product-field .label {
    font-weight: bold;
}
.custom-product-field .value {
    color: #666;
}

How It Works

  1. Admin Product Edit: Adds fields to the General tab
  2. Data Saving: Saves the field values when product is updated
  3. Frontend Display: Shows fields on the product page
  4. Order Integration: Displays fields in admin orders and emails