Every website leaks. Pages get deleted, products get discontinued, someone fat-fingers a link in an email, and a URL that used to work now doesn’t. When a visitor or a search-engine crawler lands on one of those dead URLs, WordPress shows them a page — and on most sites, that page is an afterthought nobody has looked at in years.
That afterthought matters more than it looks. A dead-end 404 is where visitors bounce, where inbound link equity goes to die, and where Google quietly decides how to treat the gap. The last migration cleanup we did left a few thousand old product URLs answering with a bare “Nothing found” page — and, worse, answering it with an HTTP 200 “everything’s fine” status. Google Search Console spent the next few weeks re-crawling every one of them, unsure whether they were real pages or mistakes. The fix wasn’t glamorous: it was making the site honest about what was actually missing.
This guide covers what WordPress really does when a URL isn’t found, the soft-404 mistake that wastes your crawl budget, when to use 410 instead of 404, and how to build a 404 page that turns a dead end into a second chance.
What WordPress Actually Does at a Dead URL
When a request comes in for a URL that doesn’t match any post, page, archive, or other route, WordPress runs its query, finds nothing, and flags the request as a 404. Two things happen from there, and it’s worth keeping them separate in your head because they fail independently.
The status header
First, WordPress sends an HTTP status code. On a genuine not-found request it calls status_header( 404 ) and the server responds with 404 Not Found. That header is the part machines read. A browser mostly ignores it, but a crawler treats it as gospel: a 404 tells Google “this URL has nothing, don’t index it, move along.” This is the single most important thing your 404 page does, and it’s invisible to human visitors.
The template
Second, WordPress picks a template to render. Following its template hierarchy, it looks for a file named 404.php in your active theme. If that file exists, you get whatever you designed. If it doesn’t, WordPress falls back to index.php, which is why so many neglected sites show a generic, styleless “Oops, that page can’t be found” with no navigation and no way out. Inside any template you can check the conditional tag is_404() to confirm you’re on an error response and branch your markup accordingly.
Here’s the part people miss: those two things — the status code and the template — are set separately. It’s entirely possible to serve a beautiful, on-brand “page not found” design that returns HTTP 200. To a human it looks correct. To Google it’s a lie, and Google has a name for that lie.
A “not found” page that returns HTTP 200 is a soft 404, and Google will keep crawling it, keep it eligible for indexing, and burn crawl budget deciding what it is. Return an honest 404 and Google drops the URL cleanly. The status code is doing the SEO work here, not the design.
The Soft 404, and Why It Quietly Hurts You
A soft 404 is Google’s term for a URL that presents like a missing page to a person but responds with a success status to a machine — usually 200, sometimes a redirect to somewhere unhelpful. Google’s own crawl-budget documentation is blunt about the cost: it says soft 404 pages “will continue to be crawled, and waste your budget,” because the server claims the page exists instead of letting Google retire it. On a small blog that’s a rounding error. On a site with thousands of expired listings, events, or products, it’s the difference between Google spending its limited attention on your live pages versus your ghosts.
There are three common ways WordPress sites end up serving soft 404s, and a page builder or a plugin is usually involved.
Redirecting every dead URL to the homepage
This one feels helpful and is genuinely harmful. Someone installs a “redirect 404s to home” plugin, and now every broken URL returns a 301 to the homepage. Google’s guidance treats redirecting a large number of missing pages to an irrelevant page like the homepage as a soft 404, not a legitimate redirect. You’ve taught the crawler that a thousand different missing URLs all “are” your homepage, which is nonsense, and you’ve robbed the visitor of any signal that they hit something that no longer exists. If a page is simply gone, let it be gone.
A landing-page plugin that serves 200 on everything
Some themes and builders intercept the request early and render a designed “not found” layout without ever letting WordPress set the 404 header. The page looks intentional, so nobody checks the status. You only discover it when Search Console’s Page indexing report fills up with “Soft 404” flags months later.
Thin or empty pages that were never really 404s
Google will also call a genuinely-live page a soft 404 if it’s nearly empty — an archive with no posts, a search results page with zero matches, a category that got cleared out. Those return 200 correctly, but there’s nothing on them, so from Google’s side they’re indistinguishable from an error. The fix there isn’t the status code; it’s giving the page something real or noindexing it.
404 or 410: Saying “Gone” On Purpose
Most people never touch the 410 status code, and for occasional dead links that’s fine. But it’s worth knowing the distinction, because it maps to a real decision you make all the time.
A 404 Not Found means “I can’t find anything at this URL right now.” It’s non-committal — the page might come back, might be a typo, might be temporary. A 410 Gone means “this existed and has been intentionally, permanently removed.” It’s a stronger, more definitive statement. Google’s documentation says all 4xx errors, including 404 and 410, are treated the same for crawling: the URL is dropped from the index and its crawl frequency gradually decreases. Some Google engineers have said a 410 may be dropped marginally faster because you’ve removed the ambiguity, but the official docs treat the two identically, so don’t expect a dramatic difference.
Use 410 when you know a page is never coming back — a discontinued product line, an expired campaign, content you deliberately pruned. Use 404 for everything else, including typo’d URLs and pages you’re unsure about. In WordPress you can send a 410 for a specific set of paths with a small snippet on the template_redirect hook:
add_action( 'template_redirect', function () {
$gone = array( '/old-product/', '/summer-2019-sale/' );
if ( in_array( untrailingslashit( $_SERVER['REQUEST_URI'] ), array_map( 'untrailingslashit', $gone ), true ) ) {
status_header( 410 );
nocache_headers();
exit;
}
} );
For a handful of URLs that’s plenty. For hundreds, a redirect-management plugin with a proper 410 option will save you the maintenance.
Building a 404 Page That Actually Helps
Once the status code is honest, the visitor experience is pure upside. A person who hits a 404 hasn’t left yet — they’re standing in your doorway, mildly annoyed, deciding whether to bounce. A good 404 page gives them somewhere to go instead of a “back” button. The best ones share a few traits.
Keep the tone human and on-brand. A tiny bit of personality (“Well, this is awkward”) beats a cold system error, but don’t let the joke get in the way of the exit. The most useful element you can add is a search box, because a 404 usually means the person knows roughly what they wanted and just landed in the wrong spot. After that, offer a short list of your most popular or most recent posts, your main navigation, and a clear link home. If your analytics or logs show a recurring broken URL — an old link everyone still shares — a direct pointer to the correct page turns your worst dead end into a fast recovery.
A minimal 404.php that does the right things
You don’t need much. This calls get_header()/get_footer() so the page keeps your site chrome, and leans on WordPress helpers for the search form and recent posts:
<?php get_header(); ?>
<main class="error-404">
<h1>We couldn't find that page</h1>
<p>It may have moved, or the link might be out of date. Try a search:</p>
<?php get_search_form(); ?>
<h2>Recent posts</h2>
<ul>
<?php
wp_get_archives( array(
'type' => 'postbypost',
'limit' => 5,
) );
?>
</ul>
<p><a href="<?php echo esc_url( home_url( '/' ) ); ?>">Back to the homepage</a></p>
</main>
<?php get_footer(); ?>
Because WordPress already set the 404 header before this template renders, you don’t have to do anything special to keep the status correct. Just don’t add a redirect or a plugin that overrides it.
Wiring It Up, and Watching It Over Time
Where you put your 404 template depends on what kind of theme you run, and the two paths are genuinely different.
Classic themes
If your theme uses PHP template files, create or edit 404.php in the active theme folder. Use a child theme so a theme update doesn’t wipe your work — that’s the same lesson as any template customization. Edit, save, then visit a deliberately fake URL to see it.
Block (full-site-editing) themes
Block themes don’t use 404.php. They ship a 404.html template made of block markup in the theme’s templates folder, and you edit it visually under Appearance → Editor → Templates → Page: 404 (or “404” in the template list). Drop in a Search block, a Latest Posts block, and a heading, then save. Same result, no code, and it survives updates because your edits live in the database rather than the theme files.
Verify the status code, not just the look
This is the step almost everyone skips. After you build the page, confirm it returns a real 404 and not a 200. The fastest way is a single command from a terminal:
curl -sS -o /dev/null -w "%{http_code}\n" https://yoursite.com/this-page-does-not-exist
You want to see 404. If it prints 200, something in your stack is overriding the header — a builder, a redirect plugin, or a caching layer — and you’ve got a soft 404 to hunt down. You can also check the response headers in your browser’s Network tab, or paste the URL into a header-checking tool.
Find the broken links you don’t know about
The 404 page handles the visitor; monitoring handles the pattern. Google Search Console’s Page indexing report lists URLs it tried and got a 404 or soft 404 on, which is the cleanest way to spot broken links search engines actually care about. Your server access logs show the same thing in real time. When you find a dead URL that still gets meaningful traffic and has an obvious replacement, 301-redirect it to that replacement — that’s the one case where a redirect beats a 404. Everything else can stay a clean 404, and now it lands on a page that helps.
A great 404 page is a safety net, but the real win is fewer people hitting it in the first place — solid internal linking, clean redirects on the pages that moved, and structured data that helps search engines route people to the page that does exist. That’s the same job amplifi.studio’s open-source amplifi.plugins suite handles for meta and schema — but a clean 404 costs nothing and you can build it this afternoon.
Frequently Asked Questions
A dead link is going to happen no matter how careful you are. The difference between a site that leaks visitors and one that catches them is a single honest status code and a page worth landing on. Build yours this week.
Built by amplifi.studio — see also our WordPress 301 redirect guide.