lee-to/laravel-seo-by-url
Laravel package for managing SEO metadata by URL. Define titles, descriptions, keywords, and Open Graph tags for specific paths, then let your app resolve the right meta tags automatically for each request. Simplifies per-page SEO without hardcoding views.
Install the package and publish its assets:
composer require lee-to/laravel-seo-by-url
php artisan vendor:publish --tag="seo-by-url-config"
Check the published config/seo-by-url.php first — it defines where SEO rules are stored, how URLs are matched, and whether caching is enabled.
Run migrations if the package ships a storage table for URL-based SEO records:
php artisan migrate
Render the meta tags in your layout head. The package exposes a SeoMeta value object (recently fixed in 2.2.1) that represents the resolved metadata for the current request:
{!! seo()->forCurrentUrl() !!}
or, if you prefer explicit objects:
$meta = SeoMeta::forUrl(request()->url());
First use case: map a URL (or URL pattern) to a title/description/OG block, then confirm the rendered <head> contains the expected tags. Start with a single static page before wiring up wildcard patterns.
If you were on 2.2.0, upgrade to 2.2.1 — this release fixes a defect in the SeoMeta class, so any custom code that instantiates or extends SeoMeta should be re-tested after composer update.
Pattern-based rules over per-page records. Define SEO for URL patterns rather than every route. Wildcards and parameterized segments keep the rule table small and make new content pages inherit sane defaults automatically.
Model-driven overrides. Keep the "default rule" in config/pattern storage, and let an Eloquent model (page, product, post) supply title, description, and og_image when present. Resolve in that order: explicit model → URL pattern rule → global fallback. This avoids editing SEO records every time content is created.
Middleware for resolution. Resolve SEO early (middleware) and expose it via a container binding or facade. Controllers, API resources, and the Blade head partial then read the same resolved object instead of each recomputing URL matching.
Blade head component. Wrap the output in a single <x-seo-head /> component so canonical URL, Open Graph, Twitter cards, and robots directives are emitted consistently. Keeping one output path means a fix like the 2.2.1 SeoMeta patch propagates everywhere at once.
Caching with URL-scoped keys. Cache resolved SEO per normalized URL (seo:url:{hash}) with a TTL. Invalidate on model save/delete by tagging or by deleting the affected URL keys — otherwise edited titles linger in the cache.
Multi-locale handling. If your app is localized, include the locale in both the cache key and the URL lookup so /en/about and /de/about resolve independently, and emit hreflang alternates alongside the canonical.
Sitemap integration. Reuse the same URL-rule source when generating sitemap.xml so the set of indexable URLs and their metadata stay in sync.
www vs. non-www, and locale prefixes will silently miss your rules. Normalize once, in one place, and match against that canonical form.2.2.1 — verify the SeoMeta surface. Since the fix touches the SeoMeta class, re-check anything that constructs it directly, extends it, or relies on its getter output. Add a small feature test asserting the rendered <head> for one representative page so future patches are caught.request()->url() can report the wrong scheme or host, producing broken canonicals. Configure trusted proxies (TrustProxies middleware) before blaming the package./blog/* vs. /blog/laravel-seo) rather than assuming.config/seo-by-url.php in production, run php artisan config:cache — otherwise stale config produces confusing "my rule is ignored" behaviour.null or an empty string; empty strings are commonly filtered out of output.SeoMeta for a given URL — far faster than inspecting rendered HTML when a pattern doesn't match.composer update to patch releases like 2.2.1 painless.How can I help you explore Laravel packages today?