TopSyde
Get your free site auditStart Risk-Free

WooCommerce Variation Price Display: Complete Guide 2026

Configure and display WooCommerce variation prices correctly — price ranges, per-variation pricing, custom display logic, and performance-safe implementations.

Elena Marchetti

Elena Marchetti

Content & SEO Strategist

··11 min read

Last updated: July 7, 2026

WooCommerce product page showing variation price range and individual selected variation price

WooCommerce variation price display controls how prices appear on variable product pages — either as a range ("$10 – $50"), a single price when one variation is selected, or a custom format you define. Getting it right affects conversion rates, customer trust, and the accuracy of what your store communicates before checkout.


How WooCommerce Variable Product Pricing Works

WooCommerce stores variation prices in a serialized meta field (_min_variation_price, _max_variation_price, and their sale equivalents) attached to the parent product. Before a shopper selects a variation, the template reads these cached min/max values and renders a range. Once a variation is chosen, a JavaScript event (found_variation) fires and updates the displayed price from the variation's JSON payload embedded in the page.

This architecture has two practical consequences:

  1. The range cache must be current. If you update a variation price but the parent's cached min/max isn't recalculated, the displayed range will be stale.
  2. JavaScript must run for individual prices to appear. If a page builder, caching plugin, or CDN breaks JS execution, customers will only ever see the range — never the selected price.

According to WooCommerce's own documentation, the variation data is output as a JSON blob via wc_get_product_variation_attributes() and loaded into the DOM; the woocommerce-add-to-cart-variation.js script handles all price swapping client-side.


Why the Default Price Range Display Causes Conversion Problems

The default $10 – $50 range is technically accurate but psychologically problematic. Shoppers anchor on the lower number, feel misled when they select a premium variant, and sometimes abandon rather than proceed. Baymard Institute's 2024 product page UX study lists ambiguous pre-selection pricing as a top-5 abandonment driver.

Common symptoms of a broken or confusing range display:

  • Range shows $0 – $50 because one variation has no price set
  • Range doesn't update after a variation is selected (JS failure)
  • Range shows an old value after a product edit (stale cache)
  • Sale price range doesn't reflect the actual discount clearly

Each of these has a distinct fix, covered in the sections below.


How to Configure Prices for Individual Variations

Navigate to Products → [Product Name] → Variations in your WordPress admin. Expand each variation and fill in Regular price (required) and Sale price (optional). Key rules:

  • Never leave Regular price blank unless you intentionally want that variation to be unpurchasable. A blank price on any variation will pull the min cache to $0 and display $0 – $X to customers.
  • Sale price must be lower than regular price or WooCommerce will silently ignore it.
  • You can schedule sale prices using the "Schedule" link next to the sale price field.

For stores with dozens of variations, editing individually is tedious. Use the bulk edit dropdown at the top of the Variations tab: select all variations, choose "Set regular prices," and apply a value or percentage rule. For programmatic updates:

$variation = wc_get_product( $variation_id );
$variation->set_regular_price( '29.99' );
$variation->set_sale_price( '19.99' );
$variation->save();
// Recalculate parent cache
WC_Product_Variable::sync( $parent_product_id );

Always call WC_Product_Variable::sync() after bulk-updating variation prices via code. Skipping this is the most common cause of stale range displays.


How to Change the Price Range Display Format

The price range HTML is generated by WC_Product_Variable::get_price_html() and is filterable. You have three common customization goals:

Show a Single Price Instead of a Range

If all your variations cost the same, or you want to hide the range until selection:

add_filter( 'woocommerce_variable_price_html', function( $price, $product ) {
    $prices = $product->get_variation_prices( true );
    $min    = current( $prices['price'] );
    $max    = end( $prices['price'] );

    if ( $min === $max ) {
        return wc_price( $min );
    }
    return $price;
}, 10, 2 );

This returns a single formatted price when min equals max, otherwise falls back to the default range.

Show "From $X" Instead of a Full Range

Useful when you have many tiers but want to emphasize the entry price:

