elegantly / laravel-seo
An Elegant & flexible SEO tag builder for Laravel
Fund package maintenance!
Elegantly
Requires
- php: ^8.2
- illuminate/contracts: ^10.0||^11.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^2.9
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.1.1||^7.10.0
- orchestra/testbench: ^9.0.0||^8.22.0
- pestphp/pest: ^2.34
- pestphp/pest-plugin-arch: ^2.7
- pestphp/pest-plugin-laravel: ^2.3
- phpstan/extension-installer: ^1.3
- phpstan/phpstan-deprecation-rules: ^1.1
- phpstan/phpstan-phpunit: ^1.3
README
Introduction
laravel-seo
is a flexible and powerful package for managing SEO tags in Laravel applications.
With this package, you can easily handle:
- Standard HTML tags like
<title>
and<meta name="robots">
- Localization with alternate tags (Google SEO Localization)
- Open Graph tags with structured properties, arrays, and object types
- Twitter (X) tags
- Structured data (JSON-LD)
Installation
You can install the package via Composer:
composer require elegantly/laravel-seo
Next, publish the config file:
php artisan vendor:publish --tag="seo-config"
Config File Overview
The configuration file (config/seo.php
) allows you to customize the default SEO behavior for your application. Here's a snippet with all available settings:
return [ 'defaults' => [ /* |-------------------------------------------------------------------------- | Default Title |-------------------------------------------------------------------------- | | This is the default value used for <title>, "og:title", "twitter:title" | */ 'title' => env('APP_NAME', 'Laravel'), /* |-------------------------------------------------------------------------- | Default Description |-------------------------------------------------------------------------- | | This is the default value used for <meta name="description">, | <meta property="og:description">, <meta name="twitter:description"> | */ 'description' => null, /* |-------------------------------------------------------------------------- | Default Author |-------------------------------------------------------------------------- | | This is the default value used for <meta name="author"> | */ 'author' => null, /* |-------------------------------------------------------------------------- | Default Generator |-------------------------------------------------------------------------- | | This is the default value used for <meta name="generator"> | */ 'generator' => null, /* |-------------------------------------------------------------------------- | Default Keywords |-------------------------------------------------------------------------- | | This is the default value used for <meta name="keywords"> | Types supported: string or array of strings | */ 'keywords' => null, /* |-------------------------------------------------------------------------- | Default Referrer |-------------------------------------------------------------------------- | | This is the default value used for <meta name="referrer"> | */ 'referrer' => null, /* |-------------------------------------------------------------------------- | Default Theme color |-------------------------------------------------------------------------- | | This is the default value used for <meta name="theme-color"> | */ 'theme-color' => null, /* |-------------------------------------------------------------------------- | Default Color Scheme |-------------------------------------------------------------------------- | | This is the default value used for <meta name="color-scheme"> | */ 'color-scheme' => null, /* |-------------------------------------------------------------------------- | Default Image path |-------------------------------------------------------------------------- | | This is the default value used for <meta property="og:image">, <meta name="twitter:image"> | You can use relative path like "/opengraph.png" or url like "https://example.com/opengraph.png" | */ 'image' => null, /* |-------------------------------------------------------------------------- | Default Robots |-------------------------------------------------------------------------- | | This is the default value used for <meta name="robots"> | See Google documentation here: https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag?hl=fr#directives | */ 'robots' => 'max-snippet:-1,max-image-preview:large,max-video-preview:-1', /* |-------------------------------------------------------------------------- | Default Sitemap path |-------------------------------------------------------------------------- | | This is the default value used for <link rel="sitemap"> | You can use relative path like "/sitemap.xml" or url like "https://example.com/sitemap.xml" | */ 'sitemap' => null, ], /** * @see https://ogp.me/ */ 'opengraph' => [ /* |-------------------------------------------------------------------------- | Default Site Name |-------------------------------------------------------------------------- | | This is the default value used for <meta property="og:site_name" /> | If null: config('app.name') is used. | */ 'site_name' => null, /* |-------------------------------------------------------------------------- | Default Determiner |-------------------------------------------------------------------------- | | This is the default value used for <meta property="og:determiner" /> | Possible values are: a, an, the, "", auto | */ 'determiner' => '', ], /** * @see https://developer.x.com/en/docs/x-for-websites/cards/overview/abouts-cards */ 'twitter' => [ /* |-------------------------------------------------------------------------- | Default Twitter username |-------------------------------------------------------------------------- | | This is the default value used for <meta name="twitter:site" /> | Example: @X | */ 'site' => null, ], /** * @see https://schema.org/WebPage */ 'schema' => [ /* |-------------------------------------------------------------------------- | Default WebPage schema |-------------------------------------------------------------------------- | | This is the default value used for the schema WebPage | @see https://schema.org/WebPage for all available properties | */ 'webpage' => [], ], ];
Usage
Displaying SEO Tags
You can easily render all SEO tags in your Blade views by calling the seo()
helper function:
<head> {!! seo() !!} </head>
This will render all the default tags, for example:
<title>Home</title> <meta name="robots" content="max-snippet:-1,max-image-preview:large,max-video-preview:-1" /> <link rel="canonical" href="https://example.com" /> <!-- Open Graph --> <meta property="og:title" content="Home" /> <meta property="og:url" content="https://example.com" /> <meta property="og:locale" content="en" /> <meta property="og:site_name" content="My App" /> <meta property="og:type" content="website" /> <!-- Twitter (X) --> <meta name="twitter:card" content="summary" /> <meta name="twitter:title" content="Home" /> <!-- JSON-LD --> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "WebPage", "name": "Home", "url": "https://example.com" } </script>
Setting SEO Tags in Controllers
You will typically want to define your SEO tags dynamically in your controllers. You can do this using either the seo()
helper or the SeoManager
facade:
namespace App\Http\Controllers; use \Elegantly\Seo\Facades\SeoManager; use Elegantly\Seo\Standard\Alternate; class HomeController extends Controller { public function __invoke() { // Using the helper seo() ->setTitle("Homepage") ->setImage(asset('images/opengraph.jpg')) ->setDescription("The homepage description") ->when(!App::isProduction(), fn($seo) => $seo->noIndex()) ->setLocale("fr") ->setAlternates([ new Alternate( hreflang: "en", href: route('home', ['locale' => "en"]), ), new Alternate( hreflang: "fr", href: route('home', ['locale' => "fr"]), ), ]) ->setOpengraph(function(OpenGraph $opengraph){ $opengraph->title = "Custom opengraph title"; return $opengraph; }); // Using the facade SeoManager::current() ->setTitle("Homepage") ->setDescription("The homepage description"); // ... return view('home'); } }
Then, in your Blade view, just render the tags like this:
<head> {!! seo() !!} </head>
Advanced Usage
For more complex SEO needs, you can instantiate and configure the SeoManager
class directly. This gives you full control over every tag, including Open Graph, Twitter, JSON-LD, and custom schema tags.
use Elegantly\Seo\SeoManager; use Elegantly\Seo\Standard\Standard; use Elegantly\Seo\OpenGraph\OpenGraph; use Elegantly\Seo\Twitter\Cards\Card; use Elegantly\Seo\Schemas\Schema; use Elegantly\Seo\SeoTags; $seo = new SeoManager( standard: new Standard(/* ... */), opengraph: new OpenGraph(/* ... */), twitter: new Card(/* ... */), webpage: new WebPage(/* ... */), schemas: [/* ... */], customTags: new SeoTags(/* ... */) );
Then, in your Blade view:
<head> {!! $seo !!} </head>
Testing
To run the tests:
composer test
Changelog
Please see CHANGELOG for details on recent updates.
Contributing
See CONTRIBUTING for guidelines on contributing to this project.
Security
Please refer to our security policy for reporting vulnerabilities.
Credits
License
This package is licensed under the MIT License.