Fix WooCommerce LCP Issues | OpsBlu Docs

Fix WooCommerce LCP Issues

Speed up WooCommerce LCP by optimizing product images, disabling cart fragments AJAX, tuning database queries, and enabling object caching.

Largest Contentful Paint (LCP) measures how long it takes for the main content to load. WooCommerce stores often struggle with LCP due to product images, cart fragments AJAX, database queries, and heavy themes. This guide provides WooCommerce-specific solutions.

What is LCP?

LCP is a Core Web Vital that measures when the largest visible content element renders.

Thresholds:

  • Good: < 2.5 seconds
  • Needs Improvement: 2.5 - 4.0 seconds
  • Poor: > 4.0 seconds

Common LCP Elements on WooCommerce:

  • Product images (single product pages)
  • Hero images (homepage featured products)
  • Product gallery images
  • Category banners
  • Large product descriptions

Measuring WooCommerce LCP

Google PageSpeed Insights

  1. Go to PageSpeed Insights
  2. Test key pages:
    • Homepage
    • Product pages
    • Category pages
    • Cart page
  3. View Largest Contentful Paint metric
  4. Check Diagnostics for WooCommerce-specific issues

Chrome DevTools

// View LCP in browser console
new PerformanceObserver((list) => {
    const entries = list.getEntries();
    const lastEntry = entries[entries.length - 1];
    console.log('LCP:', lastEntry.renderTime || lastEntry.loadTime);
    console.log('LCP element:', lastEntry.element);
}).observe({entryTypes: ['largest-contentful-paint']});

Common WooCommerce LCP Issues

1. WooCommerce Cart Fragments AJAX

Symptoms:

  • High Time to Interactive (TTI)
  • LCP delayed by cart fragment loading
  • Slow homepage/product pages

What are Cart Fragments?

WooCommerce refreshes cart data via AJAX on every page load:

// Cart fragments fire immediately on page load
// Blocks rendering until complete
wc_cart_fragments_params.ajax_url

Solutions:

Option 1: Disable Cart Fragments on Non-Shop Pages

// Disable cart fragments where not needed
add_action('wp_enqueue_scripts', 'conditionally_disable_cart_fragments', 999);
function conditionally_disable_cart_fragments() {
    // Keep cart fragments only on shop pages
    if (!is_woocommerce() && !is_cart() && !is_checkout()) {
        wp_dequeue_script('wc-cart-fragments');
        return;
    }
}

Option 2: Defer Cart Fragment Loading

// Delay cart fragments until after LCP
add_action('wp_footer', 'defer_cart_fragments', 999);
function defer_cart_fragments() {
    ?>
    <script>
        // Delay cart fragment refresh
        if (typeof wc_cart_fragments_params !== 'undefined') {
            jQuery(document).ready(function($) {
                // Wait 2 seconds before refreshing cart
                setTimeout(function() {
                    $(document.body).trigger('wc_fragment_refresh');
                }, 2000);
            });
        }
    </script>
    <?php
}

Option 3: Increase Cart Fragment Cache Duration

// Extend cart fragment cache
add_filter('woocommerce_cart_fragment_refresh', 'extend_cart_fragment_cache');
function extend_cart_fragment_cache($refresh) {
    // Only refresh on cart/checkout pages
    if (!is_cart() && !is_checkout()) {
        return false;
    }
    return $refresh;
}

// Increase session expiration
add_filter('wc_session_expiration', 'extend_cart_session');
function extend_cart_session($expiration) {
    return DAY_IN_SECONDS * 7; // 7 days instead of default 2
}

2. Unoptimized Product Images

Symptoms:

  • Large product images (> 500 KB)
  • LCP element is product image
  • Slow product gallery loading

Solutions:

Use WebP Format

// Force WebP for product images
add_filter('wp_generate_attachment_metadata', 'convert_product_images_to_webp', 10, 2);
function convert_product_images_to_webp($metadata, $attachment_id) {
    // Use plugin like ShortPixel or Imagify for automatic WebP conversion
    return $metadata;
}

Recommended Plugins:

  • ShortPixel - Automatic WebP conversion
  • Imagify - WebP with lazy load
  • EWWW Image Optimizer - Free WebP support

Optimize Product Image Sizes

// Define optimal product image sizes
add_action('after_setup_theme', 'optimize_woocommerce_image_sizes');
function optimize_woocommerce_image_sizes() {
    // Single product image (main)
    update_option('woocommerce_single_image_width', 800);

    // Thumbnail size
    update_option('woocommerce_thumbnail_image_width', 300);

    // Gallery thumbnail
    update_option('woocommerce_gallery_thumbnail_image_width', 150);

    // Disable hard crop for better file sizes
    update_option('woocommerce_thumbnail_cropping', 'custom');
    update_option('woocommerce_thumbnail_cropping_custom_width', 4);
    update_option('woocommerce_thumbnail_cropping_custom_height', 3);
}

