achyutn / laravel-seo
An opinionated Laravel package to manage SEO easily.
Fund package maintenance!
Patreon
achyutkneupane
Other
Other
Installs: 214
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/achyutn/laravel-seo
Requires
- php: >=8.2
- ralphjsmit/laravel-seo: ^1.7
Requires (Dev)
- larastan/larastan: ^3.8
- laravel/pint: ^1.26
- orchestra/testbench: ^10.8
- pestphp/pest: ^3.8
- pestphp/pest-plugin-laravel: ^3.2
- pestphp/pest-plugin-livewire: ^3
- phpstan/phpstan: ^2.1
- rector/rector: ^2.3
README
An opinionated Laravel SEO package to manage SEO on Eloquent models. This package makes use of an un-opinionated package ralphjsmit/laravel-seo and adds a pattern of auto-generating SEO metadata and sitemaps for Eloquent models with customization.
This package lets you generate SEO metadata and sitemap directly from Eloquent models without manually wiring SEO data in controllers or views. It supports multiple schema types including Blog, Product, and generic Page schema.
Installation
You can install the package via composer:
composer require achyutn/laravel-seo
You must publish package config and migration stubs to your application using the following command:
php artisan vendor:publish --tag="laravel-seo"
This generates a config/seo.php configuration file and a migration file
for the seo table in your database.
ralphjsmit/laravel-seowill also be installed as a dependency. Publishing the configuration and migration of that package will break the functionality of this package.
If you want full customization, I recommend you to check out that package directly from its GitHub repository.
Next, run the migration to create the seo table:
php artisan migrate
Usage
To use the package, simply add the AchyutN\LaravelSEO\Traits\InteractsWithSEO trait to any Eloquent model
you want to manage SEO for.
use AchyutN\LaravelSEO\Traits\InteractsWithSEO; class Post extends Model { use InteractsWithSEO; // ... }
This will automatically use the default columns (title, description, etc). You can also auto-generate breadcrumbs and schema markup for your model by implementing the respective methods or traits.
Generate SEO Entries
After adding the trait to your model, you need to generate SEO entries for existing records. You can do this by running the following Artisan command:
php artisan seo:generate
It also supports re-generating SEO entries for models that already have SEO data.
You can use the --regenerate flag to update existing entries:
php artisan seo:generate --regenerate
Schema Types
This package supports multiple schema types using traits:
- BlogSchema for blog posts
- ProductSchema for products (e-commerce)
- PageSchema for generic pages
Each schema trait implements a buildSchema(SchemaCollection $schema, ResolvedSEO $resolvedSEO) method, which receives resolved SEO data from your model. To use any schema, add the corresponding trait to your model along with the interface AchyutN\LaravelSEO\Contracts\HasMarkup.
Blog Schema
To use the Blog schema, add the AchyutN\LaravelSEO\Schemas\BlogSchema trait to your model:
use AchyutN\LaravelSEO\Contracts\HasMarkup; use AchyutN\LaravelSEO\Schemas\BlogSchema; class Post extends Model implements HasMarkup { use InteractsWithSEO; use BlogSchema; // ... }
Product Schema
To use the Product schema, add the AchyutN\LaravelSEO\Schemas\ProductSchema trait to your model:
use AchyutN\LaravelSEO\Contracts\HasMarkup; use AchyutN\LaravelSEO\Schemas\ProductSchema; class Product extends Model implements HasMarkup { use InteractsWithSEO; use ProductSchema; // ... }
Page Schema
To use the Page schema, add the AchyutN\LaravelSEO\Schemas\PageSchema trait to your model:
use AchyutN\LaravelSEO\Contracts\HasMarkup; use AchyutN\LaravelSEO\Schemas\PageSchema; class Page extends Model implements HasMarkup { use InteractsWithSEO; use PageSchema; // ... }
Breadcrumbs
You can also manage breadcrumbs by defining a breadcrumbs() method on your model that returns an array of Breadcrumb items.
use AchyutN\LaravelSEO\Data\Breadcrumb; class Post extends Model { use InteractsWithSEO; public function breadcrumbs(): array { return [ new Breadcrumb(label: 'Home', url: route('home')), new Breadcrumb(label: 'Blog', url: route('blog.index')), new Breadcrumb(label: $this->title, url: route('blog.show', $this)), ]; } }
Rendering SEO Tags
To render the SEO tags in your views, you can use the following Blade directive:
{!! seo($model) !!}
Replace $model with the instance of your Eloquent model.
Sitemaps
Once you have models using the InteractsWithSEO trait, you automatically have them included in your sitemap.
You can access the sitemap in two formats:
- XML Sitemap:
/sitemap.xml - TXT Sitemap:
/sitemap.txt
The XML sitemap will be auto-injected in your blade layout along with the metadata.
Customization
This package resolves SEO data using a simple priority order:
- A custom
*Value()method, if defined on the model - A custom
$*Columnproperty, if defined on the model - A default column name
You can customize each field independently.
Resolution Priority
For each field:
*Value()method$*Columnproperty- Default column name
Methods always take precedence over properties.
Supported Override Methods
Define these on your model when the value is computed or derived. Organized by context:
Common Methods
| Method | Return Type | When to use |
|---|---|---|
titleValue() |
?string |
Computed or dynamic title |
descriptionValue() |
?string |
Generated description |
categoryValue() |
?string |
Derived category |
imageValue() |
?string |
Media URL |
authorValue() |
?string |
Relation-based author |
authorUrlValue() |
?string |
Author profile link |
publisherValue() |
?string |
Brand or company name |
publisherUrlValue() |
?string |
Publisher homepage |
tagsValue() |
array<string> |
Normalized tags |
urlValue() |
?string |
The page URL |
publishedAtValue() |
?Carbon |
Computed publish date |
modifiedAtValue() |
?Carbon |
Computed updated date |
pageTypeValue() |
?string |
Custom page type |
Product-Specific Methods
| Method | Return Type | When to use |
|---|---|---|
brandValue() |
?string |
Product brand |
priceValue() |
?float |
Product price |
discountPriceValue() |
?float |
Discounted price |
currencyValue() |
?string |
Price currency |
availabilityValue() |
bool |
Product availability |
skuValue() |
?string |
Product SKU |
Page-Specific Methods
| Method | Return Type | When to use |
|---|---|---|
pageTypeValue() |
?string |
Type of page (landing, about, etc.) |
Example
class Product extends Model { use InteractsWithSEO; protected function priceValue(): ?float { return $this->price; } protected function availabilityValue(): bool { return $this->is_available; } }
Supported Properties
Define these on your Eloquent model to change which column is used. Organized by context:
Common Properties
| Property | Default | Purpose |
|---|---|---|
$titleColumn |
title |
Page title |
$descriptionColumn |
description |
Meta description |
$categoryColumn |
category |
Content category |
$imageColumn |
image |
Open Graph image |
$authorColumn |
author |
Author name |
$authorUrlColumn |
author_url |
Author profile URL |
$publisherColumn |
publisher |
Publisher name |
$publisherUrlColumn |
publisher_url |
Publisher URL |
$tagsColumn |
tags |
Tags or keywords |
$urlColumn |
url |
The page URL |
$publishedAtColumn |
created_at |
Publish date |
$modifiedAtColumn |
updated_at |
Updated date |
$pageTypeColumn |
page_type |
Page type |
Product-Specific Properties
| Property | Default | Purpose |
|---|---|---|
$brandColumn |
brand |
Product brand |
$priceColumn |
price |
Product price |
$discountPriceColumn |
discount_price |
Discounted price |
$currencyColumn |
currency |
Price currency |
$availabilityColumn |
is_available |
Product availability |
$skuColumn |
sku |
Product SKU |
Example
class Product extends Model { use InteractsWithSEO; protected string $priceColumn = 'product_price'; protected string $brandColumn = 'product_brand'; }
Notes
- All overrides are optional
- Do not define both a property and a method unless intentional
- IDEs and static analyzers understand all extension points via PHPDoc
License
This package is open-sourced software licensed under the MIT license.
Contributing
Contributions are welcome! Please create a pull request or open an issue if you find any bugs or have feature requests.
Support
If you find this package useful, please consider starring the repository on GitHub to show your support.