Advanced WooCommerce Customization Guide: Fees, Checkout Fields, and Product Meta (EEAT Optimized)
Meta Title (Suggested)
Advanced WooCommerce Customization with Hooks: Fees, Checkout Fields & Product Meta (Complete Guide)
Meta Description (Suggested)
Learn advanced WooCommerce customization using hooks and actions. Add custom cart notices, dynamic fees, checkout gift options, and product meta fields with real-world code examples.
WooCommerce is powerful out of the box, but its real strength lies in customization through hooks and actions. As a WordPress and WooCommerce developer, you often need to go beyond default features—whether it’s adding conditional fees, improving checkout UX, or extending product data for business-specific needs.
In this in-depth, EEAT-optimized guide, we will walk through a complete real-world WooCommerce customization example based on the provided code. This article is written from the perspective of an experienced WooCommerce developer and consultant, explaining what the code does, why it’s needed, and how it works internally.
By the end of this article, you’ll clearly understand:
How to enable WooCommerce support in a theme
How to add custom cart notices
How to apply dynamic fees and discounts
How to extend the checkout with gift options
How to save and display custom order meta
How to add custom product meta fields in the admin
How to display custom product data on the frontend
This guide is ideal for WooCommerce developers, WordPress freelancers, and store owners who want clean, scalable customizations without third-party plugins.
1. Enabling WooCommerce Support in Your Theme
Before making any WooCommerce customizations, your theme must declare WooCommerce compatibility.
add_theme_support('woocommerce');
Why this matters
This tells WooCommerce that your theme supports its templates and features. Without this, certain layouts and hooks may not work correctly.
Best practice: Always add this in your theme’s functions.php or child theme.
2. Adding a Custom Notice Above the Cart Totals
Displaying contextual messages in the cart improves conversion and user experience.
Code Example
add_action(
'woocommerce_cart_totals_after_order_total',
function () {
echo '<tr class="free-shipping-msg">
<th></th>
<td>Free shipping on orders above ₹999</td>
</tr>';
}
);
Explanation
Hook used:
woocommerce_cart_totals_after_order_totalThis hook runs inside the cart totals table
A custom table row is injected below the order total
Real-world use cases
Free shipping thresholds
Limited-time offers
Payment method notices
This approach is lightweight and avoids unnecessary JavaScript or plugins.
3. Adding Dynamic Fees and Discounts Based on Cart Value
WooCommerce allows you to programmatically add fees or discounts using the woocommerce_cart_calculate_fees hook.
Code Example
add_action('woocommerce_cart_calculate_fees', function ($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
// Fee for orders > ₹600
if ($cart->subtotal > 600) {
$cart->add_fee('Special Handling Fee', 100);
}
// Discount for orders > ₹500
if ($cart->subtotal > 500) {
$discount = $cart->subtotal * 0.5;
$cart->add_fee('Special Discount', -$discount);
}
});
Explanation
The function runs every time totals are recalculated
add_fee()supports negative values, making it perfect for discountsAdmin/AJAX check prevents unwanted execution in the backend
Important note
A 50% discount is extremely high and used here for demonstration. In production, always validate business rules carefully.
Use cases
COD charges
Bulk order discounts
Seasonal promotions
4. Adding Gift Options to the Checkout Page
Checkout customization directly impacts conversion. This example adds a gift wrap checkbox and gift message textarea.
Adding Custom Checkout Fields
add_action('woocommerce_after_order_notes', function ($checkout) {
echo '<div id="custom_checkout_field"><h3>Gift Options</h3>';
woocommerce_form_field('gift_wrap', array(
'type' => 'checkbox',
'class' => array('form-row-wide'),
'label' => 'Gift wrap this order?',
), $checkout->get_value('gift_wrap') === 'yes' ? '1' : '');
woocommerce_form_field('gift_message', array(
'type' => 'textarea',
'class' => array('form-row-wide'),
'label' => 'Gift Message',
'placeholder' => 'Write your message here',
'required' => false,
), $checkout->get_value('gift_message'));
echo '</div>';
Why woocommerce_after_order_notes?
This hook places custom fields logically after billing details, maintaining UX consistency.
5. Improving UX with jQuery (Show/Hide Gift Message)
<script type="text/javascript">
jQuery(function($) {
var $giftCheckbox = $('#gift_wrap');
var $giftMessage = $('#gift_message_field');
function toggleGiftMessage() {
if ($giftCheckbox.is(':checked')) {
$giftMessage.show();
} else {
$giftMessage.hide();
}
}
toggleGiftMessage();
$giftCheckbox.on('change', toggleGiftMessage);
});
</script>
<style>
#gift_message_field { display: none; }
</style>
Explanation
Enhances UX without page reload
Keeps checkout clean and uncluttered
Uses WooCommerce-generated field IDs
6. Saving Checkout Fields to Order Meta
add_action('woocommerce_checkout_update_order_meta', function ($order_id) {
$gift_wrap = isset($_POST['gift_wrap']) ? 'yes' : 'no';
update_post_meta($order_id, 'gift_wrap', $gift_wrap);
if (isset($_POST['gift_message']) && !empty($_POST['gift_message'])) {
update_post_meta($order_id, 'gift_message', sanitize_textarea_field($_POST['gift_message']));
}
});
Best practices applied
Sanitization using
sanitize_textarea_fieldExplicit yes/no values for checkboxes
7. Displaying Gift Details in WooCommerce Admin Orders
add_action('woocommerce_admin_order_data_after_billing_address', function ($order) {
$gift = get_post_meta($order->get_id(), 'gift_wrap', true);
$message = get_post_meta($order->get_id(), 'gift_message', true);
if ($gift === 'yes') {
echo '<p><strong>Gift Wrap:</strong> Yes</p>';
if ($message) {
echo '<p><strong>Gift Message:</strong><br>' . nl2br(esc_html($message)) . '</p>';
}
}
});
This ensures order handlers never miss important gift instructions.
8. Adding Custom Product Meta Box (Admin Side)
add_action('add_meta_boxes', function () {
add_meta_box(
'product_email_box',
'Product Email Options',
'product_email_meta_box_html',
'product',
'normal',
'high'
);
});
Meta Box HTML
function product_email_meta_box_html($post)
{
$email = get_post_meta($post->ID, '_product_email', true);
$show_email = get_post_meta($post->ID, '_show_product_email', true);
wp_nonce_field('product_email_nonce', 'product_email_nonce_field');
?>
<p>
<label>Email:</label><br>
<input type="email" name="product_email" value="<?php echo esc_attr($email); ?>" style="width:100%;">
</p>
<p>
<label>
<input type="checkbox" name="show_product_email" value="yes" <?php checked($show_email, 'yes'); ?>>
Show email on product page
</label>
</p>
<?php
}
9. Saving Product Meta Securely
add_action('save_post', function ($post_id) {
if (!isset($_POST['product_email_nonce_field']) || !wp_verify_nonce($_POST['product_email_nonce_field'], 'product_email_nonce')) {
return;
}
if (isset($_POST['product_email'])) {
update_post_meta($post_id, '_product_email', sanitize_email($_POST['product_email']));
}
$show = isset($_POST['show_product_email']) ? 'yes' : 'no';
update_post_meta($post_id, '_show_product_email', $show);
});
Nonce verification ensures security and data integrity.
10. Displaying Product Email on the Frontend
add_action('woocommerce_single_product_summary', function () {
global $product;
$show_email = get_post_meta($product->get_id(), '_show_product_email', true);
$email = get_post_meta($product->get_id(), '_product_email', true);
if ($show_email === 'yes' && !empty($email)) {
echo '<p><strong>Contact Email:</strong> ' . esc_html($email) . '</p>';
}
}, 25);
Why priority 25?
It places the email neatly after the product price, maintaining visual hierarchy.
11. Adding Custom WooCommerce Order Status (Preparing & Out for Delivery)
Order fulfillment is not always limited to WooCommerce’s default statuses like Processing or Completed. Real-world stores often need intermediate order statuses such as Preparing and Out for Delivery to better manage logistics and keep customers informed.
This section shows how to:
Register custom order statuses
Display them in the admin order status dropdown
Allow admins to update them easily
Show the current status clearly on the customer’s order page
Step 1: Register Custom Order Statuses
add_action('init', function () {
register_post_status('wc-preparing', array(
'label' => 'Preparing',
'public' => true,
'show_in_admin_status_list' => true,
'show_in_admin_all_list' => true,
'exclude_from_search' => false,
'label_count' => _n_noop('Preparing (%s)', 'Preparing (%s)')
));
register_post_status('wc-out-for-delivery', array(
'label' => 'Out for Delivery',
'public' => true,
'show_in_admin_status_list' => true,
'show_in_admin_all_list' => true,
'exclude_from_search' => false,
'label_count' => _n_noop('Out for Delivery (%s)', 'Out for Delivery (%s)')
));
});
Explanation
wc-prefix is mandatory for WooCommerce order statusesshow_in_admin_status_listensures visibility in admin filtersThese statuses behave like native WooCommerce statuses
Step 2: Add Custom Statuses to WooCommerce Order Status List
add_filter('wc_order_statuses', function ($order_statuses) {
$new_statuses = array();
foreach ($order_statuses as $key => $status) {
$new_statuses[$key] = $status;
if ($key === 'wc-processing') {
$new_statuses['wc-preparing'] = 'Preparing';
$new_statuses['wc-out-for-delivery'] = 'Out for Delivery';
}
}
return $new_statuses;
});
Why this approach?
Inserts statuses logically after Processing
Keeps fulfillment flow intuitive for admins
Admin can now update order status directly from the order edit screen.
Step 3: Display Custom Order Status on My Account → Order Page
WooCommerce automatically displays order status text, but we can enhance clarity for customers.
add_action('woocommerce_view_order', function ($order_id) {
$order = wc_get_order($order_id);
$status = $order->get_status();
if (in_array($status, array('preparing', 'out-for-delivery'))) {
echo '<p class="custom-order-status"><strong>Order Status:</strong> ' . wc_get_order_status_name($status) . '</p>';
}
});
Customer Experience Benefits
Customers clearly know if their order is being packed or shipped
Reduces "Where is my order?" support tickets
Improves trust and transparency
Optional: Styling the Status Message
.custom-order-status {
padding: 12px;
background: #f7f7f7;
border-left: 4px solid #2271b1;
margin-bottom: 20px;
}
Real-World Use Cases
Local delivery businesses
Hyperlocal grocery stores
Custom logistics workflows
Odoo or ERP-integrated WooCommerce stores
These custom statuses integrate perfectly with automation tools, webhooks, and ERP systems.
Add “Made in India” Checkbox in WooCommerce General Settings
What this does
-
✅ Adds a checkbox in WooCommerce → Settings → General
-
✅ Admin can enable/disable it globally
-
✅ Saves value in WordPress options table
-
✅ Displays “Made in India” on single product pages
-
✅ Message shows only if checkbox is checked
-
❌ No impact on products when disabled
1. Add Checkbox in WooCommerce General Settings
add_filter('woocommerce_general_settings', function ($settings) {$custom_settings = array();foreach ($settings as $setting) {$custom_settings[] = $setting;// Add setting after store address sectionif (isset($setting['id']) && $setting['id'] === 'woocommerce_store_address') {$custom_settings[] = array('name' => 'Product Origin Label','type' => 'title','desc' => 'Global product origin message','id' => 'product_origin_label_section');$custom_settings[] = array('name' => 'Show “Made in India” Label','desc' => 'Display “Made in India” message on all product pages','id' => 'wc_show_made_in_india','type' => 'checkbox','default' => 'no');$custom_settings[] = array('type' => 'sectionend','id' => 'product_origin_label_section');}}return $custom_settings;});
2. Display Message on Single Product Pages (Frontend)
add_action('woocommerce_single_product_summary', function () {
$enabled = get_option('wc_show_made_in_india');
if ($enabled === 'yes') {
echo '<p class="made-in-india-label">
<strong>Made in India 🇮🇳</strong>
</p>';
}
}, 35); // 35 = below price & short description
Result
-
✔ Shows message on all single product pages
-
✔ Hidden automatically when checkbox is unchecked
-
✔ No product-level configuration required
3. Optional Styling (Recommended)
.made-in-india-label {margin-top: 10px;padding: 8px 12px;background: #f6fff6;border-left: 4px solid #138808;color: #000;font-size: 14px;}
How This Works (Logic Flow)
-
Admin checks “Show Made in India Label”
-
WooCommerce saves value as:
-
Single product page loads
-
Hook checks option value
-
Message displays only if enabled
Final Thoughts
This complete WooCommerce customization demonstrates how powerful hooks, actions, and clean PHP logic can be when implemented correctly.
Instead of relying on heavy plugins, you now have:
Performance-friendly custom logic
Better UX at checkout
Cleaner admin workflows
Scalable and maintainable code
If you’re a WooCommerce developer or store owner aiming for professional, enterprise-level customization, this approach aligns perfectly with EEAT principles—showing real expertise, practical experience, and trustworthy implementation.
Written by an experienced WooCommerce & WordPress developer with real-world implementation expertise.
21.6
628.8
16
16
58.4
668.8
Post a Comment
Please Do Not Enter Any Spam Link or Abuse Word in The Comment Box.