Measure what buyers experience before changing anything
Run your test on a mid-range phone on a mobile connection, and test a product page rather than the homepage. That is the page most visitors land on from search and ads, and it is usually the slowest one you have.
Get two kinds of measurement. A lab test, which you can run repeatedly and use to check whether a change worked, and field data from real visitors, which tells you what is actually happening across the devices and connections your customers use. Lab tests on a fast connection make almost every store look acceptable.
Then identify the specific element that takes longest to appear, which on a product page is nearly always the main product image or the block of text next to it. Knowing which element it is turns speed work from guesswork into a short list.
Record the numbers before you start. Speed projects on WooCommerce involve a lot of changes, and without a baseline you will not know which of them mattered. Test after each significant change rather than after all of them, and test the cart and checkout separately, because those pages cannot be cached the way the rest of the site can.
Hosting and caching do most of the work
The single biggest gain on most WooCommerce stores comes from where it is hosted and whether the right caching layers are switched on. WordPress builds every page with database queries, and WooCommerce adds many more.
The layers that matter: a page cache that serves finished pages to visitors who are not logged in and have nothing in their cart, which handles the majority of your traffic. An object cache, which stops repeated database queries being run over and over. An up-to-date version of the language the platform runs on, which is a setting on the server rather than something you install. And a content delivery network so images and static files come from somewhere near the visitor.
Crucially, exclude the cart, checkout and account pages from page caching. Caching those produces the situation where a customer sees someone else's cart, which is worse than a slow page.
If your store is on shared hosting and every page starts slowly before anything loads, no amount of front-end tuning will fix it. That is the case where moving to hosting built for ecommerce is the cheapest change available.
Cut plugins and third-party scripts, in that order
Every plugin adds work to a page, and stores accumulate them without ever removing any. Go through the list and deactivate anything that is not doing a job you can name.
The ones that hurt most are those adding scripts and styles to every page rather than the page they serve. A contact form plugin loading its assets on every product page, a slider plugin used once on the homepage, a page builder loading a large framework everywhere. Some can be limited to specific pages with a small amount of configuration.
Third-party scripts are the other half. Chat widgets, review platforms, analytics, heat mapping, personalisation and ad pixels each add requests to code you do not control. Audit them the same way: name the job, name who looks at the data, and remove the ones that fail both. Load what remains after the page is usable rather than before.
One WooCommerce-specific item is worth checking. The cart fragments request refreshes the cart total on page load, and on some setups it fires on every page including ones with no cart. Limiting it to the pages that need it removes a request from the critical path across the whole site.
Images and fonts are usually the largest thing on the page
On a product page the main image is typically the element that decides how fast the page feels, so treat it as a specific task rather than part of a general clean-up.
Serve images in a modern format, at sizes that match how they are displayed rather than the original upload. A photograph uploaded at several thousand pixels wide and displayed at six hundred is wasting most of what it downloads. WordPress generates several sizes automatically, but themes do not always use the right one.
Load the main product image immediately and defer everything below the fold. Reserve the space it will occupy so the page does not jump when it arrives, which fixes both the perceived speed and the layout shift.
Fonts are the other common cost. Every custom font weight is a file to download, and a page using several weights across two families is downloading a lot before any text can appear. Host them yourself, keep the number of weights small, and set the display behaviour so text is visible while the font loads.
Galleries and zoom scripts on product pages are worth reviewing too. Many themes load a full gallery library even where a product has one photograph.
Keep the database and the cart light
WooCommerce stores accumulate data that slows queries down over time, and none of it is visible from the front end until the store feels sluggish.
The usual culprits are expired transients that were never cleaned up, post revisions building up on products and pages, abandoned session records, order metadata from plugins that were removed years ago, and log tables that were never trimmed. Cleaning these up is routine maintenance and it should be scheduled rather than done once during a crisis.
Product count matters as well. Large catalogues need the product lookup tables in good order, and archives that load dozens of products with variations and stock checks on every page view will be slower than they need to be. Reducing the number of products shown per page, and avoiding themes that load full variation data for every item in a grid, both help.
Finally, watch the admin. A slow admin makes everything harder and it is usually the same causes, plus imports and scheduled tasks running during the day. Move heavy imports and syncs to quiet hours, so a feed update is not competing with your customers for the same server.
Worked example, not a result
A speed pass on one product page
- Starting time to main content, mobile
- 6.5 seconds
- After page and object caching
- 4.1 seconds
- After removing 7 unused plugins
- 3.4 seconds
- After image resizing and modern formats
- 2.6 seconds
- After deferring chat and heat mapping
- 2.2 seconds
- Tested on
- A mid-range phone, mobile connection
Worked example, not a result