// Regenerate thumbnails after changing sizes
// Use Regenerate Thumbnails plugin or WP-CLI:
// wp media regenerate --only-missing

Exclude LCP Image from Lazy Loading

// Don't lazy load the main product image (LCP element)
add_filter('wp_lazy_loading_enabled', 'disable_lazy_load_product_image', 10, 2);
function disable_lazy_load_product_image($default, $tag_name) {
    // Disable on single product pages for main image
    if ('img' === $tag_name && is_product()) {
        global $wp_query;
        static $first_image = true;

        if ($first_image) {
            $first_image = false;
            return false; // Don't lazy load first image
        }
    }
    return $default;
}

Preload LCP Image

// Preload main product image for faster LCP
add_action('wp_head', 'preload_product_image', 1);
function preload_product_image() {
    if (is_product()) {
        global $product;
        $image_id = $product->get_image_id();
        if ($image_id) {
            $image_url = wp_get_attachment_image_url($image_id, 'woocommerce_single');
            $image_webp = str_replace(array('.jpg', '.jpeg', '.png'), '.webp', $image_url);

            // Preload WebP with JPEG fallback
            ?>
            <link rel="preload" as="image" href="<?php echo esc_url($image_webp); ?>" type="image/webp">
            <link rel="preload" as="image" href="<?php echo esc_url($image_url); ?>" type="image/jpeg">
            <?php
        }
    }
}

Add fetchpriority="high" to Product Images

// Mark product image as high priority
add_filter('woocommerce_single_product_image_thumbnail_html', 'add_fetchpriority_to_product_image', 10, 2);
function add_fetchpriority_to_product_image($html, $attachment_id) {
    // Add fetchpriority="high" and loading="eager" to main product image
    $html = str_replace('<img', '<img fetchpriority="high" loading="eager"', $html);
    return $html;
}

3. Slow Database Queries

Symptoms:

  • High Time to First Byte (TTFB > 600ms)
  • Slow product page loads
  • Category pages take long to render

Common Slow Queries:

  • Product meta lookups
  • Category queries
  • Related products
  • Cross-sells/upsells
  • Product reviews

Solutions:

Enable Object Caching (Redis/Memcached)

// wp-config.php
define('WP_CACHE_KEY_SALT', 'yoursite.com');
define('WP_CACHE', true);

// Install Redis Object Cache plugin or Memcached plugin
// This dramatically improves WooCommerce query performance
// Reduce related products queries
add_filter('woocommerce_output_related_products_args', 'optimize_related_products');
function optimize_related_products($args) {
    $args['posts_per_page'] = 3; // Reduce from default
    return $args;
}

