← Back to Blog

WooCommerce Badges Not Showing in Block Themes? Here's Why and How to Fix It

Product badges disappear in block themes like Twenty Twenty-Five because WooCommerce Blocks bypass PHP hooks. Learn why this happens, which plugins are affected, and 3 ways to fix it.

March 5, 2026 · 5 min read

You just switched your WooCommerce store to a modern block theme — Twenty Twenty-Five, Flavor, Flavor Dark, or Flavor flavor. Everything looks great, except your product badges have disappeared.

No “Sale” labels. No “New” tags. Nothing.

You check the plugin settings — badges are still active. You switch back to your old theme — badges reappear. What’s going on?

This is one of the most common compatibility issues with WooCommerce block themes, and it affects most badge plugins on the market. Here’s why it happens and how to fix it.

Why Badges Disappear in Block Themes

Traditional WooCommerce themes (Storefront, Astra, OceanWP) render products using PHP action hooks — specifically:

Badge plugins inject their HTML into these hooks. When WooCommerce fires the hook, the badge appears.

Block themes work differently. Products are rendered by WooCommerce Blocks — React-based components that bypass traditional PHP hooks entirely. The hooks simply never fire, so badges never appear.

This isn’t a bug in any specific plugin — it’s an architectural difference between classic and block-based rendering.

Which Plugins Are Affected?

Most popular badge plugins were built for classic themes and have limited or no support for block themes:

YITH WooCommerce Badge Management — Multiple reports of badges not appearing in block-based layouts. In one support thread, 11 users reported the same issue, and it remains unresolved. YITH support suggested custom PHP hooks as a workaround, but it doesn’t solve the core problem.

Sold Out Badge for WooCommerce — The plugin author explicitly confirmed that the plugin “isn’t compatible with WooCommerce Gutenberg blocks.”

BeRocket Advanced Product Labels — Users migrating to block-based themes like Kadence reported that labels stopped appearing.

The pattern is clear: if a badge plugin relies only on classic WooCommerce hooks, it will break in block themes.

How to Fix It

Option 1: CSS-Only Approach (DIY)

If you just need to restyle the default WooCommerce “Sale!” badge, CSS works in both classic and block themes:

/* Override default sale badge */
.wc-block-components-product-sale-badge,
.onsale {
    background: linear-gradient(135deg, #e53935, #d32f2f) !important;
    color: #fff !important;
    font-size: 12px !important;
    font-weight: 700 !important;
    padding: 4px 10px !important;
    border-radius: 4px !important;
    text-transform: uppercase !important;
    letter-spacing: 0.5px !important;
}

Pros: Zero dependencies, works everywhere. Cons: Only works for the default “Sale” badge. You can’t add “New”, “Low Stock”, or custom badges with CSS alone — those require product-level logic.

Option 2: Custom Code with render_block Filter

The correct way to inject badges into block-rendered products is to filter the block output HTML rather than relying on classic hooks:

add_filter('render_block', function($block_content, $block) {
    if ($block['blockName'] !== 'woocommerce/product-image') {
        return $block_content;
    }
    
    // Get the product context
    $product_id = $block['attrs']['productId'] ?? null;
    if (!$product_id) {
        return $block_content;
    }
    
    $product = wc_get_product($product_id);
    if (!$product) {
        return $block_content;
    }
    
    $badge_html = '';
    
    // "Sale" badge
    if ($product->is_on_sale()) {
        $badge_html .= '<span class="custom-badge sale-badge">SALE</span>';
    }
    
    // "New" badge (published within last 30 days)
    $created = $product->get_date_created();
    if ($created) {
        $days = (time() - $created->getTimestamp()) / DAY_IN_SECONDS;
        if ($days <= 30) {
            $badge_html .= '<span class="custom-badge new-badge">NEW</span>';
        }
    }
    
    if (!$badge_html) {
        return $block_content;
    }
    
    // Inject badge into the block HTML
    return '<div style="position:relative;">' . $badge_html . $block_content . '</div>';
}, 10, 2);

Add the CSS:

.custom-badge {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 10;
    padding: 4px 10px;
    font-size: 12px;
    font-weight: 700;
    color: #fff;
    border-radius: 4px;
    line-height: 1.4;
}

.sale-badge {
    background: linear-gradient(135deg, #e53935, #d32f2f);
}

.new-badge {
    background: linear-gradient(135deg, #4ade80, #22c55e);
    top: 8px;
    left: auto;
    right: 8px;
}

Pros: Works with both block and classic themes, uses the correct WordPress API. Cons: Requires code maintenance, no admin UI, need to handle edge cases (variable products, caching, multiple badges).

Option 3: Use a Plugin That Supports Block Themes

Some plugins already use the render_block approach internally:

When evaluating a badge plugin, check for these indicators of block theme support:

  1. Does the plugin page mention “block themes” or “WooCommerce Blocks”?
  2. Is Twenty Twenty-Five listed as a compatible theme?
  3. Does the support forum have unresolved block theme issues?

The Technical Details

For developers who want to understand the full picture:

Classic Theme Rendering

PHP Template → woocommerce_before_shop_loop_item_title hook → Badge Plugin injects HTML → Browser renders

The plugin hooks into the template lifecycle. Direct, simple, reliable.

Block Theme Rendering

Block Editor → React Component → Server-Side Render → HTML String → Browser renders

No PHP hooks fire during block rendering. The only interception point is the render_block filter, which receives the final HTML string and lets you modify it before output.

What render_block Looks Like

WordPress calls render_block for every block on the page. A badge plugin needs to:

  1. Identify woocommerce/product-image blocks
  2. Extract the product ID from the block context
  3. Evaluate badge rules against the product
  4. Parse the HTML to find the correct injection point
  5. Insert badge markup
  6. Return modified HTML

This is more complex than classic hooks but it’s the only reliable approach for block themes.

Summary

Method Classic Themes Block Themes Effort
CSS override Low (sale badge only)
Classic PHP hooks Medium
render_block filter High
Plugin with block support Low

If your badges stopped working after switching to a block theme, you’re not alone — it’s an architectural limitation that affects most plugins. The render_block filter is the correct solution, whether you implement it yourself or choose a plugin that does it for you.

WordPress is moving toward block themes as the default. If you’re choosing a badge plugin today, make sure it works with the theme architecture you’ll be using tomorrow.

Published by CartEngine. We build lightweight WooCommerce tools that actually work.

More Articles