Fast load times are critical for e-commerce success. In this article, we show how to optimize Core Web Vitals to achieve better Google rankings and higher conversion rates.
// Measuring Largest Contentful Paint (LCP)
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('LCP:', entry.startTime);
}
}).observe({entryTypes: ['largest-contentful-paint']});
// Measuring First Input Delay (FID)
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('FID:', entry.processingStart - entry.startTime);
}
}).observe({entryTypes: ['first-input']});
// Measuring Cumulative Layout Shift (CLS)
let clsValue = 0;
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
clsValue += entry.value;
}
}
console.log('CLS:', clsValue);
}).observe({entryTypes: ['layout-shift']});
We measure the three key Core Web Vitals using JavaScript.
<picture>
<source srcset="product-image.webp" type="image/webp">
<source srcset="product-image.avif" type="image/avif">
<img src="product-image.jpg"
alt="Product image"
loading="lazy"
width="400"
height="300">
</picture>
We use modern image formats and lazy loading for product images.
img {
aspect-ratio: 4/3;
object-fit: cover;
width: 100%;
height: auto;
}
/* Placeholder for Lazy Loading */
img[loading="lazy"] {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: loading 1.5s infinite;
}
@keyframes loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
With CSS, we ensure optimal display and a loading animation.
<!-- Inline Critical CSS -->
<style>
/* Above-the-fold Styles */
.header, .hero, .product-grid {
/* Critical styles here */
}
</style>
<!-- Load non-critical CSS asynchronously -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>
We load critical CSS inline and non-critical CSS asynchronously.
// JavaScript Modules for Better Performance
import { initCart } from './modules/cart.js';
import { initSearch } from './modules/search.js';
// Lazy Loading for Non-Critical Features
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// Load product reviews only when needed
import('./modules/reviews.js').then(module => {
module.initReviews(entry.target);
});
}
});
});
document.querySelectorAll('.product-reviews').forEach(el => {
observer.observe(el);
});
Implement JavaScript modules and lazy loading for non-critical features.
// Service Worker for Caching
const CACHE_NAME = 'ecommerce-v1';
const urlsToCache = [
'/css/critical.css',
'/js/app.js',
'/images/logo.webp'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(urlsToCache))
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => {
// Cache hit - return response
if (response) {
return response;
}
return fetch(event.request);
}
)
);
});
A Service Worker caches important resources for better performance.
<?php
// Set HTTP Cache Headers
header('Cache-Control: public, max-age=31536000'); // 1 year for static assets
header('ETag: "' . md5_file($filename) . '"');
// Enable Gzip Compression
if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) {
ob_start('ob_gzhandler');
} else {
ob_start();
}
// Browser Caching for Different File Types
$extension = pathinfo($_SERVER['REQUEST_URI'], PATHINFO_EXTENSION);
switch ($extension) {
case 'css':
case 'js':
header('Cache-Control: public, max-age=31536000');
break;
case 'jpg':
case 'jpeg':
case 'png':
case 'webp':
header('Cache-Control: public, max-age=2592000'); // 30 days
break;
}
Configure HTTP cache headers and Gzip compression in PHP.
-- Create indexes for frequent queries
CREATE INDEX idx_products_category_price ON products(category_id, price);
CREATE INDEX idx_products_featured ON products(is_featured, created_at);
-- Optimized product query with pagination
SELECT p.id, p.name, p.price, p.image_url, c.name as category_name
FROM products p
JOIN categories c ON p.category_id = c.id
WHERE p.is_active = 1
AND p.category_id = ?
ORDER BY p.created_at DESC
LIMIT 20 OFFSET ?;
Database indexes and optimized queries for better performance.
<?php
// Redis for Product Caching
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
function getProducts($categoryId, $page = 1) {
global $redis;
$cacheKey = "products:category:{$categoryId}:page:{$page}";
// Load from cache
$cached = $redis->get($cacheKey);
if ($cached) {
return json_decode($cached, true);
}
// Load from database
$products = loadProductsFromDB($categoryId, $page);
// Store in cache (5 minutes)
$redis->setex($cacheKey, 300, json_encode($products));
return $products;
}
Implement Redis caching for database queries.
<!-- DNS Prefetch for External Domains -->
<link rel="dns-prefetch" href="//fonts.googleapis.com">
<link rel="dns-prefetch" href="//cdn.example.com">
<!-- Preload Critical Resources -->
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/css/critical.css" as="style">
<link rel="preload" href="/js/app.js" as="script">
<!-- Preload Hero Image -->
<link rel="preload" href="/images/hero-product.webp" as="image">
<!-- Prefetch Next Page -->
<link rel="prefetch" href="/product-category/electronics">
Resource hints optimize load times through intelligent preloading.
// Intersection Observer for Intelligent Prefetching
const prefetchObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const link = entry.target;
const url = link.getAttribute('href');
// Prefetch only with fast connection
if (navigator.connection &&
navigator.connection.effectiveType === '4g') {
const prefetchLink = document.createElement('link');
prefetchLink.rel = 'prefetch';
prefetchLink.href = url;
document.head.appendChild(prefetchLink);
}
}
});
});
// Observe all product links for prefetching
document.querySelectorAll('.product-link').forEach(link => {
prefetchObserver.observe(link);
});
Intelligent prefetching based on connection speed.
With these optimizations, you can significantly improve your e-commerce shop’s Core Web Vitals. Fast load times lead not only to better Google rankings but also to higher conversion rates and happier customers. Monitor performance regularly and continue optimizing.
Core Web Vitals are three key metrics: Largest Contentful Paint (LCP), First Input Delay (FID), and Cumulative Layout Shift (CLS). They measure load speed, interactivity, and visual stability.
For optimal Core Web Vitals, LCP should be under 2.5 seconds, FID under 100 milliseconds, and CLS under 0.1.
WebP and AVIF offer the best compression with high quality. Use the picture element for fallback support.
A CDN significantly reduces load times for global visitors. It’s highly recommended for international e-commerce shops.
Use Google PageSpeed Insights, Lighthouse, and Search Console for regular performance analyses.
Service Workers are supported by all modern browsers. Implement them as a progressive enhancement with feature detection.
A fast, stable hosting provider with modern server technologies (e.g., HTTP/2, SSD, caching) greatly impacts load time and reliability, especially with high traffic.
Excessive or poorly optimized JavaScript can significantly slow down load times and interactivity. Reduce third-party scripts, use lazy loading, and minify your code.
Lazy loading only loads images and content when they become visible, saving initial load time and significantly improving Core Web Vitals like LCP.
Assign fixed heights/widths for images, ads, and iframes to prevent layout shifts. Preloading fonts also helps minimize CLS.
Critical CSS contains only the styles needed for the visible area when a page loads. It speeds up rendering and improves LCP.
Use the advanced WYSIWYG editor in Shopware 6. This editor enables easy embedding of media in descriptions and many additional features.
ab 7.99 €* / Month
Rent PluginOptimize your shop to create a better experience for your customers. This plugin minimizes your shop’s loading time and offers numerous configuration options.
ab 27.49 €* / Month
Rent PluginQuickly and easily create and edit your own template extensions in the administration. Displays existing storefront template paths and contents.
ab 3.99 €* / Month
Rent PluginNote: * All prices are exclusive of VAT
x