Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Seo Laravel Package

archtechx/laravel-seo

ArchTech's Laravel SEO package gives your app a simple, fluent API for managing meta tags, titles, descriptions, Open Graph and Twitter card data, canonical URLs and robots directives, so every page renders clean, customizable SEO tags without extra boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the package: composer require archtechx/laravel-seo.

  2. Publish the config: php artisan vendor:publish --tag="seo-config". This creates config/seo.php, where you set the site name, site URL, default title/description/image, and the templates used to compose titles (e.g. appending the site name, or falling back to parent defaults).

  3. If you want per-record SEO (blog posts, products, landing pages), publish and run the migrations, then add the HasSEO trait to the relevant Eloquent models. The trait wires up a polymorphic relationship so metadata lives in its own table rather than in columns on your content tables.

  4. Drop <x-seo::meta /> into your main layout's <head>. This one component renders the <title>, meta description, canonical URL, Open Graph tags, Twitter card tags, and any JSON-LD you've attached — nothing else needs to be in the head for basic use.

  5. First use case: a blog post. Add use HasSEO; to Post, then in your controller (or a view composer):

    $post->seo()
        ->title($post->title)
        ->description($post->excerpt)
        ->image($post->cover_url);
    

    View-source the page — the tags should render with no further wiring.

Where to look first: config/seo.php for defaults and templating, the SeoData class for the full fluent API, and the package's published views if you need to understand exactly which tags are emitted.

Implementation Patterns

Site defaults plus per-page overrides. Set sensible defaults in config/seo.php (site name, image fallback, title template). Pages that need something specific override only the fields they care about — you should never be forced to re-specify og:site_name or the fallback image on every page.

Two flavours of SEO, pick per route. Persistent, model-backed SEO (HasSEO + ->seo()) is right for content that editors manage or that changes per record. Ephemeral, request-scoped SEO (Seo::make()->title(...)) is right for static pages, landing pages, and search results where there's no meaningful database row to attach metadata to.

Render once, in the layout. Put <x-seo::meta /> in your single base layout. Per-page data flows in from the controller/model; the component handles the rest. This keeps tag ordering consistent and avoids duplicate-tag bugs.

Templating for titles. Use the config title template for the common "Page Title — Site Name" pattern rather than string-concatenating in every controller. Templates keep the separator and fallback behaviour in one place.

Eager load the relationship. On index/listing pages that iterate models, add ->with('seo') (or the equivalent relationship name) to the query. Without it you'll get an N+1 for every card.

Structured data. For articles and products, attach JSON-LD alongside the meta tags so @type, headline, author, and image are emitted from the same source of truth as your OG tags.

Testing. Assert rendered output rather than internal state — $response->assertSee('<meta property="og:title"', false) catches regressions in the component or template config that unit tests on SeoData would miss.

Gotchas and Tips

  • Config caching. If php artisan config:cache has been run, edits to config/seo.php are ignored until you clear and re-cache. This is the single most common "my defaults aren't applying" cause.
  • Migrations for model-based SEO. The trait alone isn't enough — without the published migration and a php artisan migrate, ->seo() will fail with a missing-table error that's easy to misread as a package bug.
  • Don't double up. Remove any hardcoded <title> or hand-written OG tags from your layout when you add the component, or you'll ship two of everything.
  • Head placement. The component belongs inside <head>; rendering it in <body> will usually still work in browsers but breaks validators and some crawlers.
  • Canonical URLs. Set the app URL correctly and be deliberate about canonical on paginated and filtered pages — this is the field most likely to silently hurt you in search results.
  • Laravel 13 support (v0.10.4). The package now declares Laravel 13 compatibility. If you were pinned below this release, widen your laravel/framework constraint and re-run the test suite — the bump is additive, but validate your Blade layouts still render the component unchanged.
  • Intervention Image v3 (v0.10.4). The package now targets Intervention Image v3. If your application (or an OG-image pipeline of your own) still requires v2, pin intervention/image explicitly in composer.json before upgrading, otherwise Composer may resolve a version your image code doesn't expect. Check composer why intervention/image after the bump to confirm what pulled it in.
  • Extension points. Views are publishable, so tag ordering and markup can be customised without forking. SeoData is the natural place to put app-specific helpers (e.g. a ->article(Post $post) shortcut) rather than repeating ten chained calls per controller.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager