SYMFONY SEO AUDIT · TWIG METADATA · SLUG ROUTING · SITEMAP BUNDLE
Free Symfony SEO Audit
Symfony is server-rendered PHP with full Googlebot compatibility — but SEO metadata, sitemap generation, and structured data require explicit Twig template configuration and bundles. DeepSEOAnalysis audits Symfony sites for metadata coverage gaps, slug routing, sitemap configuration, and AI visibility signals.
WHAT WE CHECK
6 Symfony-specific SEO checks
Beyond the 80+ general checks, the engine applies Symfony-aware analysis — detecting Twig template metadata gaps, numeric-ID vs slug routing patterns, sitemap bundle configuration, robots.txt structure, and AI visibility signals — with Composer package names, bundle configuration paths, and Twig code snippets for each fix.
Twig template metadata coverage
Symfony applications render HTML via Twig templates. The SEO-critical metadata — `title`, `meta name="description"`, `link rel="canonical"`, Open Graph tags, and JSON-LD — must be defined in the base layout template with per-page override blocks. The common Twig pattern: `base.html.twig` defines `{% block seo_title %}{{ defaultTitle }}{% endblock %}` and `{% block meta_description %}{% endblock %}`; route-specific child templates override these blocks with entity-specific content. Common coverage gaps: the meta description block exists but is never populated by child templates (resulting in empty meta descriptions across all blog posts and product pages); the canonical tag is hardcoded to the homepage URL rather than the current route URL (generating self-referential canonical errors on all non-homepage pages); Open Graph tags are missing entirely, preventing social sharing previews. The audit checks every crawled page for unique, non-empty title tags and meta descriptions in the server-rendered HTML, and validates canonical tag targets on all pages.
Symfony Routing slug configuration
Symfony\'s routing component supports parameterised routes with typed constraints. SEO-wise, the difference between `@Route("/posts/{id}", requirements={"id"="\\d+"})` (numeric ID route, generates `/posts/42`) and `@Route("/posts/{slug}", requirements={"slug"="[a-z0-9\\-]+"})` (slug route, generates `/posts/my-post-title`) is significant — slug routes carry keyword signal, numeric ID routes do not. Slug generation: the `stof/DoctrineExtensions` bundle provides the `Sluggable` Doctrine extension (`@Gedmo\\Mapping\\Annotation\\Slug`), which auto-generates a URL slug from entity fields and stores it in the database. The `cocur/slugify` library handles the slug generation logic. For existing sites with numeric ID routes: add a `slug` field to the entity, generate slugs for existing records via a migration script or console command, add the slug route, and set up 301 redirects from old numeric ID URLs to the new slug URLs. The audit checks URL patterns across all crawled pages and flags numeric-ID URL patterns.
Sitemap bundle configuration
`presta/sitemap-bundle` is the most maintained Symfony sitemap bundle. Installation: `composer require presta/sitemap-bundle`; configure in `config/packages/presta_sitemap.yaml` (set `default_section`, time-to-live); register Doctrine entity collections as sitemap providers by implementing `SitemapPopulatorInterface` or using the event-based API. A basic provider for a blog: the service fetches all published Post entities, iterates through them, and adds each URL via `$event->addUrl(new UrlConcrete($absoluteUrl, $lastmod, UrlConcrete::CHANGEFREQ_WEEKLY, 0.7))`. The sitemap is served at `/sitemap.xml` (configurable). Caching: the bundle includes caching for the generated sitemap to avoid regenerating on every request — configure TTL appropriately (daily regeneration is typical). The audit checks sitemap presence, URL count vs crawled page count, `lastmod` accuracy, and the `Sitemap:` directive in `robots.txt`.
robots.txt serving configuration
In a Symfony application, `robots.txt` can be served as a static file from the `public/` directory (served directly by nginx/Apache without passing through the Symfony front controller) or as a dynamic route generated by Symfony (useful for environment-specific robots.txt — e.g., noindex on staging, allow on production). The static approach: `public/robots.txt` is served at `/robots.txt` by the web server\'s root directory mapping. The dynamic approach: a Symfony controller route at `/robots.txt` returns a plain text response with appropriate `Content-Type: text/plain` header. Common gaps: AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Applebot-Extended) are blocked by an overly broad `Disallow: /` or by Symfony-specific admin route disallows that are too broad; the `Sitemap:` directive is missing; Symfony\'s default dev routes (`/_profiler`, `/_error`) are not disallowed on production (they should be either disabled or disallowed). The audit checks the file at `/robots.txt`, all AI crawler user-agents, and the Sitemap directive.
Server-rendered PHP output
Symfony renders pages server-side via PHP and the Twig template engine. Every HTTP response is a complete HTML document — content, headings, metadata, and structured data all appear in the initial response before any JavaScript runs. Googlebot receives the full page content immediately on the first wave with no rendering queue delay. This is Symfony\'s core SEO infrastructure advantage over SPA frameworks like React, Vue, and Angular. The audit verifies that crawled pages deliver complete HTML on the first request and flags any Symfony pages where content is deferred via JavaScript after the initial render — common in Symfony applications that use API Platform with a JavaScript frontend (API Platform + React/Vue decoupled), where those sections may appear empty to Googlebot\'s first-wave crawl.
AI visibility for Symfony sites
Serve `llms.txt` as a static file from Symfony\'s `public/` directory — `public/llms.txt` is served at `/llms.txt` directly by nginx/Apache. FAQPage JSON-LD can be rendered in Twig templates using the `json_encode` filter: `script type="application/ld+json">{{ faqSchema|json_encode(constant(\'JSON_UNESCAPED_UNICODE\'))|raw }}</script` where `faqSchema` is a PHP array defined in the controller (FAQ data from a Doctrine entity). Article JSON-LD for blog posts follows the same pattern — build the schema array in the controller from the Post entity fields and pass it to Twig. For sites using API Platform, the `api-platform/core` package supports automatic JSON-LD output via API responses, but this is the API schema (for `hydra:Collection` and `hydra:member` types), not the Web page SEO JSON-LD. SEO JSON-LD must be added separately in the Twig templates. The audit checks all five AI visibility signals with Symfony bundle names and Twig code patterns for each fix.
HOW IT WORKS
Audit your Symfony site in 60 seconds
- Enter your Symfony site URL. Works with any Symfony version (4.x, 5.x, 6.x, 7.x) on any host: Platform.sh, AWS, DigitalOcean, Hetzner, or self-hosted. No Symfony admin access, database credentials, or Composer access needed — the audit crawls the live site.
- We crawl and analyse. The engine crawls up to 50 pages (free) or 1,000 pages (paid), checks Twig template metadata coverage per page, detects routing URL patterns, validates JSON-LD structured data in the server-rendered HTML, tests sitemap and robots.txt configuration, measures CrUX Core Web Vitals, and evaluates all five AI visibility signals.
- You get a prioritised report. Symfony-specific issues first — Twig template metadata gaps, numeric-ID routes, sitemap bundle configuration, AI crawler access — then general SEO, each with Composer package names (`presta/sitemap-bundle`, `stof/DoctrineExtensions`), Twig code patterns, and Symfony routing configuration for the fix.
FAQ
Questions about the Symfony SEO audit
Does Symfony have good SEO out of the box?
Symfony is server-rendered PHP — every HTTP response is a complete HTML document generated by Twig templates, which Googlebot receives on the first crawl without any rendering delay. This is Symfony\'s core SEO infrastructure advantage over SPA frameworks. However, Symfony itself provides no SEO-specific features: there\'s no built-in meta description management, no sitemap generation, and no structured data output. These require Symfony bundles (RulerZ SEO Bundle, Spiriit Form Filter Bundle for routing, stof/DoctrineExtensions for slugs) or custom Twig templates. The `artgris/pagerfanta` and `dmaicher/doctrine-test-bundle` ecosystems, and the `symfony/routing` component for slug-based URLs, are the baseline for SEO-friendly Symfony sites.
How do I add SEO meta tags to a Symfony Twig template?
The pattern is to define per-route SEO variables in the controller and pass them to Twig. Controller: `return $this->render(\'post/show.html.twig\', [\'post\' => $post, \'seoTitle\' => $post->getTitle().\' | Blog\', \'seoDescription\' => $post->getExcerpt()])`; Layout template (`base.html.twig`): `title>{% block seo_title %}{{ seoTitle|default(\'Default Title\') }}{% endblock %}</title` and `meta name="description" content="{{ seoDescription|default(\'\') }}"`. Child templates override `seo_title` and `seo_description` blocks per page. For a more structured approach, `sensio/framework-extra-bundle` annotations or Symfony\'s `#[Template]` attribute can define metadata in controller attributes. Third-party bundles like `wemakecustom/seo-bundle` provide a SEO field component that can be embedded in Doctrine entities for per-entity metadata management.
How do I generate a sitemap in Symfony?
Two approaches: (1) `dpn/xml-sitemap-bundle` (or `presta/sitemap-bundle`, the more actively maintained option) — install via Composer, configure routes to include via bundle config, register sitemap providers as services. `presta/sitemap-bundle` uses event listeners to build the sitemap dynamically from Doctrine entity collections. (2) A custom Symfony Controller that queries the database and streams XML directly — simpler for smaller sites. Both approaches should: include only published, indexable URLs; set `lastmod` from the entity\'s `updatedAt` timestamp; use absolute URLs with your site\'s domain; and be referenced by a `Sitemap:` directive in `robots.txt`. Configure the sitemap to regenerate on content changes or on a cron schedule.
Is the Symfony SEO audit free?
Yes. The complete audit is free with no signup and no email gate. Paid plans add saved history, scheduled monitoring, larger crawls (up to 1,000 pages), and agency workflows.