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

Seo Bundle Laravel Package

setono/seo-bundle

Setono SEO Bundle brings SEO tooling to Symfony apps: manage meta tags, titles and descriptions, generate sitemaps, and control robots directives from one configurable package. It integrates with your entities and Twig templates so you can improve search visibility without custom boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

First, check the framework. Despite the framing, setono/seo-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no config/seo.php, no facade. If you are in a Laravel codebase, stop here — you would be reimplementing the Twig/DI layer or writing a bridge, which is more work than the bundle saves. The realistic path in Laravel is to read the source for the approach (how it models canonical URLs and JSON-LD) and build it yourself.

If you are on Symfony, the minimum sequence is:

  1. composer require setono/seo-bundle:0.1.* — pin the minor explicitly. Do not use ^0.1.
  2. Register the bundle class from src/ in config/bundles.php.
  3. Run bin/console debug:config <alias> to confirm the extension loaded. The alias is derived from the bundle name; grep src/DependencyInjection/Configuration.php for the root node rather than guessing.
  4. bin/console debug:twig and bin/console debug:container --tag=twig.extension to discover the actual helper names and service IDs. This is your documentation — there is no docs site, no README walkthrough, and v0.1.0's release note says only "work in progress."

First use case: the least risky one — a base layout template rendering <title>, <meta name="description">, and <link rel="canonical"> from values your controller already computes. That exercises the meta-tag and canonical services without depending on any structured-data API, which is the part most likely to churn.

Read in this order: the bundle class → DependencyInjection/Configuration.php (what is actually configurable) → the Twig extension (what is actually callable) → tests, if any exist.

Implementation Patterns

Keep SEO construction in a service, not the template. The bundle gives you primitives; the durable pattern is a per-entity builder (PostSeoData, ProductSeoData) that takes a domain object and returns a plain value object of title/description/canonical/JSON-LD. Templates then render that object through the bundle's helpers. When the bundle's API shifts — and at 0.1.x it will — you change one adapter class, not forty templates.

Wrap it behind your own interface. Define SeoPresenterInterface in your app, implement it with the bundle's services, and inject your interface into controllers and Twig. This is the single highest-value integration decision for a pre-1.0 dependency: it converts a breaking change from a migration into a one-file edit.

Decorate, don't fork. The bundle advertises extensible services; use Symfony's service decoration (decorates:) to add fields, change canonical normalisation, or swap JSON-LD shapes. Never patch vendor/.

Canonical URLs belong in a request listener, not in every controller. Derive the canonical from the resolved route plus normalised query parameters in one place, then expose it as a request attribute the template reads. Per-controller canonical logic is how duplicate-content bugs get shipped — one action forgets to strip ?utm_source, and you have split ranking signals.

Structured data: emit one graph per page. JSON-LD is easy to double-emit (an Organization block in the layout plus an Article block in the content template produces two competing <script> tags). Have a single collector service that templates append to, and render it once at the end of <body>.

Integration tip: put an assertion in your test suite that renders the layout and asserts the presence of exactly one canonical tag and one JSON-LD script. Functional coverage in your own repo is the only coverage you can count on here.

Gotchas and Tips

  • Framework mismatch is the headline gotcha. The Symfony/Laravel mismatch invalidates most "day-to-day leverage" questions. Verify before anything else.
  • 0.1.0 means 0.x semver: breaking changes ship in any minor. Pin exactly, commit the lockfile, and treat every bump as a code change requiring review.
  • No published docs means the source is the spec, and the spec is unfinished. Expect unregistered services, missing config nodes, or helpers that are wired but stubbed. Budget a source read before you budget an integration.
  • Twig autoescaping will break JSON-LD and meta content. Structured data needs |raw on a pre-encoded string, or Symfony's json_encode filter. Meta descriptions containing quotes or emoji need the same care. This is the most common silent failure — the page renders, the tags are malformed, and nothing in the logs tells you.
  • Canonical normalisation edge cases: trailing slashes, locale prefixes (/en/ vs /), paginated pages (each page needs a self-referential canonical, plus rel=prev/next if you use them), and tracking parameters. Decide the policy once, in one service.
  • Do not query the database from a Twig helper. If a helper lazily loads a related entity to build a description, you have moved an N+1 into your render layer where profilers are least likely to look. Resolve everything in the controller/listener.
  • Debugging: debug:container <service-id> --show-private, debug:config, and debug:twig are your entire toolchain. If a helper returns empty, first confirm the extension is tagged twig.extension, then confirm the service is public or injected — not that the logic is wrong.
  • Cache invalidation: if you cache rendered SEO fragments, key on entity ID and updatedAt. Stale titles in <title> are invisible in the UI and expensive in search results.
  • Escape hatch: keep the interface wrapper (above) and a fallback implementation that writes the three tags manually. That fallback is roughly thirty lines and removes the abandonment risk entirely — which, given a 0-star, WIP package, is the honest price of admission.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings