PHPackages                             rankbeam/laravel-seo - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. rankbeam/laravel-seo

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

rankbeam/laravel-seo
====================

Open-core SEO infrastructure for Laravel: metadata, canonical URLs, social cards, linked JSON-LD, XML sitemaps and crawler controls - the free MIT core.

v3.12.0(1w ago)159↓50%1MITPHPPHP ^8.2CI passing

Since Jun 12Pushed 1w ago1 watchersCompare

[ Source](https://github.com/rankbeam/laravel-seo)[ Packagist](https://packagist.org/packages/rankbeam/laravel-seo)[ Docs](https://rankbeam.dev)[ RSS](/packages/rankbeam-laravel-seo/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (10)Dependencies (22)Versions (23)Used By (1)

Laravel SEO (core)
==================

[](#laravel-seo-core)

[![Tests](https://github.com/rankbeam/laravel-seo/actions/workflows/tests.yml/badge.svg)](https://github.com/rankbeam/laravel-seo/actions/workflows/tests.yml)[![Latest Version on Packagist](https://camo.githubusercontent.com/06cbeae570973cf6a794a58b63e0b821b8a3154312d66be3ef3b633580e74f08/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f72616e6b6265616d2f6c61726176656c2d73656f2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/rankbeam/laravel-seo)[![License: MIT](https://camo.githubusercontent.com/942e017bf0672002dd32a857c95d66f28c5900ab541838c6c664442516309c8a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)

The free MIT core of **[Rankbeam](https://rankbeam.dev)** — open-core SEO infrastructure for Laravel. This package resolves meta tags through a layered precedence chain and renders Open Graph / Twitter Cards, a linked `@id` JSON-LD schema graph, XML sitemaps and crawler controls, straight from your Laravel models and config. Production monitoring (Pro) and the Filament admin UI ship as separate packages — this one never pulls them in.

> **Upgrading from `fibonoir/laravel-seo` v1?** See [UPGRADING.md](UPGRADING.md) — v2 renames the vendor and carves the old "full suite" down to this core; the analyzer, scanner, redirect manager, 404 monitor, and admin UI live on as separate packages ([`laravel-seo-filament`](https://github.com/rankbeam/laravel-seo-filament), free; `laravel-seo-pro`, commercial).

What this package does
----------------------

[](#what-this-package-does)

AreaDetails**Meta resolution**`SEOResolver` merges six layers — config → global DB defaults → model-type defaults → route defaults → computed model values → explicit `seo_meta` values. Null never overwrites a lower layer.**Computed fallbacks**Title/description/image/robots derived from model attributes. Description candidates are configurable (`seo.computed.description_fields`), normalized (HTML stripped, entities decoded), and truncated at a word boundary (default 160 chars, no ellipsis). Per-model robots/`noindex` is built in — a `getSEORobots()` hook or an `is_indexable` attribute, overridable per page via `saveSEO(['robots' => …])`.**Rendering**`TagRenderer` outputs HTML (`@seo` Blade directives), structured arrays (Vue/React), or Inertia Head format. JSON-LD is emitted with `JSON_HEX_*` escaping so `` in content cannot break out of the script element.**Canonical policy**Derived canonicals (model URL / current URL) get the query string stripped; explicitly set canonicals are preserved verbatim.**Schema (JSON-LD)**Builders for Article, Breadcrumb, FAQ, LocalBusiness, Organization, Product; `SchemaGraph` for Organization/WebSite/WebPage nodes cross-linked via stable `@id`s; breadcrumbs from a page's ancestor chain with a loop guard.**Sitemaps**`SitemapBuilder` (wraps spatie/laravel-sitemap) with config-driven model sources, programmatic named sources via `SEO::sitemaps()->register(...)`, sitemap index support, `seo:sitemap` command, and `/sitemap.xml` routes that can be disabled. Sitemaps open as a readable, branded page in the browser via a [styled XSL stylesheet](https://rankbeam.dev/guide/sitemaps#styled-sitemap-in-the-browser) (on by default; search engines ignore it).**llms.txt**`seo:llms-txt` writes an optional markdown [`llms.txt`](https://llmstxt.org) index from the **same sources as the sitemap** (the registry + `seo.sitemap.models`), so the two never disagree. It's a compatibility file for tools that choose to consume it — Google Search does not use it. Served at `/llms.txt`, gated by config.**AI crawler control**`seo:robots-txt` renders a managed `robots.txt` (and `ai.txt`) from a doc-verified catalog of AI crawlers tagged by purpose — **allow the AI-search and assistant crawlers (`ai_search`/`ai_assistant`), disallow the ones that train on you (`ai_training`)** by default. `SEO::robotsTxt()->aiDirectives()` for a paste-able block; `SEO::aiCrawlers()` for the catalog + policy. Bots that ignore robots.txt are flagged advisory.**Markdown for bots**Content negotiation that serves clean **markdown** to AI crawlers instead of HTML — on `Accept: text/markdown`, `?format=md`, or (opt-in) a known AI crawler — from a model's `toSeoMarkdown()`, a `SEO::markdown()->register()` source, or a built title+description+content fallback. Off by default; never touches a normal visitor's response.**Indexing guard**Ties indexability to the Laravel *environment*: outside `seo.indexing_guard.allowed_environments` (default `['production']`) every page is forced to `noindex,nofollow` (above the whole precedence chain — overrides even a stored per-page value), `robots.txt`/`ai.txt` go disallow-all, and `seo:audit` warns. Stops a staging/local copy leaking into the index. **Off by default**, one-line opt-in `SEO_INDEXING_GUARD=true`, inert on production. See [Indexing guard](docs/guide/indexing-guard.md).**Generated OG images**Optional 1200×630 Open Graph images rendered by a real headless browser (`spatie/browsershot`) — correct multi-line wrapping, CJK/accents and truncation. Three publishable templates (default / article / product, selectable per model) + bundled OFL font; `seo:og-images` pre-generates and caches each card (content-hashed); the resolver serves it as a computed `og:image` fallback (existence-gated — never renders on a web request). **Off by default**, browser is a suggested dependency, static pre-generation only. See [Generated OG images](docs/guide/og-image.md).**Warnings**`SEOWarningEvaluator` for admin UIs: title &gt; 60 / description &gt; 160 warnings, manual-vs-fallback indicators, social-image dimension checks (min 200x200, ideal 1200x630, local files only).**Free audit**`seo:audit` — an in-process "what's wrong with my SEO right now" command (no queue, license, or network). Runs the metadata-class checks (missing / over- / under-length title &amp; description, OG image, robots conflicts, canonical format/cross-domain/shared/insecure, focus keyword) and prints a per-page pass/warn/fail table with an explicit capability matrix. `--strict` for CI, `--json` for tooling. No numerical score (that's Pro).**Explain resolution**`seo:explain "App\Models\Post" 42` — the resolver precedence trace: per field, the winning layer + value, the losing layers it overrode, and post-processing notes (title suffix, canonical strip, og:url derivation, image absolutization, indexing guard). Plus a site-level ledger (site name, default locale, canonical host) naming each value's source. Human `route:list`-style output + `--json`. Read-only; can't drift from what renders. See [Explain resolution](docs/guide/explain.md).**Migration importer**`seo:import-from ralphjsmit` — bulk-import SEO data from a competing Laravel package's storage into `seo_meta`. Idempotent, `--dry-run`, `--model=` scoping, explicit field mapping, morph rows re-resolved to the live model. See [Migrating from other packages](docs/guide/migrate-from-other-packages.md).**WordPress importer**`seo:import-from wordpress-csv` (a CSV export) and `seo:import-from yoast` / `rank-math` (the live WordPress DB via `--connection=`). Maps Yoast/Rank Math keys explicitly (incl. OG/Twitter overrides), resolves `%%title%%`-style template tokens, matches posts to your models by slug, and emits a redirects CSV for Pro. See [Migrating from WordPress](docs/guide/migrate-from-wordpress.md).**Database tables:** `seo_meta` (per-model explicit values, morph + locale) and `seo_defaults` (global/model-type/route defaults). Nothing else.

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11, 12, or 13 (CI runs the full matrix; Laravel 13 requires PHP 8.3+)
- `spatie/laravel-sitemap` ^7.0 or ^8.0 (suggested, required for sitemap generation)

Installation
------------

[](#installation)

```
composer require rankbeam/laravel-seo
php artisan vendor:publish --tag=seo-config
php artisan migrate
```

Quick start
-----------

[](#quick-start)

```
use Rankbeam\Seo\Traits\HasSEO;

class Post extends Model
{
    use HasSEO;

    public function getUrlForSEO(): string
    {
        return route('posts.show', $this);
    }
}
```

```

    @seo($post)

```

Explicit values from the admin side:

```
$post->saveSEO([
    'title' => 'Custom SEO Title',
    'description' => 'Custom meta description',
]);
```

Headless / Inertia:

```
use Rankbeam\Seo\Facades\SEO;

return Inertia::render('Post', [
    'seo' => SEO::forInertia($post),
]);
```

Sitemap sources:

```
// config/seo.php
'sitemap' => ['models' => [Post::class => ['priority' => 0.8]]],

// or programmatically (e.g. in a service provider)
SEO::sitemaps()->register('pages', fn () => ['/about', '/contact']);
```

Then generate the files (requires `spatie/laravel-sitemap`) — the package's `/sitemap.xml` route serves what this command writes:

```
composer require spatie/laravel-sitemap
php artisan seo:sitemap
```

Serving your own static `/sitemap.xml`? Disable the package routes:

```
// config/seo.php
'routes' => ['enabled' => false],
```

### Audit your SEO

[](#audit-your-seo)

```
# Audit the models under seo.audit.models / seo.sitemap.models
php artisan seo:audit

# Or target specific models, CI-fail on any issue, or emit JSON
php artisan seo:audit --model="App\Models\Post" --strict
php artisan seo:audit --json
```

A free, in-process pass/warn/fail report over the metadata-class checks. The rendered-HTML and live-canonical checks, and the numerical score, are part of the Pro scan — the command prints that boundary every run.

### Generate llms.txt

[](#generate-llmstxt)

```
php artisan seo:llms-txt            # writes public/llms.txt
php artisan seo:llms-txt --print    # print to stdout (dry run)
```

A markdown index of your site for AI crawlers ([llms.txt](https://llmstxt.org)), built from the **same sources as your sitemap** — registered sources plus `seo.sitemap.models`, with the same noindex/unpublished exclusions — so the two never disagree. It is served at `/llms.txt` (disable that route via `seo.llms_txt.route`), and you can schedule it alongside the sitemap:

```
Schedule::command('seo:llms-txt')->daily();
```

### AI crawler control (robots.txt / ai.txt)

[](#ai-crawler-control-robotstxt--aitxt)

```
php artisan seo:robots-txt          # writes public/robots.txt
php artisan seo:robots-txt --print  # print to stdout (dry run)
php artisan seo:robots-txt --ai-txt # also write public/ai.txt
```

A managed `robots.txt` for the AI era, rendered from a doc-verified catalog of AI crawlers tagged by purpose. The default policy **allows the AI-search and assistant crawlers (`ai_search` / `ai_assistant`) and disallows the ones that train on your content (`ai_training`)**; override per purpose or per bot in `seo.ai_crawlers`. Grab just the managed block for an existing file with `SEO::robotsTxt()->aiDirectives()`, or serve `/robots.txt` dynamically (off by default — it won't shadow a static file). Bots documented not to honour robots.txt are flagged advisory. See [AI crawler control](docs/guide/ai-crawlers.md).

Test status
-----------

[](#test-status)

`vendor/bin/pest` on `master`: **632 passed (1825 assertions), 0 failed** (plus 4 skipped by default: 3 Chrome-dependent OG-image smokes and 1 ext-xsl transform check) under PHP 8.4 / Laravel 13 (CI matrix: PHP 8.2–8.4 × Laravel 11/12/13).

```
git clone https://github.com/rankbeam/laravel-seo.git
cd laravel-seo
composer install
vendor/bin/pest
```

What is *not* in this package
-----------------------------

[](#what-is-not-in-this-package)

Queued site scans, content analysis, redirect manager, 404 monitor, and the SEO dashboard ship in `laravel-seo-pro` (commercial); the Filament admin form fields ship in `laravel-seo-filament` (free). The old `seo:install` stub-publishing flow is gone.

Contributing
------------

[](#contributing)

Bug reports, fixes and features are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md)for the package boundary (what belongs in core vs. the Filament/Pro packages), how to run the suite, the rendering contract, and the versioning/BC policy.

Security
--------

[](#security)

Please report security vulnerabilities privately, not in a public issue — see [SECURITY.md](SECURITY.md).

License
-------

[](#license)

MIT — see [LICENSE.md](LICENSE.md).

###  Health Score

47

—

FairBetter than 93% of packages

Maintenance98

Actively maintained with recent releases

Popularity14

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

21

Last Release

13d ago

Major Versions

v2.0.1 → v3.0.02026-06-15

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/176622217?v=4)[Valentin Goxhaj](/maintainers/Fibonoir)[@Fibonoir](https://github.com/Fibonoir)

---

Top Contributors

[![Fibonoir](https://avatars.githubusercontent.com/u/176622217?v=4)](https://github.com/Fibonoir "Fibonoir (179 commits)")

---

Tags

phplaravelschemaJSON-LDSitemapseostructured-dataopen-graphmeta-tagstwitter cardscanonical

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/rankbeam-laravel-seo/health.svg)

```
[![Health](https://phpackages.com/badges/rankbeam-laravel-seo/health.svg)](https://phpackages.com/packages/rankbeam-laravel-seo)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M348](/packages/psalm-plugin-laravel)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M134](/packages/roots-acorn)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M137](/packages/laravel-pulse)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)[mike-bronner/laravel-model-caching

Automatic caching for Eloquent models.

2.4k96.5k1](/packages/mike-bronner-laravel-model-caching)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
