A lightweight Laravel package for canonical URLs. Every URL is normalised against one configured domain, so duplicate content collapses to a single address. It powers the canonical tags on Dead by Stats.

  • One canonical domain — URLs are built from the configured domain, never from the host the request arrived on.
  • Deterministic normalisation — trailing slashes trimmed, query parameters preserved, root path collapsed to the bare domain.
  • Four ways to emit it — the Canonical facade, the canonical() helper, the <x-canonical> component, and the @canonical directive.
  • Validated configuration — a missing or malformed domain throws CanonicalConfigurationException instead of emitting a broken tag.
  • Deferred and Octane-safe — nothing resolves until you first ask for a URL.
  • PHP 8.4 or higher
  • Laravel 12.x or 13.x

Older release lines support PHP 8.3 and Laravel 11 — see version compatibility.

  1. Require the package. The service provider and facade are auto-discovered.

    Terminal window
    composer require fkrzski/laravel-canonical
  2. Set the canonical domain. Falls back to APP_URL, then http://localhost.

    .env
    CANONICAL_DOMAIN=https://example.com
  3. Emit the tag in your layout.

    resources/views/components/layouts/app.blade.php
    <head>
    <x-canonical />
    </head>
  4. Optionally publish the config to override the defaults.

    Terminal window
    php artisan vendor:publish --tag="canonical-config"

The same canonical URL, four ways:

<x-canonical /> {{-- current request --}}
<x-canonical path="/products/item" />

The component and the directive render the complete tag:

<link rel="canonical" href="https://example.com/products/item" />

The facade and the helper return the URL as a string, for reuse in an Open Graph tag, a header, or a redirect.