Modify WooCommerce Product Price Based on Checkbox (Without Plugins)

design
Modify WooCommerce product price based on a checkbox without using plugins

Sometimes you don’t need a full “product add-ons” plugin just to charge a little extra for something simple—like gift wrap, priority processing, or extended warranty.

In this tutorial, you’ll build a checkbox on the single product page that, when checked:

  • Adds a fixed extra amount (example: +$5.00)
  • Updates the cart line item price (the part that actually matters for totals)
  • Shows the selection on cart/checkout
  • Saves it to the order (so it appears in admin + emails)

No plugins. Just WooCommerce hooks + a little JS.


What we’re building (and how WooCommerce pricing really works)

WooCommerce pricing has two separate realities:

  1. Displayed product price on the product page (mostly cosmetic)
  2. Cart item price used for totals (the real billing)

If you only change the displayed price with JavaScript, checkout totals will still be wrong.
So we’ll do both:

  • Frontend (JS): Show a “live” updated price when checkbox is toggled
  • Backend (PHP): Add data to cart item + adjust price in woocommerce_before_calculate_totals

WooCommerce’s hook system is designed for this kind of customization.


Step 0 — Decide your add-on amount (and where it should apply)

In this example, we’ll use:

  • Checkbox label: “Add gift wrap (+$5)”
  • Extra charge: 5
  • Applies per quantity (if qty=2 and gift wrap checked → add $10 total)

If you want it to be “per line item” instead (only +$5 once no matter quantity), I’ll show where to change that.


Step 1 — Add a checkbox to the single product page

Add this to your child theme functions.php (or a small custom plugin).

/**
 * 1) Display checkbox on single product page.
 */
add_action( 'woocommerce_before_add_to_cart_button', function() {
	// Optional: only show on simple products
	global $product;
	if ( ! $product || ! $product->is_type('simple') ) {
		return;
	}

	woocommerce_form_field( 'bb_addon_giftwrap', [
		'type'  => 'checkbox',
		'class' => [ 'form-row-wide' ],
		'label' => 'Add gift wrap (+$5)',
	], '' );
});

This outputs a real WooCommerce field (so it’s consistent with theme styles).


Step 2 — Validate (optional but recommended)

If you ever make the checkbox required (or conditional), validation belongs here.

For a normal optional checkbox, validation can be minimal—but here’s a pattern you can reuse:

/**
 * 2) Validate add-on field before add to cart.
 */
add_filter( 'woocommerce_add_to_cart_validation', function( $passed, $product_id, $qty ) {

	// Example: if you ever need to require it, you’d check and add a notice here.
	// if ( empty($_POST['bb_addon_giftwrap']) ) {
	//     wc_add_notice( 'Please confirm gift wrap selection.', 'error' );
	//     return false;
	// }

	return $passed;
}, 10, 3 );

Step 3 — Store checkbox value in cart item data

When the user adds to cart, we need to attach a flag to that cart item.

WooCommerce provides woocommerce_add_cart_item_data specifically for this.

/**
 * 3) Save checkbox selection into cart item data.
 */
add_filter( 'woocommerce_add_cart_item_data', function( $cart_item_data, $product_id, $variation_id, $quantity ) {

	$checked = ! empty( $_POST['bb_addon_giftwrap'] );

	if ( $checked ) {
		$cart_item_data['bb_addon_giftwrap'] = true;

		/**
		 * IMPORTANT:
		 * This makes the cart item unique so Woo doesn't merge
		 * two items where one has giftwrap and the other doesn't.
		 */
		$cart_item_data['bb_addon_unique_key'] = md5( microtime(true) . rand() );
	}

	return $cart_item_data;
}, 10, 4 );

Why the unique key matters: without it, WooCommerce may merge items and you’ll lose per-item options.


Step 4 — Display the selection on Cart + Checkout

This makes the UX clear and reduces refunds/support tickets.

/**
 * 4) Show add-on in cart and checkout line item data.
 */
add_filter( 'woocommerce_get_item_data', function( $item_data, $cart_item ) {

	if ( ! empty( $cart_item['bb_addon_giftwrap'] ) ) {
		$item_data[] = [
			'key'   => 'Gift wrap',
			'value' => 'Yes (+$5)',
		];
	}

	return $item_data;
}, 10, 2 );

Step 5 — Adjust the cart item price (this is the real pricing change)

This is the most important part.

We’ll use woocommerce_before_calculate_totals to modify the price of the product inside the cart object (so totals update properly). This is a standard WooCommerce approach for cart-level price overrides.

/**
 * 5) Increase cart item price when checkbox is selected.
 */
add_action( 'woocommerce_before_calculate_totals', function( $cart ) {

	if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
		return;
	}

	if ( ! $cart || $cart->is_empty() ) {
		return;
	}

	$extra = 5.0; // +$5

	foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {

		if ( empty( $cart_item['bb_addon_giftwrap'] ) ) {
			continue;
		}

		// Base price (current product price in cart context)
		$base_price = (float) $cart_item['data']->get_price();

		/**
		 * Prevent double-adding the extra fee:
		 * WooCommerce may run calculate_totals multiple times.
		 */
		if ( empty( $cart_item['bb_addon_price_applied'] ) ) {
			$new_price = $base_price + $extra;

			$cart_item['data']->set_price( $new_price );
			$cart_item['bb_addon_price_applied'] = true;

			// Persist the flag back into cart contents
			$cart->cart_contents[ $cart_item_key ] = $cart_item;
		}
	}

}, 100 );

Want “+ $5 once per line item” (not per quantity)?

