Integration
When a visitor hits a 404 you ask no404, get the best matching URL back and send them there. There are three ways to do it — and the difference is not what the visitor sees, it's the HTTP status the search engine sees.
Which path should I pick?
All three get the visitor to the right page. The difference is the HTTP status your server returns, and that difference decides the SEO outcome: an address that returns 301 carries its accumulated value to the new one, an address that stays 404 does not.
| Path | HTTP status | Who it's for |
|---|---|---|
| WordPress plugin | 301 | WordPress sites. No code, installed from the admin panel. |
| Server-side | 301 | Anyone writing their own code. We hand you a ready specification. |
| Browser snippet | stays 404 | No server access, or you just want to try it in five minutes. |
WordPress pluginPublished on WordPress.org
Catches the 404 on the server, asks no404 and returns a real 301. It doesn't touch your theme files and requires no code.
- WordPress 6.0+ · PHP 7.4+
- Caches results locally — protecting your quota and the rate limit.
- If no404 doesn't answer, the page falls back to its normal 404 (fail-open); the plugin never keeps your site waiting.
Installation
- In your WordPress admin, go to Plugins → Add New and search for no404.
- Click Install Now and activate it.
- Paste the API key from your dashboard into the plugin settings.
Server-side integration
If you write your own code, you can ask no404 wherever you produce a 404 and return a real 301. You don't have to design this from scratch: the dashboard generates a ready integration specification for your site.
The specification is not a snippet, it's an engineering document: timeouts, mandatory caching, a blocklist, the 301/302 rule, plus loop and open-redirect protection. Hand the file to your developer, or straight to an AI coding agent.
Caching is not optional
In a server-to-server call all of your traffic counts as coming from a single IP, and the rate limit (120 requests per minute) applies to that IP. If you don't cache responses locally, a busy site will hit the limit and redirects will stop silently. The specification includes this as a mandatory item.
The minimal version (Node.js)
const res = await fetch(
"https://www.no404.tr/api/v1/resolve/YOUR_API_KEY?path=" + encodeURIComponent(path),
{ headers: { Origin: "https://yoursite.com" } }
);
const data = await res.json();
// REDIRECT or a high-scoring CATALOG match → permanent (301); everything else → temporary (302).
if (data.redirect) {
const permanent = data.source === "REDIRECT" || data.score >= 0.5;
// örn. Express: res.redirect(permanent ? 301 : 302, data.redirect);
}Browser snippet
This path leaves the HTTP status at 404
The redirect happens in JavaScript, so the server still returned a 404. The visitor reaches the right page, but the search engine keeps treating the old address as dead and no link value is passed on. If you can reach your server, pick one of the two paths above.
Add the code below to your site's 404 page. Replace YOUR_API_KEY with the API key from your dashboard.
<!-- no404: add this to your 404 page -->
<script>
(function () {
var p = location.pathname + location.search;
var ref = document.referrer;
fetch("https://www.no404.tr/api/v1/resolve/YOUR_API_KEY?path=" + encodeURIComponent(p) + "&ref=" + encodeURIComponent(ref))
.then(function (r) { return r.json(); })
.then(function (d) { if (d && d.redirect) location.replace(d.redirect); })
.catch(function () {});
})();
</script>Next.js (App Router)
Inside app/not-found.tsx:
"use client";
import { useEffect } from "react";
export default function NotFound() {
useEffect(() => {
const p = location.pathname + location.search;
fetch(`https://www.no404.tr/api/v1/resolve/YOUR_API_KEY?path=${encodeURIComponent(p)}&ref=${encodeURIComponent(document.referrer)}`)
.then((r) => r.json())
.then((d) => { if (d.redirect) location.replace(d.redirect); })
.catch(() => {});
}, []);
return <p>Page not found, redirecting you…</p>;
}Endpoint reference
A single endpoint used by all three paths; it accepts both GET and POST.
Parameters
| apiKey | path | Your site's API key (required). |
| path | query / body | The path that returned 404, e.g. /missing-page (required). |
| ref | query / body | Where the visitor came from (document.referrer). Optional; empty = direct visit. |
GET example
curl "https://www.no404.tr/api/v1/resolve/YOUR_API_KEY?path=/14g-gold-ring-102" \
-H "Origin: https://yoursite.com"POST example
curl -X POST "https://www.no404.tr/api/v1/resolve/YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Origin: https://yoursite.com" \
-d '{"path":"/14g-gold-ring-102"}'Response & status codes
A successful response returns JSON:
{
"success": true,
"found": true,
"redirect": "https://yoursite.com/14g-gold-ring",
"score": 0.92,
"source": "CATALOG"
}Response fields
| found | boolean | Whether a confident match was found (can be false on a fallback redirect). |
| redirect | string | null | The full URL to redirect to. If set, send the visitor there (fallbacks included). |
| score | number | Match score between 0 and 1 (1 = a manual redirect). |
| source | enum | REDIRECT (manual) · CATALOG (automatic) · FALLBACK (below threshold, fallback address) · NONE (no match). |
Status codes
| 200 | Success (found may be true or false). |
| 403 | Origin not allowed, or tracking is paused. |
| 404 | Invalid API key. |
| 422 | Invalid or missing 'path'. |
| 429 | Rate limit exceeded (too many requests). |
Origin lock & security
Your API key is protected by an origin lock. Requests are only accepted from the allowed origins you define in the dashboard. Even if your key leaks, a browser request from another domain is rejected with 403 and no CORS response is returned.
- When you add your site, your domain is added as an allowed origin automatically (with and without www).
- You can add further domains from the dashboard.
- If a key leaks, regenerate it from the dashboard; the old key becomes invalid immediately.
Origin header, so the origin lock never engages; protection comes from the key plus the rate limit. Keep the key on your server and never embed it in the client.Best practices
- Prefer the server side: it's the only path that produces a 301; the snippet carries no SEO value.
- Cache the responses: in a server-side integration this is not optional — all traffic counts as one IP.
- Connect your sitemap: match quality depends on how current your catalog is.
- Review the threshold: if you don't want overly aggressive redirects, raise it (0.3 recommended).
- Define manual redirects for critical paths; they override automatic matching.
- Rate limit: 120 requests per minute per key + IP.