Weave Code
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

ralphjsmit/laravel-seo

Out-of-the-box SEO for Laravel models: automatically generates title, meta, OpenGraph, Twitter, structured data, robots, alternates and favicon tags. Store per-model SEO or derive it dynamically, then render everything with a simple seo()->for($model) call.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require ralphjsmit/laravel-seo
    php artisan vendor:publish --tag="seo-migrations"
    php artisan vendor:publish --tag="seo-config"
    php artisan migrate
    
  2. Configure: Edit config/seo.php to set site-wide defaults (e.g., site_name, favicon, robots).

  3. First Use Case: Add the HasSEO trait to a model (e.g., Post):

    use RalphJSmit\Laravel\SEO\Support\HasSEO;
    
    class Post extends Model
    {
        use HasSEO;
    }
    

    Then render SEO tags in a Blade view:

    {!! seo()->for($post) !!}
    

Implementation Patterns

Core Workflows

  1. Model Integration:

    • Use HasSEO trait to auto-associate a SEO model with your Eloquent model.
    • Update SEO data via the seo relationship:
      $post->seo->update([
          'title' => 'Updated Title',
          'description' => 'Updated description...',
      ]);
      
  2. Dynamic SEO Data: Override getDynamicSEOData() to fetch SEO data dynamically:

    public function getDynamicSEOData(): SEOData
    {
        return new SEOData(
            title: $this->title,
            description: $this->excerpt,
            image: $this->featuredImagePath,
        );
    }
    
  3. Controller-Driven SEO: Pass SEOData directly from a controller:

    return view('page', [
        'SEOData' => new SEOData(
            title: 'Custom Title',
            description: 'Custom description...',
        ),
    ]);
    

    Render in Blade:

    {!! seo($SEOData) !!}
    
  4. Structured Data: Use SchemaCollection to generate JSON-LD:

    use RalphJSmit\Laravel\SEO\Support\Schema\Article;
    
    $schema = new SchemaCollection([
        new Article(
            headline: $post->title,
            description: $post->excerpt,
            datePublished: $post->published_at,
        ),
    ]);
    
    return new SEOData(schema: $schema);
    
  5. Fallbacks: Configure defaults in config/seo.php (e.g., title.suffix, description.fallback).


Integration Tips

  • Blade Directives: Use {!! seo()->for($model) !!} in layouts to avoid repetition. For dynamic routes (e.g., Inertia.js), leverage enableTitleSuffix: false in SEOData.

  • Middleware: Attach SEO data in middleware for API responses or non-model pages:

    public function handle($request, Closure $next)
    {
        $response = $next($request);
        $response->headers->set('X-SEO-Data', json_encode($seoData));
        return $response;
    }
    
  • Testing: Mock SEOData in tests:

    $this->view->share('SEOData', new SEOData(title: 'Test Title'));
    

Gotchas and Tips

Pitfalls

  1. Image Paths: Ensure image paths in SEOData are relative to public_path() or use absolute URLs. The package uses secure_url(), which resolves paths via public_path().

  2. Title Suffix: The title.suffix in config is not appended to the homepage by default. Set config('seo.title.homepage_title') explicitly if needed.

  3. Robots Tag: If robots.force_default is true, manual overrides via SEOData->robots are ignored. Use SEOData->markAsNoIndex() instead.

  4. Dynamic Data Overrides: The priority order for SEO data is:

    1. SEOManager::SEODataTransformer (lowest priority).
    2. getDynamicSEOData().
    3. Associated SEO model.
    4. Config defaults (highest priority). Debug by checking SEOManager::getSEOData() output.
  5. Alternate Tags: Ensure alternates in SEOData use absolute URLs (e.g., https://example.com/en). Relative paths may break hreflang tags.

  6. Schema Validation: Structured data (e.g., Article) requires valid datePublished/modified_time (Carbon instances). Invalid dates may cause rendering errors.


Debugging Tips

  1. Inspect Generated Tags: Use SEOManager::getSEOData($model)->toArray() to debug raw data before rendering.

  2. Disable Inertia Attribute: Add enableInertia: false to SEOData if titles flicker in SPAs:

    new SEOData(enableInertia: false)
    
  3. Clear Cached Config: If changes to config/seo.php aren’t reflected, clear the config cache:

    php artisan config:clear
    
  4. Favicon Issues: Verify favicon path in config points to a valid file (e.g., public/favicon.ico). Supported formats: ico, png, svg.

  5. Locale Handling: Override locale in SEOData for multilingual sites:

    new SEOData(locale: 'fr')
    

Extension Points

  1. Custom Transformers: Extend SEO data generation via SEOManager::SEODataTransformer:

    SEOManager::SEODataTransformer(function ($data, $model) {
        if ($model instanceof Post) {
            $data->tags = ['laravel', 'seo'];
        }
        return $data;
    });
    
  2. Custom Schema Types: Extend SchemaCollection for new JSON-LD types:

    class CustomSchema extends Schema
    {
        public function toJsonLd(): array
        {
            return ['@type' => 'CustomType', 'property' => 'value'];
        }
    }
    
  3. Override Defaults: Dynamically modify config values in a service provider:

    SEOManager::setConfig('robots.default', 'noindex,nofollow');
    
  4. Event Listeners: Trigger actions on SEO updates via model observers:

    class PostObserver
    {
        public function saved(Post $post)
        {
            if ($post->wasChanged('title')) {
                $post->seo->update(['title' => $post->title]);
            }
        }
    }
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport