softspring / cms-seo-plugin
SEO analysis plugin for Softspring CMS.
Package info
github.com/softspring/cms-seo-plugin
Type:sfs-cms-plugin
pkg:composer/softspring/cms-seo-plugin
Requires
- php: >=8.4
- ext-dom: *
- ext-libxml: *
- ext-mbstring: *
- softspring/cms-bundle: ^6.0@dev
- symfony/config: ^6.4 || ^7.4 || ^8.0
- symfony/console: ^6.4 || ^7.4 || ^8.0
- symfony/dependency-injection: ^6.4 || ^7.4 || ^8.0
- symfony/framework-bundle: ^6.4 || ^7.4 || ^8.0
- symfony/http-client: ^6.4 || ^7.4 || ^8.0
- symfony/http-client-contracts: ^3.5
- symfony/http-foundation: ^6.4 || ^7.4 || ^8.0
- symfony/http-kernel: ^6.4 || ^7.4 || ^8.0
- symfony/routing: ^6.4 || ^7.4 || ^8.0
Requires (Dev)
- ergebnis/composer-normalize: ^2.50
- friendsofphp/php-cs-fixer: ^3.94
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^12.5
- rector/rector: ^2.3
- symfony/yaml: ^6.4 || ^7.4 || ^8.0
This package is auto-updated.
Last update: 2026-06-19 10:55:20 UTC
README
Experimental package: this plugin is in active development and its configuration, checks, storage format, UI, and extension points may change before a stable release.
softspring/cms-seo-plugin adds SEO analysis tools to Softspring CMS administration.
It analyzes published CMS URLs and reports deterministic checks for HTTP status, HTML content type, title, meta description, canonical URL, alternate language URLs, H1 usage, heading structure, image alt text, robots meta tag, and approximate body word count.
It also supports site-level checks for robots.txt, sitemap indexes, configured sitemaps, and root slash redirects.
Installation
composer require softspring/cms-seo-plugin:^6.0@dev
The plugin requires softspring/cms-bundle and Symfony HttpClient.
Register the bundle if Symfony Flex does not do it automatically:
// config/bundles.php return [ Softspring\CmsSeoPlugin\SfsCmsSeoPlugin::class => ['all' => true], ];
Configuration
Site analysis is enabled by default. Disable it or individual checks when a project does not expose the related public resources:
# config/packages/sfs_cms_seo.yaml sfs_cms_seo: site_analysis: enabled: true checks: robots_reachable: true robots_sitemap_index: true sitemap_index_reachable: true sitemap_index_contains_configured_sitemaps: true sitemap_reachable: true slash_route_redirect: true
Usage
The plugin adds SEO screens to the CMS admin:
- A global SEO dashboard.
- A SEO tab for CMS content administration.
- A SEO tab for CMS site administration.
Run all configured analysis from the command line:
php bin/console sfs:cms:seo:analyze
Analyze only sites or content:
php bin/console sfs:cms:seo:analyze --sites php bin/console sfs:cms:seo:analyze --contents
The --async option is reserved for projects that replace the default dispatcher with a Messenger-backed implementation.
Content Analysis Storage
Each content analysis run is stored in the analyzed ContentVersion metadata field:
version.meta.sfs_cms_seo_analysis
The metadata payload contains the analysis timestamp, content id, version id, version number, summary, and per-URL rows with checks, metrics, and details.
When the content SEO tab is opened, the plugin stores the result in the published version. When a version-specific SEO analysis route is used, the plugin stores the result in that version.
If a version already has stored SEO analysis metadata, the admin tab reads and displays that payload without fetching the published URLs again. Editors can use Update data to fetch the URLs again, recalculate the checks, and replace the stored metadata.
When Update data targets a version that stores compiled content in the database, the admin UI shows a warning because the analyzed HTML can still come from stored compiled content.
The plugin overrides @SfsCms/admin/content/_read_indexing.html.twig through templates/bundles/SfsCmsBundle/admin/content/_read_indexing.html.twig. The content read screen shows the stored SEO summary for the published version when analysis metadata exists.
Dashboard
The dashboard reads stored SEO analysis metadata from published versions and shows:
- General statistics for average score, analyzed content, pending content, analyzed URLs, errors, and warnings.
- Site-level SEO status for robots and sitemaps.
- Lowest scoring published content.
- Lowest scoring published URLs.
The dashboard does not recalculate analysis. Editors must open the content SEO tab and use Update data when they need fresh content analysis.
The fetcher appends a random sfs_cms_seo_bust query parameter to request URLs so analysis reads fresh HTML instead of cached CDN or Varnish content. Public URLs shown in the admin UI keep their canonical form.
Local Fetch Behavior
When a published URL uses a .local host, the fetcher rewrites the request to http://balancer:8008 and sends the original host in the Host header plus X-Forwarded-Proto: https.
This avoids resolving local development domains to 127.0.0.1 inside the PHP container, where the host nginx proxy is not listening.
Extension Points
Add content SEO checks by implementing Softspring\CmsSeoPlugin\Content\Check\CheckInterface. Services are autoconfigured with the sfs_cms_seo.check tag.
Add site SEO checks by implementing Softspring\CmsSeoPlugin\Site\Check\SiteCheckInterface. Services are autoconfigured with the sfs_cms_seo.site_check tag.
Replace Softspring\CmsSeoPlugin\Seo\SeoAnalysisDispatcherInterface when a project needs asynchronous analysis or an external provider.
The implementation is split so future analysis providers can be added without changing the admin tab contract:
PageUrlResolverresolves CMS URLs for a content item.PublishedPageFetcherfetches published pages.BasicSeoAnalyzercreates local checks and scores.SiteAnalyzercreates site-level checks and scores.
Future providers such as AI analysis, SEMrush, or Ahrefs should add services beside BasicSeoAnalyzer and merge their results in the controller or an orchestration service.
Features
See FEATURES.md for the functional scope of this package.
Contributing
See CONTRIBUTING.md.
Report issues and send Pull Requests
Security
See SECURITY.md.
License
This package is free and released under the AGPL-3.0 license.