Every site has at least four URLs for its homepage: http://example.com, https://example.com, http://www.example.com and https://www.example.com. One of them is the site. The other three should send a visitor there with a redirect and nothing else. When they do not, a machine reading the site sees two or four sites with identical content, and has to guess which one is real. Check B7 in the rubric, canonical and duplication hygiene, is worth three points and rated Low effort, because the fix is a redirect rule and a link element. This article covers what the check does, what it expects to see, and how we set it up on our own site.
The four URLs, and why one has to win
A host variant is not a cosmetic difference. To an HTTP client, www.example.com and example.com are unrelated hostnames that happen to share a suffix, and http and https are different schemes with different security properties. Nothing in the protocol says they belong together. Your server says it, by answering three of the four with a redirect to the fourth.
If it does not, each variant is a fully working copy. A search engine has spent two decades learning to fold copies together, and Google's own guidance on consolidating duplicate URLs describes the signals it uses to pick one. An agent doing a single fetch has no such machinery. It fetches the URL it was given, reads the page, and cites whatever host it landed on. Two agents given two variants will cite two different sites. The site that answers all four with one canonical host has removed the ambiguity rather than asking every consumer to resolve it.
There is a second, quieter cost. Any check that depends on a page's identity, structured data with @id values, sitemap entries, og:url, breadcrumbs, is written against one host. When the page is served from another host too, those values point somewhere else, and every consumer that compares them sees a mismatch.
What B7 measures
The check has two parts, scored separately. The evidence block on your report records pagesCrawled, selfConsistentCanonicals and a hostVariants list, and the recommendation names whichever part failed.
Two points for a self-consistent rel=canonical
For every crawled page, up to six, the scanner reads the href of link[rel="canonical"] from the raw HTML, resolves it against the page's own URL, and compares the path of the canonical with the path of the page it fetched. Trailing slashes are stripped from both sides before comparing. If every crawled page has a canonical whose path matches its own, the two points are earned. A page with no canonical element at all counts as inconsistent, and so does a page whose href fails to parse as a URL.
Three details follow from how that comparison is written. The query string is ignored, so a page reached at /pricing?utm_source=x with a canonical of /pricing is self-consistent, which is what you want. The host is not compared, only the path, so this part of the check does not care whether your canonical says www or not; the host question is the second part's job. And the standard is all or nothing across the crawled pages, because a template that emits the right canonical on five pages and the homepage's canonical on the sixth has a bug, not a partial pass.
One point for the host variants
After crawling, the scanner works out the bare domain by stripping any leading www. and probes two URLs: https://www. plus the bare domain, and http:// plus the bare domain. Whichever of those equals the origin it was asked to scan is skipped, so a scan of https://example.com sends both probes and a scan of https://www.example.com sends only the http one. Each probe is a plain GET with the scanner's own user agent and redirects set to manual, meaning it records the first response and does not follow it.
A variant passes if it returns a 200, or a status in the 300 range with a Location header. The point is earned only if every probed variant passes. What fails, therefore, is anything else: a 404 or 403 because the www host is not configured, a 5xx, or a status of 0, which is what the record shows when the connection never produced a response. That last case is the common one. A www hostname with no DNS record, or one that resolves but presents a certificate that does not cover it, both surface as an error rather than a status, and both fail.
Note what the check does not do. It does not follow the redirect to confirm where it lands, and it does not fail a variant that answers 200 with a full copy of the site. That is a deliberate floor: the point rewards a variant that responds sensibly, and the report's evidence shows you the status and location of each probe so you can see for yourself whether the redirect goes where you intended.
The shape of a correct answer
Pick the canonical host. Apex or www is a matter of taste; consistency is not. Then arrange for the three others to answer with a permanent redirect straight to the canonical https URL, preserving the path.
GET http://example.com/pricing -> 301 Location: https://example.com/pricing
GET http://www.example.com/pricing -> 301 Location: https://example.com/pricing
GET https://www.example.com/pricing -> 301 Location: https://example.com/pricing
GET https://example.com/pricing -> 200
Two hops, http://www to https://www to https:// apex, still pass the check, since the probe only inspects the first response, but one hop is better for every client that has to follow it. Then, on every page of the canonical host, emit a canonical that names the page's own URL:
<link rel="canonical" href="https://example.com/pricing">
An absolute URL is the safe choice. A relative one resolves correctly, and the scanner resolves it, but an absolute canonical is also what tells a consumer which host is canonical, which the redirect alone cannot do for a client that arrived at the right host to begin with.
You can watch the probes yourself with curl. The -I flag sends a HEAD rather than a GET, which is close enough for this purpose, and curl does not follow redirects unless told to:
for u in http://example.com https://www.example.com http://www.example.com; do
printf '%-28s ' "$u"
curl -s -o /dev/null -I -w '%{http_code} %{redirect_url}\n' "$u"
done
Three lines of a 3xx and the same https://example.com/ target is a pass. A 000 on any line is the DNS or certificate problem described above, and is the finding to chase first.
How we do it
Our canonical host is the apex, https://agentfriendlyrank.com. The www redirect lives in the application's own configuration rather than in a DNS panel, so it is versioned with the code and cannot quietly differ between environments. In next.config.ts it is a single rule matched on the Host header:
async redirects() {
return [
{
source: "/:path*",
has: [{ type: "host", value: "www.agentfriendlyrank.com" }],
destination: "https://agentfriendlyrank.com/:path*",
permanent: true,
},
];
}
Next.js answers a permanent: true redirect with a 308 rather than a 301. Both are in the 300 range with a Location header, so both pass the probe, and a 308 has the additional property of forbidding the client from changing the method, which is what you want for a redirect that exists purely to move hosts. The http to https hop is answered by the platform in front of the application before the request reaches it, which is the usual arrangement and the reason the http probe returns a redirect rather than reaching Next.js at all.
Every route sets its own canonical through the metadata API, resolved against the site URL so the emitted href is absolute. The layout declares a canonical of / as the default, which is precisely the value that would be wrong on every other page; the reason each page declares its own is that the check compares paths page by page and would catch a route that forgot.
The remaining piece is the Strict-Transport-Security header, sent on every response:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Check D1 wants the header present; for B7 its relevance is includeSubDomains. Once a browser has seen it, that browser will never send a plain http request to the apex or to www again for two years, so the insecure variants stop existing from that client's point of view. A crawler with redirects set to manual does not honour HSTS, though, which is why the server-side redirect still has to be there. The header is a promise to clients that remember; the redirect is the answer for the ones that do not.
One more place the canonical host matters is robots.txt. The Sitemap: line there is an absolute URL, and it should name the canonical host, because a crawler that reads a sitemap full of www URLs from a site whose canonical is the apex has just been handed several hundred pages that each redirect. robots.txt for the agent era covers the rest of that file.
Check your own site
Run the free scan and open B7 on the report. The evidence lists every page's canonical result and both host probes with their status and Location. The definition of the check sits under understanding on the methodology page, and our own result, including the redirect described above, is on our live report.