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

Seo Bundle Laravel Package

sonata-project/seo-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require sonata-project/seo-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        SonataSeoBundle::class => ['all' => true],
    ];
    
  2. Configuration: Add basic SEO settings in config/packages/sonata_seo.yaml:

    sonata_seo:
        title: "Default Title"
        description: "Default Description"
        keywords: "default, keywords"
        robots: "index, follow"
        meta:
            property: "value"
    
  3. First Use Case: Override SEO metadata for a route in a controller:

    use Sonata\SeoBundle\Model\SeoMetadataInterface;
    
    public function showAction(SeoMetadataInterface $metadata): Response
    {
        $metadata->setTitle('Custom Page Title');
        $metadata->setDescription('Custom description for SEO');
    
        return $this->render('page/show.html.twig', [
            'metadata' => $metadata,
        ]);
    }
    
  4. Twig Integration: Use the sonata_seo Twig extension to render metadata in templates:

    {{ sonata_seo.render() }}
    

Implementation Patterns

Core Workflows

  1. Dynamic Metadata Handling:

    • Use SeoMetadataInterface in controllers to dynamically set metadata per route.
    • Example: Fetch SEO data from a database entity and apply it:
      $metadata->setTitle($entity->getSeoTitle());
      $metadata->setMeta('og:image', $entity->getOgImageUrl());
      
  2. Entity-Based SEO:

    • Extend an entity with SEO fields (e.g., title, description, metaTags).
    • Use a listener to populate SeoMetadataInterface from the entity:
      public function onKernelView(GetResponseForControllerResultEvent $event)
      {
          $metadata = $event->getControllerResult();
          if ($metadata instanceof SeoMetadataInterface && $metadata->getEntity()) {
              $entity = $metadata->getEntity();
              $metadata->setTitle($entity->getSeoTitle());
          }
      }
      
  3. Route-Based Overrides:

    • Configure SEO metadata per route in YAML:
      sonata_seo:
          routes:
              app_homepage:
                  title: "Welcome to Our Site"
                  description: "Discover amazing features"
      
  4. Twig Extensions:

    • Use sonata_seo.render() to output metadata in layouts.
    • Customize output with filters:
      {{ sonata_seo.render({ exclude: ['keywords'] }) }}
      
  5. API Responses:

    • Attach SEO metadata to API responses using event subscribers:
      public function onKernelView(GetResponseForControllerResultEvent $event)
      {
          $metadata = $event->getControllerResult();
          if ($metadata instanceof SeoMetadataInterface) {
              $event->getResponse()->headers->set('X-Seo-Title', $metadata->getTitle());
          }
      }
      

Integration Tips

  1. Symfony UX/Turbo:

    • For SPAs or Turbo-driven apps, use sonata_seo to hydrate metadata on page changes via JavaScript:
      document.addEventListener('turbo:load', () => {
          fetch('/seo/metadata').then(response => {
              response.json().then(data => {
                  document.querySelector('meta[name="description"]').content = data.description;
              });
          });
      });
      
  2. CMS Integration:

    • Pair with Sonata Admin Bundle to edit SEO fields in the admin panel:
      $admin->getShowMapper()->add('seoTitle', 'text', [
          'label' => 'SEO Title',
      ]);
      
  3. Sitemap Generation:

    • Combine with sonata-project/google-analytics-bundle or custom sitemap generators to include SEO-optimized URLs.
  4. Testing:

    • Mock SeoMetadataInterface in PHPUnit tests:
      $metadata = $this->createMock(SeoMetadataInterface::class);
      $metadata->method('getTitle')->willReturn('Test Title');
      
  5. Performance:

    • Cache metadata for static pages using Symfony’s cache system:
      $metadata = $cache->get('seo_metadata_' . $route, function() use ($metadata) {
          return $metadata;
      });
      

Gotchas and Tips

Pitfalls

  1. Metadata Overrides:

    • Route-based YAML overrides do not merge with dynamic controller settings. The last defined value wins.
    • Fix: Use SeoMetadataInterface in controllers for dynamic control.
  2. Twig Auto-escaping:

    • Metadata values rendered in Twig may be escaped. Use |raw if needed:
      {{ sonata_seo.render()|raw }}
      
  3. Entity Hydration:

    • Forgetting to set metadata->setEntity($entity) before hydration will skip entity-based SEO logic.
  4. Deprecated Methods:

    • Older versions used setMetaTag(); prefer setMeta() for consistency.
  5. Caching Headers:

    • SEO metadata in HTTP headers (e.g., X-Seo-*) may conflict with CDN caching. Explicitly set Cache-Control headers.

Debugging

  1. Check Rendered Metadata:

    • Use Twig’s dump() to inspect metadata:
      {{ dump(sonata_seo.getMetadata()) }}
      
  2. Event Debugging:

    • Log SeoMetadataInterface events in a subscriber:
      public function onSeoMetadata(SeoMetadataEvent $event)
      {
          \Log::debug('SEO Metadata:', [
              'title' => $event->getMetadata()->getTitle(),
              'route' => $event->getRoute(),
          ]);
      }
      
  3. Browser DevTools:

    • Verify metadata is rendered correctly in the <head> using Chrome DevTools (Elements > Head).

Extension Points

  1. Custom Metadata Types:

    • Extend SeoMetadataInterface to add custom fields:
      class CustomSeoMetadata extends SeoMetadata implements CustomSeoMetadataInterface
      {
          private $customField;
      
          public function setCustomField(string $value): void
          {
              $this->customField = $value;
          }
      }
      
  2. Metadata Providers:

    • Implement Sonata\SeoBundle\Provider\MetadataProviderInterface to fetch metadata from external sources (e.g., APIs):
      class ApiMetadataProvider implements MetadataProviderInterface
      {
          public function getMetadata(string $route): SeoMetadataInterface
          {
              $metadata = new SeoMetadata();
              $apiData = $this->fetchFromApi($route);
              $metadata->setTitle($apiData['title']);
              return $metadata;
          }
      }
      
  3. Event Subscribers:

    • Subscribe to sonata.seo.metadata events to modify metadata dynamically:
      public static function getSubscribedEvents()
      {
          return [
              SeoEvents::METADATA => 'onSeoMetadata',
          ];
      }
      
  4. Twig Extensions:

    • Override the default Twig extension to customize rendering:
      $twig->addExtension(new class extends \Sonata\SeoBundle\Twig\SeoExtension
      {
          public function render(array $options = []): string
          {
              // Custom logic
              return parent::render($options);
          }
      });
      
  5. Configuration Overrides:

    • Use environment-specific configs (e.g., config/packages/dev/sonata_seo.yaml) to toggle SEO features in development.

Pro Tips

  • Canonical URLs: Use metadata->setCanonicalUrl() to avoid duplicate content issues.
  • OpenGraph/Twitter Cards: Leverage setMeta() for social media previews:
    $metadata->setMeta('og:type', 'website');
    $metadata->setMeta('twitter:card', 'summary_large_image');
    
  • Localization: Combine with Symfony’s translation system to support multilingual SEO:
    $metadata->setTitle($this->translator->trans('seo.title', [], 'messages'));
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui