ScoutSentinelScoutSentinel
Menu

Guide

How to detect a broken online form before your customers tell you

Why quote, application and claim forms break while the page still loads, why uptime checks miss it, and how to test the whole submission from outside.

Updated

In short

  • A broken form usually still loads. The page answers 200, so status-code checks stay green.
  • Test the outcome, not the page. Fill the form in a real browser and check for the confirmation a customer would see.
  • Run it on a schedule from outside your network, and again after each release.
  • Open an alert after two failed runs in a row, not one, to keep noise down.
  • Good evidence names the step that failed and shows the screenshot next to the last good run.

A quote form, a policy application or a claim form is where a customer’s intent turns into business. When it breaks, the site rarely goes down. The page loads, the header and footer are there, and the monitoring dashboard is green. The customer simply cannot finish.

This guide covers how that failure shows up, why the usual checks miss it, how to detect it yourself with a scripted browser, and what evidence makes the fix fast.

How a broken form shows up

Most broken forms fall into a handful of patterns:

  • The submit control is missing or disabled. A template change, a feature flag or a failed script leaves the page without its “Get quote” or “Submit” button, or leaves it greyed out for good.
  • Submitting does nothing. A JavaScript error stops the click handler, so the button looks fine and the page does not move on.
  • Valid answers are rejected. A validation rule changes (a postcode pattern, a date range, a phone format) and real customers are told their details are wrong.
  • A third-party part fails. Address lookup, identity checks, payment fields, CAPTCHA or a pricing service loads in the customer’s browser, not on your server, and fails there.
  • Something covers the form. A cookie banner, chat widget or promotion sits over the button on smaller screens.
  • It submits, then nothing follows. The confirmation page appears but no reference is shown, or the follow-up email with the policy documents does not arrive.

The signals you do see are indirect and late: a dip in completed quotes, more calls to the contact centre, complaints on social media, or an analyst noticing the funnel the next morning.

Why uptime checks and pings miss it

An uptime check asks one question: did this URL answer, quickly, with a success status? A form page with a missing button answers 200 OK as quickly as ever. So does the health endpoint behind it.

  • Status codes describe the server, not the task. Error messages rendered into a normal page (“Quotes are temporarily unavailable online”) still arrive with a 200.
  • Browser-side failures are invisible to HTTP checks. JavaScript errors, blocked third-party scripts and overlapping elements happen after the HTML is delivered.
  • Keyword checks look for the wrong thing. Checking that the page contains “Get a quote” passes when the heading says it and the button is gone.
  • Internal monitoring sits inside your network. It can miss DNS, CDN, certificate and consent problems that a customer on the public internet meets first.

None of these checks are wrong. They answer “is it up?”, which is a different question from “can a customer complete it?”.

How to detect it yourself

You can build a useful form check with an open-source browser automation tool such as Playwright. The principle is simple: do what the customer does, then check for what the customer should see at the end.

  1. Choose the forms that matter. Start with the two or three whose failure costs the most: getting a quote, applying, making a claim. Write each as a customer task: “Get a travel insurance quote and see a price”.
  2. Define success as an outcome. A quote reference on screen, a confirmation page with an order number, an email received. Not “the page loaded”.
  3. Script a real browser. Fill every field a customer would, with agreed test data, and submit. Use stable selectors your developers own, such as data-testid attributes, so a copy change does not break the test.
  4. Assert at each step. Check that the submit button is visible before clicking it, and that the result appears afterwards. When a step fails, you then know which one.
  5. Run it from outside, on a schedule. Every five to fifteen minutes from a location on the public internet is a sensible start for a revenue form. Add a run straight after each release.
  6. Alert on a pattern, not a blip. Two failed runs in a row from the same step is a good default. A single failure is often a network wobble.
  7. Agree how test submissions are handled. Use test cards and test accounts, mark the traffic so it can be excluded from analytics, and make sure nobody underwrites a test policy.

A minimal Playwright version of step 3 and 4 looks like this:

import { expect, test } from "@playwright/test";

test("a customer can get a quote", async ({ page }) => {
  await page.goto("https://www.example.com/quote");
  await page.getByLabel("Destination").selectOption("europe");
  await page.getByLabel("Departure date").fill("2026-10-14");
  await page.getByLabel("Return date").fill("2026-10-21");
  await page.getByLabel("Number of travellers").fill("2");
  await expect(page.getByTestId("get-quote")).toBeVisible();
  await page.getByTestId("get-quote").click();
  await expect(page.getByTestId("quote-price")).toBeVisible();
});

Pair it with the signals you already have. Analytics can compare form starts with submissions, server logs can count validation rejections, and real-user error monitoring can catch JavaScript errors. They tell you something changed; the scripted check tells you whether the task still works and where it stops.

What good evidence looks like

When the check fails, the person on call needs to act without reproducing the problem first. Good evidence answers five questions:

  • Which step failed? “Step 4 of 8: Get quote button is shown”, not “the quote journey is down”.
  • What was expected, and what happened? The assertion (“element visible: get-quote”) and the result (“element not visible after 5 seconds”).
  • What did the customer see? A screenshot at the failure, next to one from the last run that passed.
  • What else was going on? The page HTML and the network log from the same run, to show a failed request or a missing script.
  • How sure are we? How many runs failed in a row, from where, and when it started. If the check itself could not run, that is recorded as “unknown”, not as a failure of your form.

Evidence is more useful to an operational resilience or audit team when each file is hashed at capture, so it can be shown later that it has not changed.

How ScoutSentinel does it

ScoutSentinel runs these checks for you from outside your systems. You describe the form in plain words; it proposes the steps and assertions; you review and approve them before anything runs.

  • Checks run in a real browser from Cloudflare edge locations, as often as your plan allows.
  • By default an event opens after two consecutive failures at the same step, and resolves after two passes.
  • The event pairs a screenshot from the last passing run with the first failing one, and keeps the HTML, network log and browser trace your check captures, each hashed at capture.
  • Alerts go to email and signed webhooks on every plan, and to Slack and PagerDuty from Team. Each alert names the journey and links to the event.
  • A run that could not complete for reasons on our side is recorded as unknown, with the reason, not as a failure.

The home page walks through one example: a quote form on our demo insurance site loses its “Get quote” button while every uptime check stays green.

Check your most important form

Describe the form in plain words. ScoutSentinel proposes the steps, you approve them, and the check runs from outside your systems, keeping screenshots as evidence.

Free 14-day pilot by invitation. No card required. Starter limits apply unless we agree a scoped one-service evaluation. When the trial ends, the organisation is suspended until you choose a plan: scheduled checks stop, and your journeys and checks stay in your account. See pricing.