add_filter( 'woocommerce_variable_price_html', function( $price, $product ) {
    $prices = $product->get_variation_prices( true );
    $min    = current( $prices['price'] );
    return sprintf( __( 'From %s', 'your-textdomain' ), wc_price( $min ) );
}, 10, 2 );

Show "Price varies by option selected" Text

For configure-to-order products where any price display before selection is misleading:

add_filter( 'woocommerce_variable_price_html', function( $price, $product ) {
    return '<span class="variable-price-notice">' . __( 'Price varies by option selected', 'your-textdomain' ) . '</span>';
}, 10, 2 );

Place these snippets in your child theme's functions.php or a site-specific plugin. Avoid editing core WooCommerce files directly — updates will overwrite them.


Price Display After Variation Selection: JavaScript Behavior

When a shopper picks a variation, WooCommerce fires the found_variation jQuery event and passes the variation object. The woocommerce-add-to-cart-variation.js script then replaces the price HTML in .woocommerce-variation-price. If this isn't working on your store, check these failure points:

SymptomLikely CauseFix
Price never updates on selectionjQuery conflict or JS errorCheck browser console; ensure jQuery loads before WooCommerce scripts
Price updates but shows blankVariation has no price setAdd a Regular price to every variation
Price updates to $0.00Sale price set to 0 or empty stringSet sale price to blank (null), not "0"
Range reappears after deselectionExpected behaviorCustomize with $('.reset_variations') handler
Price doesn't update with swatchesSwatches plugin bypasses native select eventsVerify plugin triggers change on the underlying <select>

This last row is especially important if you're using a variation swatches implementation — see our WooCommerce Variation Swatches implementation guide for how to verify that native WooCommerce price-update events still fire correctly after replacing dropdowns with visual buttons.


Recalculating the Variation Price Cache

WooCommerce caches min/max prices on the parent product to avoid calculating them on every page load. This cache becomes stale when:

  • You update variation prices programmatically without calling sync()
  • You import products via CSV or a plugin that doesn't trigger WooCommerce hooks
  • You delete or add variations

To force recalculation on a single product:

$product = wc_get_product( $product_id );
if ( $product->is_type( 'variable' ) ) {
    WC_Product_Variable::sync( $product );
}

To recalculate all variable products (run once via WP-CLI or a one-time script):

$variable_products = wc_get_products([
    'type'   => 'variable',
    'limit'  => -1,
    'return' => 'ids',
]);

foreach ( $variable_products as $id ) {
    WC_Product_Variable::sync( $id );
}

On large catalogs, run this in batches of 50–100 with sleep(1) between iterations to avoid overwhelming the database. If you're on managed hosting with WP-CLI access, this is the cleanest approach — no GUI required.


Displaying Variation Prices on Shop/Archive Pages

By default, WooCommerce archive pages (shop, category, search results) show the parent product's price range using the same cached values. The loop template calls $product->get_price_html() which returns the range.

If you want archive pages to behave differently — for example, only showing the minimum price with a "from" prefix — hook into woocommerce_variable_price_html as shown earlier. That filter applies globally, so archive and single product pages are both affected.

To target only archive pages:

add_filter( 'woocommerce_variable_price_html', function( $price, $product ) {
    if ( ! is_singular( 'product' ) ) {
        $prices = $product->get_variation_prices( true );
        $min    = current( $prices['price'] );
        return sprintf( __( 'From %s', 'your-textdomain' ), wc_price( $min ) );
    }
    return $price;
}, 10, 2 );

WooCommerce HPOS and Variation Pricing Compatibility

If you've migrated to High-Performance Order Storage, variation pricing itself is unaffected — prices are stored on product meta, not order tables. However, if your pricing logic queries order history (dynamic pricing by purchase count, loyalty tiers, etc.), verify your queries use wc_get_orders() instead of direct $wpdb calls on wp_posts. See our WooCommerce HPOS migration guide for a full compatibility checklist.


Plugin vs Custom Code: When to Use Each

