A website can be “up” and still broken: the server answers with HTTP 200, but the page shows a database error, an empty product list or a hosting company’s default page. A check that only looks at the status code passes all of those. Keyword monitoring closes the gap by checking the content too: text that must be on the page, such as “Add to cart”, or text that must not be, such as “Fatal error”. If the check doesn’t hold, the page counts as down and you get an alert.
How a site can be up but broken
The status code is set by whatever answers the request, and that isn’t always the part of the stack that failed. These all happen with a 200, or with a code your monitor accepts:
- An application error page. Some frameworks, themes and custom error pages render errors with a 200 instead of a 5xx code.
- An empty page. A PHP fatal error with error display switched off can produce an empty body, or a cache can store and serve an empty page.
- Missing data. The shop loads, but the product API behind it failed, so every category says “No products found”.
- The wrong site. After a hosting or DNS change, the domain lands on a default page such as “Welcome to nginx!” or a parking page.
- A maintenance page left on. A maintenance mode plugin that answers 200 instead of 503 looks like a working site to a status check.
- A defaced or injected page. An attacker replaces content or adds spam links, and the server still answers normally.
Google calls a page that says “not found” or shows nothing while answering 200 a soft 404, and such pages can be dropped from search. Users just see a broken site.
How keyword monitoring works
On every check, the monitor requests the page, reads the HTML the server returns and searches it for your text. There are two modes:
- Must contain: the check fails when the text is missing. Use it for proof that the page works, such as a button label or a product name.
- Must not contain: the check fails when the text appears. Use it for known error messages.
Two details matter. The check reads the HTML source, not the page you see in a browser, so text added later by JavaScript isn’t there. And the match is usually exact, including upper and lower case. The glossary entry on keyword monitoring has the short definition.
How to pick a good keyword
A good “must contain” keyword appears only when the page works, and stays the same from day to day. That rules out prices, dates, stock levels, counters and anything in an A/B test. Prefer text the application renders from its data or templates, so it disappears when the application fails, over text in a static header that a cache could still serve.
| Page | Must contain | Why it works |
|---|---|---|
| Product page | Add to cart | Only rendered when the product and the cart work |
| Category page | A product name that is always in stock | Missing when the product data fails to load |
| Login page | Forgot your password? | Part of the real login form, not an error page |
| Blog or news page | A line from the footer the CMS renders | Disappears when the CMS can’t reach its database |
| Health endpoint | "status":"ok" | Written by the application after it checks its dependencies |
For an API or a health check endpoint, a JSON check such as $.status equals ok is more precise than a keyword, since it doesn’t depend on spacing or field order.
“Must not contain” checks for error messages
A negative check catches failures you can name in advance. Useful strings, depending on your stack:
Error establishing a database connectionon WordPress. Core sends it with a 500, but a customdb-error.phppage may not.Fatal errororParse erroron PHP sites that display errors.Welcome to nginx!or your host’s default page title, to catch a domain pointing at the wrong server.- Spam words that have no business on your site, as a basic tripwire for injected content.
Watch out for pages where the string can appear legitimately. A blog post about database errors, or a help article quoting an error message, would fail a “must not contain” check every time. When in doubt, a positive check on text that proves the page works is the safer choice, since it catches failures you didn’t think of.
Test the keyword before you rely on it
Check what the server actually sends, not what the browser shows. From a terminal:
curl -s --compressed https://example.com/product/blue-mug | grep -c "Add to cart"
A count of 0 means the monitor won’t find it either. The usual reasons:
- JavaScript renders the text. View the page source (not the inspector) to see the HTML the server returns, and pick text that is in it.
- HTML entities. “Terms & Conditions” on screen is often
Terms & Conditionsin the source, and curly quotes may be encoded too. Pick text without special characters, or copy it from the source. - Case and spacing. A button styled in capitals with CSS is still “Add to cart” in the HTML. Line breaks inside the text also break an exact match.
- The monitor sees a different page. Sites that pick language or currency by location, or show a bot challenge to unknown clients, can send a monitor different HTML than you get at your desk.
When a keyword isn’t enough
- The content depends on JavaScript. Single-page apps send little HTML. Check them with a flow in a real browser, which runs the JavaScript before it looks for the text.
- The failure is a few steps in. The product page works, but adding to the cart doesn’t. A multi-step synthetic check walks the journey and checks each step.
- The page is very large. Monitors usually read only the first part of a response. Check for text near the top, or check a smaller endpoint.
- The page is slow, not broken. That is a response time question; set a slow-response limit instead.
The checklist of what to monitor on your website suggests which pages deserve a content check, and how to reduce false alerts covers the rest of the tuning.
Keyword checks in Uptimecheck
Every HTTP(S) monitor in Uptimecheck uptime monitoring can carry a keyword check next to the expected status codes:
- Contains or does not contain: one keyword per monitor, matched exactly, including case, in the first 2 MB of the response. Need both a positive and a negative check on the same page? Add a second monitor.
- JSON and header checks: up to 10 per monitor, such as
$.statusequalsokor aContent-Typeheader that containsjson, for APIs and health endpoints. - Test request: see the response and whether the checks pass before you save the monitor.
- Confirmed and explained: a failed check is repeated before an incident opens, and the incident says what was wrong, for example that the expected text wasn’t on the page or that the page came back empty, with the start of the response.
- JavaScript and journeys: flows check text at every step, and flows in a real browser see text that JavaScript renders, with a screenshot of the step that failed.
Checks run as often as every minute from Stockholm, Sweden, so a site that changes language by location shows Uptimecheck the version it serves to Sweden; pick a keyword that is the same in every version, or send the headers that choose a language. To set one up, see how to add your first monitor, and if a monitor reports down while the site works for you, why a monitor can be down when the site works.
Make “up” mean working. Try Uptimecheck free for 14 days, no credit card required.