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
Requires
- php: ^8.3
- illuminate/support: ^11.0 | ^12.0
Requires (Dev)
- driftingly/rector-laravel: ^2.0.7
- larastan/larastan: ^3.0
- laravel/pint: ^1.17
- mockery/mockery: ^1.6
- orchestra/testbench: ^9.0 | ^10.5
- pestphp/pest: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- pestphp/pest-plugin-profanity: ^4.0
- pestphp/pest-plugin-type-coverage: ^4.0
- rector/rector: ^2.1.2
- symfony/var-dumper: ^7.0
This package is auto-updated.
Last update: 2025-11-06 18:07:58 UTC
README
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=teststays 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
/blogand/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.