Installation Add the bundle via Composer:
composer require daddl3/seo-tool-bundle
Enable the bundle in config/bundles.php:
Daddl3\SeoToolBundle\Daddl3SeoToolBundle::class => ['all' => true],
Basic Configuration Publish the default configuration:
php bin/console daddl3:seo:install
Update config/packages/daddl3_seo_tool.yaml to match your needs (e.g., canonical URLs, meta tags, OpenGraph defaults).
First Use Case: Dynamic Meta Tags
Use the SeoTool service in a controller to generate meta tags dynamically:
use Daddl3\SeoToolBundle\Service\SeoTool;
class PageController extends AbstractController
{
public function show(SeoTool $seoTool, $slug)
{
$seoTool->setTitle('My Page Title');
$seoTool->setDescription('A dynamic description for my page.');
$seoTool->setCanonicalUrl($this->generateUrl('page_show', ['slug' => $slug]));
// Add OpenGraph tags
$seoTool->setOpenGraph([
'title' => 'OG Title',
'description' => 'OG Description',
'image' => $this->generateUrl('asset', {'path' => 'images/og-image.jpg'}),
]);
return $this->render('page/show.html.twig');
}
}
Twig Integration
Ensure Twig is configured to render SEO tags. The bundle provides a seo Twig extension:
{{ seo.render() }}
Place this in your base template (e.g., base.html.twig) to auto-inject meta tags.
Page-Specific SEO Override SEO settings per route or entity:
// In a controller or event subscriber
$seoTool->setTitle('Custom Title for ' ~ $entity->getName());
$seoTool->setKeywords([$entity->getTagline(), 'related', 'tags']);
Entity-Based SEO
Use Doctrine listeners or Symfony’s PRE_PERSIST/PRE_UPDATE events to auto-generate SEO metadata from entities:
// src/EventListener/SeoListener.php
public function prePersist(PrePersistEventArgs $args)
{
$entity = $args->getObject();
if ($entity instanceof SeoAwareInterface) {
$seoTool->setTitle($entity->getSeoTitle());
$seoTool->setDescription($entity->getSeoDescription());
}
}
Dynamic Canonical URLs Generate canonical URLs based on route parameters:
$seoTool->setCanonicalUrl(
$this->generateUrl('product_show', ['id' => $product->getId(), 'slug' => $product->getSlug()])
);
Social Media Optimization Leverage OpenGraph/Twitter Cards for sharing:
$seoTool->setOpenGraph([
'type' => 'article',
'url' => $this->generateUrl('article_show', ['id' => $article->getId()]),
'images' => [$this->generateUrl('asset', {'path' => 'images/article.jpg'})],
]);
$seoTool->setTwitterCard('summary_large_image');
Conditional SEO Disable SEO tags for specific routes (e.g., admin pages):
if ($this->isGranted('ROLE_ADMIN')) {
$seoTool->disable();
}
{{ seo.title }}, {{ seo.description }}, etc., in templates for granular control.seo.tool.build (fired before rendering).$seoTool->setCache($cachePool->getItem('seo:page:' ~ $slug));
Configuration Overrides
daddl3_seo_tool.yaml does not accidentally override defaults:
# ❌ Bad: Overrides all OpenGraph tags globally
daddl3_seo_tool:
open_graph:
title: "Default Title" # Forces this on all pages
# ✅ Good: Use `setOpenGraph` in controllers for dynamic values
Twig Auto-Rendering
{{ seo.render() }} tag must be placed in the <head> section of your template. Placing it elsewhere (e.g., <body>) will break rendering.Canonical URL Conflicts
$canonicalUrl = $seoTool->getCanonicalUrl();
if (strpos($canonicalUrl, '?') !== false) {
throw new \RuntimeException('Canonical URL must not include query parameters.');
}
Entity Listeners and Circular References
SeoAwareInterface triggering SEO updates recursively). Use @ORM\HasLifecycleCallbacks sparingly.Missing Assets
$imageUrl = $this->generateUrl('asset', {'path' => 'images/og-image.jpg'});
if (!$this->isPathValid($imageUrl)) {
$seoTool->setOpenGraphImage($this->generateUrl('asset', {'path' => 'images/default-og.jpg'}));
}
Enable Debug Mode
Set debug: true in daddl3_seo_tool.yaml to log SEO metadata to the Symfony profiler:
daddl3_seo_tool:
debug: true
Access via Profiler > SEO Tool.
Validate HTML Output Use tools like Google’s Rich Results Test to validate OpenGraph/Twitter Cards.
Check for Deprecated Methods The bundle may evolve. Refer to the CHANGELOG for breaking changes.
Custom Tag Support
Extend the bundle to add custom meta tags (e.g., article:published_time):
// src/Service/SeoToolExtension.php
public function addCustomTags(SeoTool $seoTool, array $tags)
{
foreach ($tags as $name => $content) {
$seoTool->addMetaTag($name, $content);
}
}
Event Subscribers
Listen to seo.tool.build to modify metadata dynamically:
// src/EventSubscriber/SeoSubscriber.php
public function onSeoBuild(SeoBuildEvent $event)
{
$event->getSeoTool()->setKeywords(['custom', 'keywords']);
}
Register in services.yaml:
services:
App\EventSubscriber\SeoSubscriber:
tags: ['kernel.event_subscriber']
Custom Twig Functions Add helper functions to Twig for SEO-specific logic:
// src/Twig/SeoExtension.php
public function getSeoTitle(SeoTool $seoTool, string $fallback = null)
{
return $seoTool->getTitle() ?: $fallback;
}
Register in services.yaml:
services:
App\Twig\SeoExtension:
tags: ['twig.extension']
How can I help you explore Laravel packages today?