---
title: "No single rel=canonical in <head> (seo/canonical-missing)"
description: "seo/canonical-missing: Without a canonical in <head>, Google picks one itself from duplicates (trailing slash, query strings, www), splitting signals."
canonical: https://void-design.vercel.app/rules/seo/canonical-missing
lastModified: 2026-09-16
---

# No single rel=canonical in <head>

`seo/canonical-missing` · severity **error** · category SEO · detected by `void seo` and `void audit`

## Why it matters

Without a canonical in <head>, Google picks one itself from duplicates (trailing slash, query strings, www), splitting signals. Canonicals in <body> or conflicting canonicals are ignored. This is a scoring gate.

## How to fix it

Emit exactly one absolute, self-referential canonical in <head> on every indexable page via alternates.canonical (absolutised by metadataBase).

## Example

```ts
// lib/seo.ts — one helper so every page emits the full set (nested metadata objects are replaced, not merged)
export function pageMetadata({ path, title, description }: { path: string; title: string; description: string }): Metadata {
  return {
    title,
    description,
    alternates: { canonical: path }, // '/blog/hello-world' → https://acme.example/blog/hello-world
    openGraph: { url: path, title, description, siteName: site.name, locale: site.locale, type: 'website' },
  }
}
```

## References

- https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls
- https://nextjs.org/docs/app/api-reference/functions/generate-metadata#alternates

## More seo rules

`void seo` reports 60 rules in this category. What search engines need from the raw response: status codes, titles and descriptions in <head>, self-referencing canonicals, one h1, crawlable links, Open Graph, icons, robots.txt and a sitemap with real dates.

- `title-length` Title length outside 10–60 characters, or keyword-stuffed — [seo/title-length](https://void-design.vercel.app/rules/seo/title-length)
- `meta-description-missing` No meta description in <head> — [seo/meta-description-missing](https://void-design.vercel.app/rules/seo/meta-description-missing)
- `meta-description-length` Meta description length outside 50–160 characters — [seo/meta-description-length](https://void-design.vercel.app/rules/seo/meta-description-length)
- `metadata-in-body` Crawler receives <title>/canonical/description inside <body> (Next.js streaming metadata) — [seo/metadata-in-body](https://void-design.vercel.app/rules/seo/metadata-in-body)
- `canonical-invalid` Canonical URL is relative or contains a fragment — [seo/canonical-invalid](https://void-design.vercel.app/rules/seo/canonical-invalid)
- `canonical-broken` Canonical points to a URL that returns 4xx/5xx — [seo/canonical-broken](https://void-design.vercel.app/rules/seo/canonical-broken)
- `canonical-conflict` Canonical target redirects, is noindex, or canonicalises elsewhere — [seo/canonical-conflict](https://void-design.vercel.app/rules/seo/canonical-conflict)
- `canonical-not-self` Canonical points to a different URL — [seo/canonical-not-self](https://void-design.vercel.app/rules/seo/canonical-not-self)

Detected by `void seo` and `void audit`. Explain it in a terminal: `void rules seo/canonical-missing`
