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

Schema Org Laravel Package

spatie/schema-org

Fluent PHP builder for the full Schema.org vocabulary. Create Schema.org types and properties via chainable methods and output valid JSON-LD/ld+json scripts for SEO. Auto-generated from Schema.org standards for complete coverage.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require spatie/schema-org
    

    Add to composer.json if using Laravel’s autoloader.

  2. First Use Case: Generate a simple LocalBusiness schema for SEO:

    use Spatie\SchemaOrg\Schema;
    
    $business = Schema::localBusiness()
        ->name('Acme Corp')
        ->email('contact@acme.com')
        ->telephone('+123456789');
    
    echo $business->toScript();
    

    Outputs:

    <script type="application/ld+json">
    {
        "@context": "https://schema.org",
        "@type": "LocalBusiness",
        "name": "Acme Corp",
        "email": "contact@acme.com",
        "telephone": "+123456789"
    }
    </script>
    
  3. Where to Look First:

    • Source Code: src/ for type definitions (auto-generated from Schema.org).
    • Schema.org Docs: schema.org for property/value constraints.
    • Laravel Integration: Use Blade directives or service providers to centralize schema generation.

Implementation Patterns

Core Workflows

  1. Fluent Builder Pattern: Chain methods for readability:

    $article = Schema::article()
        ->headline('Laravel 11 Released')
        ->datePublished('2024-01-01')
        ->author($graph->person('author1')->name('Jane Doe'));
    
  2. Graph for Complex Relationships: Use Graph to manage interconnected schemas (e.g., Product + Offer + Organization):

    $graph = new Graph();
    $graph->product()
        ->name('Premium Widget')
        ->brand($graph->organization()->name('Acme Inc'))
        ->offers(Schema::offer()->price(99.99)->currency('USD'));
    echo $graph->toScript(); // Renders all linked schemas
    
  3. Conditional Properties: Avoid breaking chains with if():

    $schema = Schema::localBusiness()
        ->name('Store')
        ->if($hasEmail, fn($s) => $s->email('info@example.com'));
    
  4. Multi-Typed Entities (MTE): For hybrid schemas (e.g., HotelRoom + Product):

    $mte = new MultiTypedEntity();
    $mte->hotelRoom()->name('Suite A');
    $mte->product()->aggregateRating(Schema::aggregateRating()->ratingValue(4.5));
    
  5. Dynamic Properties: Use setProperty() for non-standard Schema.org fields (e.g., custom extensions):

    $schema->setProperty('customField', 'value');
    

Laravel-Specific Patterns

  1. Service Provider: Register a singleton for global schema access:

    // app/Providers/SchemaServiceProvider.php
    public function register()
    {
        $this->app->singleton('schema', fn() => new Schema());
    }
    
  2. Blade Directives: Create a @schema directive for views:

    // app/Providers/BladeServiceProvider.php
    Blade::directive('schema', function ($expression) {
        return "<?php echo app('schema')->{$expression}->toScript(); ?>";
    });
    

    Usage:

    @schema("localBusiness()->name('Store')")
    
  3. Model Observers: Auto-generate schemas on model events (e.g., saved):

    // app/Observers/ProductObserver.php
    public function saved(Product $product)
    {
        $schema = Schema::product()
            ->name($product->name)
            ->sku($product->sku);
        $product->schema = $schema->toScript();
        $product->save();
    }
    
  4. SEO Meta Tags: Inject schemas into <head> via a view composer:

    // app/Providers/AppServiceProvider.php
    public function boot()
    {
        View::composer('*', function ($view) {
            $view->with('schema', Schema::organization()->name(config('app.name')));
        });
    }
    

Gotchas and Tips

Pitfalls

  1. HTML Injection in toScript():

    • Issue: Values containing </script> break the generated script tag.
    • Fix: Use toArray() or json_encode() for dynamic content, or escape manually:
      $schema->description(htmlspecialchars($userInput));
      
    • Since v4.0.2: Automatically escapes </> to \u003C/\u003E.
  2. Circular References:

    • Issue: Nested schemas (e.g., author in article) may cause infinite loops in toArray().
    • Fix: Use Graph or manually set @id:
      $author = Schema::person()->name('John');
      $author->setId('https://example.com/authors/john');
      $article->author($author);
      
  3. Reserved Keywords:

    • Issue: Float type is unavailable (PHP reserved word).
    • Workaround: Use float strings or number type.
  4. Missing Types:

    • Issue: Physician type is excluded (health extension).
    • Workaround: Use MedicalEntity or extend the package.
  5. Array vs. Single Values:

    • Issue: Properties like sameAs accept arrays but may fail if passed as a string.
    • Fix: Always use arrays for multi-value properties:
      ->sameAs(['https://url1.com', 'https://url2.com']);
      

Debugging Tips

  1. Validate with Google’s Tool: Use Rich Results Test to catch errors early.

  2. Inspect Raw Output:

    dd($schema->toArray()); // Debug structure
    
  3. Check for Deprecated Methods:

    • Example: identifier@id (since v2.6.0).
  4. Type-Safe Enumerations: Use constants for predefined values (e.g., BookFormatType::Hardcover).

Performance Tips

  1. Reuse Instances: Cache frequently used schemas (e.g., Organization for all products):

    $company = Schema::organization()->name('Acme');
    // Reuse $company across multiple products
    
  2. Lazy Loading: Defer schema generation until needed (e.g., in a getSchema() method).

  3. Minimize Graph Size: Use hide() to exclude helper schemas:

    $graph->hide(Organization::class); // Exclude from output
    

Extension Points

  1. Custom Types: Extend SchemaOrg\Type for domain-specific schemas:

    class CustomType extends \Spatie\SchemaOrg\Type
    {
        public function customMethod($value)
        {
            $this->setProperty('customField', $value);
            return $this;
        }
    }
    
  2. Override Property Handling: Extend SchemaOrg\Property to validate or transform values:

    class CustomProperty extends \Spatie\SchemaOrg\Property
    {
        public function __construct($name, $value)
        {
            parent::__construct($name, strtoupper($value));
        }
    }
    
  3. Modify Generation: Override toArray() or toScript() in a custom class:

    class CustomSchema extends \Spatie\SchemaOrg\Schema
    {
        public function toScript()
        {
            $array = $this->toArray();
            $array['@context'] = 'https://custom.org';
            return '<script type="application/ld+json">' . json_encode($array) . '</script>';
        }
    }
    
  4. Integrate with Laravel Scout: Use schemas for search engine optimization:

    $product->searchableAs('product')->addSelectableAttributes(['schema']);
    
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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai