Test your checkout flow before launch
What breaks checkout flows, ranked — and the safe way to verify each before launch: walk the flow up to the payment wall, no real card charged.
Your checkout flow is the one place on your site where a bug costs money directly — the user is trying to pay you, and something silently eats the order. It’s also the flow that every free pre-launch checker skips. Static audits read your pages; they confirm the checkout page loads and returns 200. None of them adds an item to a cart, watches the total recompute, or checks that an order actually got created. And the obvious manual test — clicking through it yourself — passes for you and hides the race conditions that hit real users. In a June 2026 audit of 49 fresh web launches, 38 (78%) shipped with at least one critical verified finding on day one. (That audit walks public pages, so it can’t tell you how many checkouts specifically broke — but it tells you launch-day code ships broken far more often than founders expect.)
The safe way to test a checkout flow before launch is to walk it the way a real buyer would — add to cart, go to checkout, fill the address — and verify each step actually worked, stopping at the payment wall instead of charging a real card. Then do the handful of manual checks no external tool can safely do for you. This piece is the list of what breaks, in order, and how to verify each one.
Why static checkers and a quick click-through miss this
A static audit confirms the page exists. It does not press “add to cart,” re-read the cart total after a coupon, watch the network request that creates the order, or check that the confirmation email fired. Checkout is a flow — four or five screens with server-side state changing under each one — and flow testing is a different problem from page testing.
Clicking through it yourself misses a different set of bugs: you test with your own browser, your own saved address, your own fast connection, and a warm cache. Real users hit the cold path, the second concurrent request, the mobile payment sheet, the expired coupon. The good news is the same as with signup flows: the surface is small and bounded. A handful of things break checkout. You can know all of them.
The things that break checkout flows
In rough order of how often they show up in founder reports and in our own audits:
-
Cart state doesn’t persist. The user adds three items, navigates, comes back — the cart is empty. Or it’s full on desktop and empty on their phone. Why it happens: the cart lives in client-side state (
localStorage, a React store) and was never persisted server-side or tied to a session. AI coding tools reach for the in-memory version first because it’s the shortest path to a working demo. 5-minute manual check: add an item, hard-refresh the page, then open the same URL in a second browser. The cart should survive both. -
The total is wrong. Tax, shipping, or a discount is computed in the browser and never re-checked on the server — so a user can land on a total that doesn’t match what they’re charged, or a coupon “works” in the UI but the server ignores it (or vice versa). Why it happens: client-side price math is easy to generate and demos cleanly; the server-side re-validation is the boring half that gets skipped. 5-minute manual check: apply a coupon, then watch the order-create request in DevTools → Network. The amount the server receives must match the amount the UI showed. Try an invalid coupon too — it should be rejected server-side, not just hidden in the UI.
-
The order is created but the payment webhook never fires. The success page renders, the buyer sees “Thank you” — but nothing fulfills the order, because the app wired completion to the client-side redirect instead of the gateway’s webhook. This is the checkout twin of the signup bug where the UI updates but the server state never does, and the same class of failure as a dropped payment webhook after launch. Why it happens: the redirect URL is right there in the client code; the webhook handler is a separate endpoint that’s easy to stub and forget. 5-minute manual check: complete a test-mode order, then look at your backend — was the order row created and marked paid from the webhook, not from the browser landing on
/success? Kill the success-page tab before it loads and confirm the order still completes. -
The payment form is blocked or broken on mobile. The Stripe Elements iframe doesn’t render, Apple Pay / Google Pay never appears, or a popup-based redirect is blocked by mobile Safari. The buyer sees a blank box where the card field should be and leaves. Why it happens: the payment UI is the one part of checkout you can’t fully control — it’s a third-party iframe or native sheet with its own mobile quirks, and it’s rarely tested on a real phone. 5-minute manual check: open checkout on an actual iPhone and an actual Android phone. The card field must render and accept input; the wallet button, if you offer one, must open its sheet.
-
Double-submit and inventory races. The buy button fires twice on a slow connection — two orders, or two charges — because there’s no idempotency key and the button isn’t disabled after the first click. Why it happens: the happy path was built and tested once, fast; the retry path wasn’t. 5-minute manual check: throttle your network to 3G in DevTools, then double-click the pay button. You should get exactly one order. (Idempotency on money-moving endpoints isn’t optional — it’s the reason agent-facing APIs need the same discipline: anything that retries must be safe to re-enter. See how Prufa verifies a flow.)
-
The diagnostic one: the test hits the payment wall. When an automated check reaches a card-entry step, the right behavior is to stop — not to type a card. If your checkout is behind a gateway a tool can’t safely enter, the tool reports BLOCKED at the payment wall. That’s not “your checkout is broken”; it’s “an external test can’t go further without charging someone.” The manual test order is the workaround.
How Prufa walks a checkout flow
Prufa runs the same pattern here it runs everywhere: an LLM does the navigation, plain code does the verification. The LLM reads the page like a buyer — finds the product, the add-to-cart button, the checkout link, the address form — and plain code, against captured browser evidence, verifies each step actually worked: the cart request returned 200, the total in the order-create payload matches what was shown, the right endpoint was hit. The LLM never grades the result, so its blind spots can’t become the verifier’s blind spots. (The full walkthrough is in How Prufa verifies a signup flow; checkout is the same machinery pointed at a different flow.)
The part that’s specific to checkout is what happens at the payment step. Prufa’s rule is a conservative decision tree, and it’s enforced in code, not policy:
- No card field on the page → proceed.
- A card field, and you haven’t explicitly authorized test payments for this domain → hard-halt. The run records that it reached the payment wall and stops.
- You authorized test payments, but the page doesn’t prove it’s in test mode → still hard-halt. This is the case that matters most: even with your opt-in, Prufa refuses to enter card data unless the page itself carries a test-mode signal, because the cost of getting it wrong is a real charge.
- You authorized test payments and the page proves test mode (a test publishable key or a “test mode” banner on the page) → and only then does it use a known gateway test card.
A real payment instrument is never used — that’s a hard product invariant (“no real payment instruments, no money out”), and there’s a regression test plus a metric that has to stay at zero to keep us honest about it. That’s the answer to the question the rest of the internet’s checkout-testing advice dodges: you can automate testing a real checkout safely, but only by defaulting to “don’t touch the card.”
What the free 60-second audit does for checkout
The free audit on prufa.dev opens your entry URL on a real browser and walks the public purchase path — finding the product, adding to cart, advancing to checkout — and verifies each step up to the payment wall, where it halts. You can run a free checkout audit on any URL — no signup, no card, public pages only. It catches the silent failures a static checker can’t: a cart that doesn’t persist, a checkout link that 404s, a total that never recomputes. It’s pre-launch QA for indie hackers shipping solo: the walk-to-the-payment-wall check, run for you.
If you want checkout watched continuously rather than once, Starter ($29/mo) re-verifies your core flows — signup, login, checkout — daily and on every deploy, and alerts you the moment one breaks. Pro ($99/mo) adds money-flow monitoring and credential-backed flows from an encrypted vault, across staging and production in one workspace — for the deeper, logged-in purchase journeys. Even there, the payment-wall rule holds: a charge is only ever possible against a gateway you’ve authorized in test mode. (See pricing for the full plan breakdown.)
For the rest of the pre-launch surface — sitemaps, meta tags, broken links, console errors — see Website QA checklist before launch. Checkout is the flow that list points at and static checkers don’t walk. If your site’s conversion path is a lighter one, the same gap applies to your contact form — it can submit cleanly and still never deliver the email.
What the audit doesn’t do (honest limits)
The free audit cannot complete a purchase — by design, it stops at the payment wall. It can’t see what happens server-side after payment: order fulfillment, inventory decrement, the tax your accountant cares about, the confirmation email actually landing. It can’t pass a reCAPTCHA, and it can’t test a payment gateway you haven’t authorized in test mode. Those are the parts you have to test yourself — which is exactly what the checklist below covers. An external black-box walk verifies the flow up to the handoff; the test order you place yourself verifies the handoff and everything past it.
What to do before you launch
In order of impact:
- Place one real test order through your gateway’s test mode. Use the gateway’s test card. Walk the entire flow — cart, address, payment, confirmation. Then check your backend: the order row exists, it’s marked paid from the webhook, and the confirmation email arrived.
- Re-check the total server-side. Apply a coupon and watch the order-create request. The amount the server charges must equal the amount the UI showed. Try an invalid coupon — it must be rejected server-side.
- Test checkout on a real phone, ideally Safari on iOS. The card field and any wallet button must render and work. A blank payment box is an abandoned sale.
- Hard-refresh with a full cart, and open it in a second browser. The cart must survive both. If it empties, your cart state isn’t persisted.
- Throttle to 3G and double-click the pay button. You should get exactly one order. Two means no idempotency on a money-moving endpoint.
Get those five right and you’ve closed the failure modes that turn a working-looking checkout into lost revenue on launch day. The signup flow is the other half of the same job — both are flows static checkers never walk.
FAQ
How do I test my checkout flow before launch without charging a real card?
Walk the flow up to the payment step on a real browser — add to cart, go to checkout, fill the address — and verify each step worked, then stop before entering card data. A free 60-second audit does this automatically and halts at the payment wall. For the payment step itself, place one order through your gateway’s test mode with its test card. Never type a real card into a checkout you’re testing.
Why does my checkout work for me but fail for real customers?
Because you test the warm path: your saved address, a fast connection, one browser, a primed cache. Real customers hit the cold path — a cart that was never persisted server-side, a total computed only in the browser, a payment webhook that never fires so the order is never fulfilled, or a card field that doesn’t render on mobile Safari. Each looks fine in a quick click-through and breaks for someone else.
Can an automated tool test a Stripe checkout safely?
Yes, if it defaults to never touching the card. The safe rule is: detect the card-entry step and hard-halt unless you’ve explicitly authorized test payments for that domain and the page itself proves it’s in test mode — only then use a known test card, never a real one. Prufa enforces exactly this decision in code, with a metric that has to stay at zero.
What’s the difference between testing the checkout UI and testing the payment?
The checkout UI is everything up to the payment handoff — cart, totals, address, validation — and it’s safe for an external tool to walk and verify. The payment is the charge itself, which only you can safely test, through your gateway’s test mode. Most checkout bugs live in the UI-and-state half; the payment half needs a test order you place yourself.
Frequently asked questions
How do I test my checkout flow before launch without charging a real card?
Walk the flow up to the payment step on a real browser — add to cart, go to checkout, fill the address — and verify each step worked, then stop before entering card data. A free 60-second audit does this automatically and halts at the payment wall. For the payment step itself, place one order through your gateway's test mode with its test card. Never type a real card into a checkout you're testing.
Why does my checkout work for me but fail for real customers?
Because you test the warm path: your saved address, a fast connection, one browser, a primed cache. Real customers hit the cold path — a cart that was never persisted server-side, a total computed only in the browser, a payment webhook that never fires so the order is never fulfilled, or a card field that doesn't render on mobile Safari. Each looks fine in a quick click-through and breaks for someone else.
Can an automated tool test a Stripe checkout safely?
Yes, if it defaults to never touching the card. The safe rule is: detect the card-entry step and hard-halt unless you've explicitly authorized test payments for that domain and the page itself proves it's in test mode — only then use a known test card, never a real one. Prufa enforces exactly this decision in code, with a metric that has to stay at zero.
What's the difference between testing the checkout UI and testing the payment?
The checkout UI is everything up to the payment handoff — cart, totals, address, validation — and it's safe for an external tool to walk and verify. The payment is the charge itself, which only you can safely test, through your gateway's test mode. Most checkout bugs live in the UI-and-state half; the payment half needs a test order you place yourself.