Skip to content
Home » Articles » Fix JavaScript-Only Image Loading in WooCommerce for 2026

Fix JavaScript-Only Image Loading in WooCommerce for 2026

Intro

JavaScript-only image loading in WordPress WooCommerce stores is a real SEO problem in 2026 because product thumbnails, gallery images, and category banners often exist only after front-end scripts run. When Googlebot or other crawlers do not see usable image markup in the initial HTML, image indexing drops, product listing pages look thin, and Google Images traffic can disappear.

For WooCommerce, this usually happens after aggressive lazy-loading plugins, custom theme JavaScript, headless-style gallery scripts, or slider libraries replace normal `img` tags with `data-src`, JSON blobs, or background images. The fix is not to remove performance optimization entirely. The goal is to ship crawlable image HTML first, then layer JavaScript enhancements on top. If you also manage media performance, review web image performance in 2026 and installing Imagick for PHP 8.3 on Ubuntu 24.

Prerequisites

What you need is a current WooCommerce stack and access to inspect rendered and raw HTML, because this issue is usually caused by theme or optimization-layer output rather than the media library itself.

  • WordPress 6.8 or newer
  • WooCommerce 9.8 or newer
  • PHP 8.2 or 8.3
  • A block theme or classic theme with access to `functions.php` or a site-specific plugin
  • Admin access to caching, CDN, and performance plugins
  • SSH or hosting file manager access
  • Chrome or Chromium DevTools
  • Optional: WP-CLI 2.10+
ComponentRecommended VersionWhy It Matters
WordPress6.8+Core loading attributes and image functions are stable
WooCommerce9.8+Product gallery output is current and predictable
PHP8.2 or 8.3Compatible with modern WooCommerce builds
WP-CLI2.10+Useful for plugin checks and cache-related workflows

Installation / Setup

What you need to do first is identify whether JavaScript-only image loading is coming from the theme, a performance plugin, or a front-end component, because the fix changes depending on where the markup is altered.

Start by viewing the raw page source of a product archive and a single product page. Do not inspect the live DOM first. You want the server-delivered HTML.

curl -L https://example.com/shop/ | grep -iE "img|data-src|background-image" | head -n 30

Expected output should include real image tags with `src` values, not only `data-src` or script-generated placeholders.

<img width="600" height="600" src="https://example.com/wp-content/uploads/2026/04/product-a.webp" ...>

If you only see patterns like these, the page likely has a JavaScript-only image problem:

<img class="lazyload" data-src="https://example.com/..." src="data:image/gif;base64,...">
<div class="product-image" data-bg="https://example.com/...">

Next, list active plugins if you have shell access.

wp plugin list --status=active

Look closely for lazy-load, optimization, image CDN, slider, and page builder plugins. Common triggers include features that rewrite WooCommerce thumbnails into placeholders until JavaScript hydrates them.

Also inspect related articles if your stack overlaps with nearby image SEO issues, such as fix CDN image indexing issues in WordPress WooCommerce stores and 9 free WordPress media optimization plugins compared.

Configuration

What you need here is a server-rendered fallback for every important WooCommerce image, because crawlers should be able to discover product imagery without waiting for client-side enhancement.

Keep Real `img` Tags In Initial HTML

For product loops, single-product galleries, and related-product sections, make sure WooCommerce outputs standard image tags with a real `src` attribute. A correct baseline looks like this:

<?php
$image_id = get_post_thumbnail_id( $product->get_id() );
echo wp_get_attachment_image(
    $image_id,
    'woocommerce_thumbnail',
    false,
    array(
        'loading'  => 'lazy',
        'decoding' => 'async',
        'class'    => 'attachment-woocommerce_thumbnail size-woocommerce_thumbnail',
    )
);

This matters because `wp_get_attachment_image()` builds proper responsive markup with `src`, `srcset`, sizes, dimensions, and attachment metadata.

Exclude WooCommerce Images From Script-Only Lazy Loading

If a plugin rewrites `src` to `data-src`, exclude WooCommerce selectors from that behavior. Exact settings differ, but typical selectors include:

  • `.woocommerce ul.products img`
  • `.woocommerce div.product img`
  • `.woocommerce-product-gallery__image img`
  • `.related.products img`

If your optimization plugin supports exclusions by class, add a stable class and skip rewrite logic.

<?php
add_filter( 'wp_get_attachment_image_attributes', function( $attr ) {
    if ( ! empty( $attr['class'] ) && strpos( $attr['class'], 'woocommerce' ) !== false ) {
        $attr['class'] .= ' skip-lazy-js';
    }
    return $attr;
}, 20 );

Then place `skip-lazy-js` in the plugin exclusion field.

Avoid CSS Background Images For Primary Product Media

Background images are fine for decoration, but they are weak choices for core commerce visuals. If your shop grid uses this pattern:

<div class="card-media" style="background-image:url('https://example.com/image.webp')"></div>

replace it with semantic image markup. Product images should be discoverable as images, not hidden in CSS declarations.

Preserve Noscript Fallbacks When A Plugin Requires JS Lazy Loading

If you must keep a JavaScript lazy-loading library, add a `noscript` fallback for key commerce templates.

<?php
add_filter( 'post_thumbnail_html', function( $html, $post_id, $thumbnail_id ) {
    if ( is_admin() || ! function_exists( 'is_woocommerce' ) ) {
        return $html;
    }

    if ( is_shop() || is_product_category() || is_product() ) {
        $fallback = wp_get_attachment_image( $thumbnail_id, 'full', false, array( 'loading' => 'eager' ) );
        $html .= '<noscript>' . $fallback . '</noscript>';
    }

    return $html;
}, 10, 3 );

