vibecheck0.3.0
Search visibilityseocanonical-missinginfo

Missing canonical link in Vanilla JS

The same content is often reachable at several URLs — with and without a trailing slash, with query or tracking params, at www and apex. Without <link rel="canonical">, search engines may treat these as separate pages and split ranking signals between them. AI-built apps generate lots of parameterised and duplicated routes, making this common.

Symptoms

  • The same page indexed under multiple URLs
  • Ranking signals split between ?utm and clean URLs
  • www vs non-www or trailing-slash duplicates in Search Console

How VibeCheck catches it

In your widget · Problems

infoseoMissing canonical link

To your coding agent · MCP

agent › get_detected_issues
{ detector: "seo", issue: "Missing canonical link", threshold: "no <link rel="canonical">" }

The same string in your widget and in your agent’s context — no screenshot, no copy-paste.

Root causes

  • Routes are reachable at multiple URL variants with no canonical declared
  • Query and tracking parameters create infinite URL variants
  • The head is unmanaged so no canonical tag is emitted

The fix for Vanilla JS

Add the canonical link to each page’s <head> with the clean absolute URL.

html
<link rel="canonical" href="https://acme.com/pricing" />

Steps

  1. Pick one canonical URL convention (host, trailing slash) and apply it everywhere
  2. Emit <link rel="canonical"> with the clean absolute URL on every page
  3. Point duplicate/parameterised variants at the same canonical

See the general, framework-agnostic fix →

FAQ

Should a page canonicalise to itself?
Yes. The preferred version should carry a self-referencing canonical. Duplicate variants then point at that same URL.
Does canonical fix duplicate content penalties?
There is no “penalty” per se, but canonical consolidates ranking signals onto one URL so duplicates do not compete with each other.
Absolute or relative canonical URL?
Use absolute URLs. They are unambiguous to crawlers. In Next.js a relative path is fine because metadataBase makes it absolute at build time.