// Or disable related products entirely if not needed
remove_action('woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);

Optimize Product Reviews

// Limit reviews loaded initially
add_filter('woocommerce_product_review_list_args', 'limit_product_reviews');
function limit_product_reviews($args) {
    $args['number'] = 5; // Show only 5 reviews initially
    return $args;
}

// Lazy load additional reviews
add_action('woocommerce_after_product_reviews', 'add_load_more_reviews_button');
function add_load_more_reviews_button() {
    echo '<button id="load-more-reviews">Load More Reviews</button>';
}

Index WooCommerce Tables

-- Add indexes to improve query performance
-- Run via phpMyAdmin or WP-CLI

-- Index product meta
ALTER TABLE wp_postmeta
ADD INDEX meta_key_value (meta_key(191), meta_value(100));

-- Index product lookup table
ALTER TABLE wp_wc_product_meta_lookup
ADD INDEX stock_status (stock_status);

4. Slow Server Response (TTFB)

Symptoms:

  • TTFB > 600ms
  • Slow across all WooCommerce pages
  • Database queries taking too long

Solutions:

Upgrade Hosting

WooCommerce-Optimized Hosts:

  • WP Engine - Managed WordPress with WooCommerce optimization
  • Kinsta - Google Cloud, excellent TTFB
  • SiteGround - WooCommerce hosting plan
  • Cloudways - Flexible managed hosting

Enable Page Caching

// Exclude dynamic WooCommerce pages from caching
// For WP Rocket:
add_filter('rocket_cache_reject_uri', 'exclude_woocommerce_from_cache');
function exclude_woocommerce_from_cache($uri) {
    // Don't cache cart/checkout/account
    $uri[] = '/cart/';
    $uri[] = '/checkout/';
    $uri[] = '/my-account/';
    return $uri;
}

// Cache product pages and categories
add_filter('rocket_cache_dynamic_cookies', 'cache_woocommerce_product_pages');
function cache_woocommerce_product_pages($cookies) {
    // Allow caching if cart is empty
    return array_diff($cookies, ['woocommerce_items_in_cart']);
}

Optimize WooCommerce Database

// Install WP-Optimize plugin
// Or run manual optimizations:
// 1. Delete transients
// 2. Clean up orphaned post meta
// 3. Optimize database tables

5. Render-Blocking Resources

Symptoms:

  • Multiple CSS/JS files blocking render
  • WooCommerce scripts loading in header
  • Third-party scripts delaying LCP

Solutions:

Defer Non-Critical WooCommerce Scripts

// Defer WooCommerce scripts
add_filter('script_loader_tag', 'defer_woocommerce_scripts', 10, 2);
function defer_woocommerce_scripts($tag, $handle) {
    // Scripts safe to defer
    $defer_scripts = array(
        'wc-cart-fragments',
        'woocommerce',
        'wc-add-to-cart',
        'wc-add-to-cart-variation'
    );

    if (in_array($handle, $defer_scripts)) {
        return str_replace(' src', ' defer src', $tag);
    }
    return $tag;
}

Remove Unused WooCommerce Assets

// Disable WooCommerce assets on non-shop pages
add_action('wp_enqueue_scripts', 'remove_woocommerce_assets', 99);
function remove_woocommerce_assets() {
    if (!is_woocommerce() && !is_cart() && !is_checkout()) {
        // Dequeue WooCommerce styles
        wp_dequeue_style('woocommerce-general');
        wp_dequeue_style('woocommerce-layout');
        wp_dequeue_style('woocommerce-smallscreen');

        // Dequeue WooCommerce scripts
        wp_dequeue_script('wc-cart-fragments');
        wp_dequeue_script('woocommerce');
        wp_dequeue_script('wc-add-to-cart');
    }
}

Critical CSS for WooCommerce

/* Inline critical CSS for above-the-fold WooCommerce content */
/* Add to wp_head with high priority */
.woocommerce-product-gallery {
    max-width: 800px;
}
.product .price {
    font-size: 24px;
    color: #000;
}
.single_add_to_cart_button {
    background: #000;
    color: #fff;
    padding: 12px 24px;
}
// Inline critical WooCommerce CSS
add_action('wp_head', 'inline_critical_woocommerce_css', 1);
function inline_critical_woocommerce_css() {
    if (is_product()) {
        ?>
        <style>
            /* Inline critical product page CSS here */
            .woocommerce-product-gallery { max-width: 800px; }
            /* ... more critical CSS */
        </style>
        <?php
    }
}

6. Heavy Theme/Page Builder

Symptoms:

  • Large CSS/JS payload
  • Unused theme features loading
  • Page builder overhead

Solutions:

Switch to Lightweight Theme

WooCommerce-Optimized Themes:

  • Astra - Fast, WooCommerce ready
  • GeneratePress - Lightweight, modular
  • Kadence - Performance-focused
  • Storefront - Official WooCommerce theme

Disable Unused Theme Features

// Disable unused Elementor/Divi features
add_action('wp_enqueue_scripts', 'remove_page_builder_bloat', 999);
function remove_page_builder_bloat() {
    // Example for Elementor
    if (!is_page('custom-page-with-elementor')) {
        wp_dequeue_style('elementor-frontend');
        wp_dequeue_script('elementor-frontend');
    }
}

WooCommerce-Specific LCP Optimizations

// Disable WooCommerce gallery zoom/lightbox if not needed
add_action('after_setup_theme', 'disable_woocommerce_gallery_features');
function disable_woocommerce_gallery_features() {
    remove_theme_support('wc-product-gallery-zoom');
    remove_theme_support('wc-product-gallery-lightbox');
    remove_theme_support('wc-product-gallery-slider');
}

Optimize Variable Products

// Reduce variation data loaded
add_filter('woocommerce_ajax_variation_threshold', 'reduce_variation_threshold', 10, 2);
function reduce_variation_threshold($qty, $product) {
    return 10; // Load variations via AJAX if more than 10
}

Preconnect to External Domains

// Preconnect to payment gateway, CDN, etc.
add_action('wp_head', 'woocommerce_preconnect_domains', 1);
function woocommerce_preconnect_domains() {
    ?>
    <link rel="preconnect" href="https://cdn.example.com">
    <link rel="preconnect" href="https://payment-gateway.com">
    <?php
}

Testing LCP Improvements

Before and After Comparison

  1. Measure baseline LCP

    • Test with PageSpeed Insights
    • Record LCP time and element
  2. Apply optimizations

    • Implement solutions one at a time
    • Test after each change
  3. Re-measure LCP

    • Verify improvement
    • Ensure no regressions in other metrics

Tools for Testing

  • PageSpeed Insights - Lab and field data
  • WebPageTest - Detailed waterfall
  • Chrome DevTools Performance Tab - Local testing
  • GTmetrix - Historical tracking

Common Mistakes to Avoid

  1. Lazy loading LCP image - Never lazy load your main product image
  2. Too many cart fragment calls - Limit or defer cart fragments
  3. Ignoring image optimization - Always use WebP and proper sizing
  4. No object caching - Essential for WooCommerce database performance
  5. Caching dynamic pages - Don't cache cart/checkout
  6. Loading all product images eagerly - Only prioritize LCP image

Next Steps