Tools · check

WooCommerce checkout speed test.

One product into a cart on your store, the real checkout opened with it three times, and what came back printed here: the first byte, the plugins the page shows, the scripts loaded from other domains, beside what the store I run reads.

Type the store’s address · the read takes a few seconds

The front page is enough; the check finds the shop, a product and the checkout from it. Public stores only, read once an hour, and a read answers for a day. Your address is sent to your store and nowhere else.

Beside yours

The store I run.

337 ms to the first byte of the checkout, 32 plugins, 1 render-blocking resource, on a phone, from the case study. Type your address above; the check puts one product in a cart on your store, opens the real checkout with it, and prints what it said back, here, beside these.

The store I run reads 337 ms, 32 plugins and 1 render-blocking resource, from 1,870 ms and 63 plugins before the speed sprint. The lines above are web.dev’s for the first byte and mine for the list: past 32 plugins the page shows, or more than 5 hosts that are not yours.

How this is read

The check works from Cloudflare’s network nearest you, the way a phone would, with a user agent that names this page. It reads your front page and finds the shop, one simple product and the checkout from it. It puts that product in a cart with the same add-to-cart link a customer clicks, in the throwaway session your store creates for every visitor, and it opens the checkout with that cart three times, timing each one; the median is the number and the three are printed. Each request waits eight seconds at most, follows three redirects at most, and reads a megabyte of HTML at most. The first byte is timed from the request leaving to the response’s headers arriving, which is web.dev’s definition: redirects, DNS, the connection, the request, the server’s work.

From the checkout’s HTML it reads what the page says back: its title and heading, the item and the total in the order review, the fields it asks, the payment and shipping methods it offers, whether there is a coupon field, an order-notes box, a terms box, a guest checkout. That is the proof it read your checkout and not your homepage. It also reads what the page shows: the paths under wp-content/plugins, which is what a plugin leaves when it ships a script or a style; the theme and its version; the WordPress and WooCommerce versions; a page builder and a caching plugin when they leave their marks; the payment gateway’s script; the host of every script, style, preconnect and frame that is not the store’s own; how many scripts and styles sit in the head and block the first paint; and the scripts I strip on a speed sprint. It keeps the words and the counts and throws the HTML away.

The verdict is three words. The server, when the checkout’s first byte is past 800 ms (web.dev’s line), or past a second (mine: nothing in the browser saves it then), or when the checkout arrived from a cache, which WooCommerce’s own documentation says it must not. The list, when the first byte is fine and the page shows more than 32 plugins or loads more than 5 hosts that are not yours, fonts and the gateway not counted; those two lines are mine, from the store I run. The platform, when the address is not WordPress, or WordPress without WooCommerce, and the numbers still read for what they are. Reads fine, when none of that is true.

What it does not do. It does not run Lighthouse, so there is no score and no largest paint here; PageSpeed Insights does that, thirty to sixty seconds a run, and it is worth running on the checkout as well as the homepage. It cannot see a plugin that ships nothing to the front of the site, so the count is a floor. It cannot read the fields of a checkout that a script draws after the page arrives, and it says so when that is what it found. A store is read at most once an hour by anyone and a read answers for a day, and one visitor gets ten reads a day, so nobody can use this page to hammer a store. Every read is written down: the host, the numbers, the verdict.

The three numbers, in the order I check them

The server first. On the checkout, the first byte is the whole of WordPress booting plus every query, on a processor you may be sharing with hundreds of other sites. web.dev holds a first byte to 800 ms for good and 1,800 for poor. The case study’s store read 1,870 ms on a shared plan and 337 after the move and one cache rule, a fall of 82 percent from the rule alone.

Then every plugin. Every active plugin loads on every uncached request, so the one that adds a slider to the homepage still loads its code on the checkout. Metorik’s sample of 6,000 stores runs 58 on average, 66 at a million a year of revenue, and one store ran 237. The case study went from 63 to 32 by removing the ones that could not name their job.

Then scripts from other domains. The analytics tag, the ad pixels, the chat widget, the review badge, the heat-map recorder: each is a new connection and a download, and on a phone on a weak signal they are often the largest thing painted. None of them sells anything on the checkout. The gateway’s script is the one you keep, and load last.

What to do with the numbers

If the fix is the server: move the store to a host that can run a checkout, at the price after the first-year offer, and exclude the cart, the checkout and my account from every cache. The store cost calculator has the hosts and their renewal prices; the case study has the cache rule.

