fkrzski/laravel-canonical

Laravel package for managing canonical URLs and preventing duplicate content

Fund package maintenance!
fkrzski

Installs: 0

Dependents: 0

Suggesters: 0

Security: 0

Stars: 1

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/fkrzski/laravel-canonical

1.2.0 2025-10-30 15:48 UTC

This package is auto-updated.

Last update: 2025-11-06 18:07:58 UTC


README

Latest Version on Packagist Tests Total Downloads

A lightweight Laravel package for generating canonical URLs to prevent duplicate content issues and improve SEO. Automatically normalizes URLs by removing trailing slashes while preserving query parameters.

Version Compatibility

Package Version PHP Version Laravel Version
1.x.x 8.3+ 11.x, 12.x

Installation

Install via Composer:

composer require fkrzski/laravel-canonical

The package will auto-register via Laravel's package discovery.

Configuration

Publish the configuration file (optional):

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

Set your canonical domain in .env:

CANONICAL_DOMAIN=https://example.com

If not set, it falls back to APP_URL.

Trailing Slash Configuration

@since 1.1.0

Control whether trailing slashes are removed from canonical URLs:

# Remove trailing slashes (default behavior)
CANONICAL_TRIM_TRAILING_SLASH=true

# Preserve trailing slashes
CANONICAL_TRIM_TRAILING_SLASH=false

When set to true (default), URLs are normalized by removing trailing slashes. When set to false, the original URL format is preserved.

Usage

Blade Components

@since 1.2.0

The package provides three convenient ways to add canonical link tags in your Blade templates:

1. Using Blade Component

<head>
    {{-- Use current request URL --}}
    <x-canonical />

    {{-- Specify custom path --}}
    <x-canonical path="/products/item" />

    {{-- Use dynamic path --}}
    <x-canonical :path="$post->canonical_path" />
</head>

2. Using Helper Function

The canonical() helper provides a hybrid approach - it can return either the generator instance or a URL string:

<head>
    {{-- Direct URL generation --}}
    <link rel="canonical" href="{{ canonical('/products/item') }}" />

    {{-- Fluent usage (without arguments returns generator) --}}
    <link rel="canonical" href="{{ canonical()->generate('/products/item') }}" />

    {{-- Use current request URL --}}
    <link rel="canonical" href="{{ canonical()->generate() }}" />

    {{-- Also works in PHP code --}}
    @php
        $url = canonical('/products/item'); // Returns: "https://example.com/products/item"
        $generator = canonical(); // Returns: CanonicalUrlGeneratorInterface instance
    @endphp
</head>

3. Using Blade Directive

<head>
    {{-- Use current request URL --}}
    @canonical

    {{-- Specify custom path --}}
    @canonical('/products/item')

    {{-- Use variable --}}
    @canonical($canonicalPath)
</head>

All Three Methods Generate:

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

In Blade Templates (Facade)

Generate canonical URLs in your views using the Facade:

<head>
    <link rel="canonical" href="{{ Canonical::generate() }}">
</head>

Generate for Specific Paths

use Fkrzski\LaravelCanonical\Facades\Canonical;

// Current request URI
Canonical::generate(); // https://example.com/blog/post

// Override with a custom path
Canonical::generate('/products/item'); // https://example.com/products/item

// Current request with query parameters (preserved)
// Request: /search?q=laravel&page=2
Canonical::generate(); // https://example.com/search?q=laravel&page=2

// Override path even when on different URL
// Current: /old-url, Generate: /new-canonical-url
Canonical::generate('/new-canonical-url'); // https://example.com/new-canonical-url

URL Normalization

With CANONICAL_TRIM_TRAILING_SLASH=true (default):

  • Removes trailing slashes: /blog//blog
  • Preserves query parameters: /search?q=test stays intact
  • Normalizes root URL: /https://example.com

With CANONICAL_TRIM_TRAILING_SLASH=false (@since 1.1.0):

  • Preserves trailing slashes: /blog//blog/
  • Maintains original URL structure while still normalizing the domain
  • Useful when your application treats /blog and /blog/ as different routes

Use Cases

Prevent duplicate content penalties:

{{-- Both /blog and /blog/ point to same canonical --}}
<link rel="canonical" href="{{ Canonical::generate() }}">

Multi-domain environments:

// config/canonical.php
return [
    'domain' => env('CANONICAL_DOMAIN', config('app.url')),
];

Preserve URL structure (@since 1.1.0):

# When your app treats /page and /page/ differently
CANONICAL_TRIM_TRAILING_SLASH=false
{{-- /blog/ stays as /blog/ --}}
<link rel="canonical" href="{{ Canonical::generate() }}">

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.