ApproachBest ForRisk
woocommerce_variable_price_html filterSimple format changesLow — pure filter, no DB writes
WooCommerce built-in bulk editUpdating prices in adminLow
Programmatic sync via WC_Product_Variable::sync()Imports, bulk CLI updatesMedium — test on staging first
A pricing plugin (e.g. WooCommerce Dynamic Pricing)Tiered, role-based, quantity pricingHigher — adds queries per request
Theme override of single-product/price.phpLayout restructuringMedium — breaks on theme updates without child theme

For most display customizations, a filter in a site plugin is the right call. Plugins that add dynamic pricing rules introduce per-request database overhead — benchmark their impact on your product pages using Query Monitor before enabling on production.

If you need to temporarily take the store offline while you apply bulk pricing changes, the WooCommerce store maintenance mode guide covers how to do that without breaking SEO or losing in-flight orders.


Testing Variation Price Changes Safely

Variation price changes — especially bulk recalculations or filter modifications — should always be validated on staging before hitting production. Things to verify:

  1. Range display — Does the parent product show the correct min/max on shop and single product pages?
  2. Selection update — Does selecting each variation update the displayed price correctly?
  3. Sale price logic — Are strikethrough prices (<del>) appearing only where expected?
  4. Archive pages — Does the loop display match your intended format?
  5. JavaScript errors — Open the browser console and trigger variation selection; confirm no JS errors.
  6. Caching layer — Purge page cache and object cache after changes, then retest. Cached HTML containing old prices will persist until purged.

TopSyde managed WooCommerce hosting includes one-click staging environments on every plan starting at $89/month — see our hosting plans and pricing for details. For stores running complex pricing logic, review our WooCommerce hosting for ecommerce stores article, which covers the infrastructure requirements that prevent pricing-related slowdowns at scale.


Frequently Asked Questions

Why does my WooCommerce variable product show $0 in the price range?

A $0 in the range means at least one variation has its Regular price set to 0 or left blank but treated as 0 by WooCommerce. Open the Variations tab, sort by price, and find any variation without a Regular price set. Either add a price or set the variation to "Draft" status if it shouldn't be purchasable. After fixing, run WC_Product_Variable::sync() to refresh the cached range.

How do I stop the price from showing a range and just show the lowest price?

Use the woocommerce_variable_price_html filter to intercept the default range HTML and return a formatted single price using wc_price( current( $product->get_variation_prices()['price'] ) ). Optionally prefix it with "From" for clarity. This approach requires no plugin and has no performance overhead since it only modifies the output string, not the underlying data.

Why doesn't the price update when a customer selects a variation?

The most common causes are a JavaScript conflict that prevents woocommerce-add-to-cart-variation.js from initializing, a page caching plugin serving stale HTML that strips the variation JSON payload, or a swatches plugin that replaces native <select> elements without triggering WooCommerce's change event listeners. Check the browser console for JS errors first, then disable caching temporarily to isolate the cause.

Does changing the price range display format affect SEO or structured data?

The filter woocommerce_variable_price_html only changes the visible HTML price string. WooCommerce outputs structured data (Schema.org Product with offers) separately — it uses the raw price values from the database, not the filtered display HTML. Changing your display format will not affect how Google reads your product prices in rich results.

How often does WooCommerce recalculate the min/max price cache?

WooCommerce recalculates the cached min/max on save when a variation or the parent product is updated through the admin. It does not automatically recalculate on a schedule. If you update prices via direct database writes, WP-CLI scripts, or import plugins that bypass WooCommerce hooks, you must call WC_Product_Variable::sync() manually to keep the displayed range accurate.

Elena Marchetti
Elena Marchetti

Content & SEO Strategist

7+ years SEO & content strategy, Google Analytics certified

Elena drives content strategy and SEO at TopSyde, helping clients maximize organic visibility and AI search presence. She combines technical WordPress knowledge with data-driven content optimization.

Related Articles

View all →

Stop managing your WordPress site

Let our team handle hosting, speed, security, and updates — so you can focus on what matters.

Get Started Free