If the fix is the list: remove one plugin a day that cannot name its job, and measure again on Friday. Move every script that is not the gateway’s off the checkout: the tag manager, the pixels, the chat. Strip what the tile names, starting with the emoji script and jQuery Migrate. Keep the count under the store I run, not under the average.

If the fix is the platform: the store is not WooCommerce, or the checkout is not the problem. The guide on when to leave WooCommerce draws that line, and the storefront I built is what the other side of it looks like.

Measure it yourself this week. One item in the cart, the checkout open on your phone, the network panel’s first byte, the number of requests to domains that are not yours, the number of active plugins in the dashboard. Three numbers. If they are bad and you cannot see why, book a call: thirty minutes, free, and I will tell you whether the fix is the server, the list, or the platform. The other calculators are on the tools page.

Questions people ask

Why not just use PageSpeed Insights?

Use it as well. It gives you the largest paint and the score, from a lab and from real Chrome users, and this page does not pretend to. What it does not do is read your checkout: people test the homepage, which is the cached page, and the number comes back fine while the checkout, which cannot be cached, is the page that is slow. This check opens the checkout with a cart in it, separates the server’s part from the page’s part, and puts a fast store’s numbers beside yours.

Does it really put something in my cart?

Yes, one simple product, with the same add-to-cart link a customer clicks, in a throwaway session your store creates for every visitor and forgets in two days. Nothing is ordered, nothing is paid, and the tile names the product it used and what your checkout said back, so you can see for yourself that it read the real page. If no simple product shows on your front page or your shop, the checkout is read empty and the tile says so.

What does “plugins it shows” miss?

Every plugin that ships nothing to the front of the site. A back-office plugin, a backup tool, a security plugin that hides its paths: none of them show in the HTML, so the count here is a floor, never the total. Metorik’s sample of 6,000 stores puts the average at 58 active plugins; if this page shows 25, the true number is higher, not lower.

Why is my first byte different from my own test?

This read is made from Cloudflare’s network nearest you to your server, three times in a row, and the median counts. Your own test is made from your phone on your network, and the number moves with your server’s load, your host’s neighbours and the time of day. The three reads are printed so you can see the spread: a checkout that answers in 300 ms and then 1,300 ms is a shared server having a bad hour.

Why can it not read my checkout’s fields?

Because your checkout is drawn by a script after the page arrives: the block checkout does that, and so do checkout plugins like CartFlows. The HTML this check reads holds the frame and not the form, so the fields and the payment methods are not in it. The first byte, the plugins, the outside hosts and the scripts to strip are all still real, and the tile says which kind of checkout it found.

Does it store my store’s address?

It keeps the host and the path it read, the numbers, the names of the plugins and the outside hosts, what the checkout said back and the verdict. That row answers for a day, so the next person asking about the same store gets it instead of your server being read again, and it stays in my log after that as the record of every read this page has made. It keeps a salted hash of your address for the rate limit. It never keeps the page’s HTML, and it sends your address to your store and nowhere else, with a user agent that names this page.

What if it says it could not read my store?

Your store’s bot protection answered the check with a refusal, which is what it is for, or the server did not answer within eight seconds, which is a finding on its own. Either way, do the exercise below from your phone: one item in the cart, the checkout open, the network panel’s first byte, the outside domains, the active plugin count. Three numbers, ten minutes.

Is a cached checkout bad?

Yes. WooCommerce’s own documentation says the cart, the checkout and my account must stay dynamic, because they show one customer’s cart. A caching plugin or a CDN rule that caches the checkout will show one customer another’s page, or a page that will not take an order, and the fast number it produces here is a lie. The fix is an exclusion rule, and the case study has the one I use.

What is a good first byte for a WooCommerce checkout?

web.dev’s line is 800 ms for good and 1,800 for poor, and I hold the checkout to the tighter one: over a second, nothing you do in the browser will save the page. The store I run reads 337 ms from 1,870 before the speed sprint, which is the difference between a shared plan with 63 plugins and a managed plan with 32 and one cache rule.

Next step · Norvahl, one designer-engineer, both tradesTaking on projects

Is the fix the server, the list, or the platform?

Send me the three numbers, or the address, and I read it myself and reply within a working day with which of the three it is.

Send a message Book a call

reply within a working day · me, not an assistant · a 30 minute call, free · no newsletter · hello@norvahl.com