This method is already per unit, because Woo’s price is per unit.
If you want + $5 once total per line, don’t change the unit price—instead add a fee via woocommerce_cart_calculate_fees. (Different pattern; tell me and I’ll drop that version.)


Step 6 — Save the selection to the order (so it appears in admin + emails)

/**
 * 6) Save add-on selection to order item meta.
 */
add_action( 'woocommerce_checkout_create_order_line_item', function( $item, $cart_item_key, $values, $order ) {

	if ( ! empty( $values['bb_addon_giftwrap'] ) ) {
		$item->add_meta_data( 'Gift wrap', 'Yes (+$5)', true );
	}

}, 10, 4 );

Now the store owner sees it in the backend, and it can also appear in emails depending on email template settings.


Step 7 — Optional: Update the displayed price instantly on the product page (JS)

Again: JS is not the pricing engine—it’s just to improve UX.

This script reads the displayed price on the product page, adds $5 when checked, and swaps the visible text.

Add this (still inside functions.php):

/**
 * 7) Frontend script to update displayed price on toggle (optional UX).
 */
add_action( 'wp_footer', function() {
	if ( ! is_product() ) return;
	?>
	<script>
	(function(){
		const checkbox = document.querySelector('input[name="bb_addon_giftwrap"]');
		const priceEl  = document.querySelector('.summary .price .woocommerce-Price-amount');
		if(!checkbox || !priceEl) return;

		const extra = 5;

		// Try to parse the first visible price amount
		const getNumber = (text) => {
			// remove currency symbols and commas
			const num = text.replace(/[^\d.]/g,'');
			return parseFloat(num || '0');
		};

		// Store original numeric price once
		const originalText = priceEl.textContent;
		const originalVal  = getNumber(originalText);

		const formatLikeOriginal = (val) => {
			// simple formatting; your theme/currency may differ
			const fixed = val.toFixed(2);
			return originalText.replace(getNumber(originalText).toFixed(2), fixed);
		};

		const update = () => {
			if(checkbox.checked){
				priceEl.textContent = formatLikeOriginal(originalVal + extra);
			}else{
				priceEl.textContent = originalText;
			}
		};

		checkbox.addEventListener('change', update);
	})();
	</script>
	<?php
});

If your theme has variable prices, sale prices, or multiple .woocommerce-Price-amount nodes, we’ll adjust selectors—this is intentionally “starter safe.”


Common Issues (and how to fix them)

1) “Price keeps increasing every refresh”

That’s the classic calculate_totals running multiple times. WooCommerce can re-run totals during AJAX updates, checkout changes, etc. There’s even discussion around how often totals can run.
Fix: we used the bb_addon_price_applied flag.

2) “Checkbox selection doesn’t show on checkout”

Make sure Step 3 stored the flag in cart item data and Step 4 prints it using woocommerce_get_item_data.

3) “Cart merges items and loses one selection”

The unique key in Step 3 prevents merging. Keep it.

4) “My checkout is slow / stuck loading”

When you add custom cart logic, checkout performance matters. If you’re seeing delays, cross-check your AJAX/caching/session behavior too:

5) “Cart empties after refresh”

That’s usually caching/cookie/session issues—not this pricing pattern. Still, here’s our internal guide on woocommerce cart empty after refresh.

FAQs: Modify WooCommerce Product Price Based on Checkbox

Add a checkbox field on the product page, store its value in cart item data, then update the cart item price using woocommerce_before_calculate_totals. This ensures the updated price is used for cart totals and checkout.

Yes. You can do it with WooCommerce hooks and a small PHP snippet—no plugins required. The key is changing the cart item price, not just the displayed product price.

JavaScript only changes what the customer sees on the product page. WooCommerce calculates totals server-side, so you must update the cart item price in PHP for checkout totals to match.

Use woocommerce_before_calculate_totals. It runs before totals are calculated, allowing you to adjust the product price in the cart object safely.

WooCommerce can recalculate totals more than once. Add a flag in the cart item data (like price_applied) and check it before adding the extra cost to avoid double-charging.

Use the woocommerce_get_item_data filter to display the checkbox selection as line-item data. This makes it visible in both the cart and checkout UI.

Use woocommerce_checkout_create_order_line_item to store the selection as order item meta. This makes the selection visible in the admin order screen and in customer emails (depending on template settings).

WooCommerce may merge identical products into one line item. To prevent this, add a unique key (like unique_key) to the cart item data when the checkbox is checked.

Yes. Instead of increasing the unit price, add a flat fee using woocommerce_cart_calculate_fees so it applies once per line item (not per quantity).

It can, but you may need to adjust logic for variations and ensure the checkbox is included for each variation add-to-cart form. The core approach stays the same: store the option in cart item data and modify the cart item price.

Meet the Author

Babar khan

Babar Ilyas is a full-stack WordPress developer and SEO strategist focused on building fast, functional, and search-optimized websites. With years of hands-on experience, he shares real-world fixes and dev workflows that actually work.
When he’s not deep in code, he’s dropping fresh blog posts and tracking what Google’s up to — one ranking at a time.
Leave a Reply

Your email address will not be published. Required fields are marked *

    Branding Design Development Front-End Website-Redesigning Shopify-Development WordPress-Development
    Branding Design Development Front-End Website-Redesigning Shopify-Development WordPress-Development
    We love crafting unforgettable
    digital experiences, brands and websites with people like you.
    Follow us:
    Let’s get started
    We'd love to hear about your project.
    © 2025 babarilyas. All rights reserved.