That is not the cleanest long-term fix, but it gives crawlers a usable fallback when a third-party script cannot be removed immediately.

Confirm Thumbnail Sizes And Regeneration State

If image HTML exists but points to missing files, regenerate WooCommerce thumbnails after changing theme image sizes.

wp media regenerate --yes

Minimal expected output:

Success: Regenerated 1842 of 1842 images.

Usage / Execution

What you need now is a repeatable remediation workflow, because the right fix is verified by HTML output and crawlability, not by whether images appear visually in your browser.

Step 1: Test Raw HTML On Key Templates

Check these page types:

  1. Shop archive
  2. Product category archive
  3. Single product page
  4. Related products block

Use curl or View Source, not only DevTools Elements after scripts run.

curl -L https://example.com/product/sample-product/ | sed -n '1,220p'

Look for:

  • Real `img src="https://…"`
  • Real width and height attributes
  • Useful `srcset` output
  • Alt text on product images
  • No placeholder-only GIF data URIs for primary images

Step 2: Disable The Offending Rewrite Layer

Temporarily disable one performance feature at a time:

  • Lazy loading replacement
  • Defer JS image module
  • Image CDN URL rewrite
  • Slider/gallery hydration
  • Infinite scroll thumbnail replacement

If you use WP-CLI, you can test by deactivating a suspected plugin in staging.

wp plugin deactivate plugin-slug

Then purge all caches:

wp cache flush

If you also use a host cache or CDN, purge those layers before re-testing.

Step 3: Reintroduce Performance Features Safely

Use native browser lazy loading where possible instead of JavaScript-only swaps. A good WooCommerce image should still have:

  • `src`
  • `srcset`
  • `sizes`
  • `loading="lazy"` where appropriate
  • `decoding="async"`

A safe example output is:

<img src="https://example.com/wp-content/uploads/2026/04/shoe-blue-600x600.webp" srcset="https://example.com/wp-content/uploads/2026/04/shoe-blue-300x300.webp 300w, https://example.com/wp-content/uploads/2026/04/shoe-blue-600x600.webp 600w" sizes="(max-width: 600px) 100vw, 600px" loading="lazy" decoding="async" alt="Blue running shoe">

Step 4: Verify With Rich Checks

After the fix, validate both crawl and UX signals.

CheckGood ResultBad Result
View SourceReal image URLs presentOnly `data-src` or JS templates
DevTools NetworkProduct images requested normallyImages appear only after JS event chain
Image Search VisibilityProduct images begin indexingImage indexing remains flat
Category Page HTMLThumbnails visible in sourceEmpty wrappers or CSS backgrounds only

Step 5: Tighten Supporting Image SEO

Once the crawlability issue is fixed, make supporting improvements that help WooCommerce image performance and relevance:

  • Add descriptive alt text to product media
  • Keep filenames readable before upload
  • Use WebP or AVIF where compatible
  • Maintain stable canonical product URLs
  • Keep category pages internally linked

For adjacent cleanup, see best WordPress SEO plugins for agencies in 2026 if you are comparing plugin stacks.

Troubleshooting

What you need here is to separate similar-looking failures, because JavaScript-only image loading is often confused with CDN, cache, or theme bugs.

Images Appear In Browser But Not In Page Source

This usually means JavaScript is injecting images after hydration. The common causes are lazy-load rewrites, React-like gallery scripts, and slider libraries.

Fixes:

  • Restore server-rendered `img` output
  • Disable `data-src` rewriting for WooCommerce selectors
  • Add `noscript` fallback while migrating away from the script-only pattern

Product Grid Uses CSS Backgrounds Instead Of Images

Themes sometimes render catalog cards as clickable blocks with background images for layout convenience. That is poor for image SEO and accessibility.

Fixes:

  • Replace background-image cards with semantic `img` tags
  • Keep backgrounds only for decorative overlays
  • Ensure product links wrap the image rather than replacing it with CSS art direction

Cached HTML Still Serves Broken Placeholder Markup

You may fix the PHP template and still see placeholder output because page cache, object cache, or CDN edge cache keeps the old HTML.

Fixes:

wp cache flush

Then purge any host cache and CDN cache. Re-test using curl with a cache-bypass query if needed.

curl -L "https://example.com/shop/?nocache=1" | grep -i "img"

WooCommerce Gallery Plugin Overrides Core Markup

Some gallery, zoom, and variation-image plugins replace WooCommerce markup with script templates. That is common after plugin updates.

Fixes:

  • Switch temporarily to Storefront or a default theme in staging
  • Disable the gallery extension
  • Compare source output before and after
  • Keep the extension only if it preserves crawlable base HTML

Conclusion

What matters most is simple: WooCommerce product images must exist as real image elements in the initial HTML, even if JavaScript later enhances zoom, sliders, or lazy loading. If crawlers only see placeholders, CSS backgrounds, or `data-src` without a valid `src`, image SEO suffers and category pages lose search value.

In 2026, the safest pattern is native WordPress image markup first, selective lazy loading second, and JavaScript enhancement last. Audit shop archives, single-product templates, and related-product blocks separately because each one can fail differently. Once your source HTML consistently exposes product media, you can keep most front-end optimizations without sacrificing image indexing or WooCommerce discoverability.