aryaazadeh / laravel-seo-audit
This is my package laravel-seo-audit
Fund package maintenance!
AryaAzadeh
Installs: 13
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/aryaazadeh/laravel-seo-audit
Requires
- php: ^8.3
- illuminate/contracts: ^11.0||^12.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.0.0||^9.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
README
Developer-first SEO auditing for Laravel apps with deterministic checks, report persistence, and a protected dashboard.
Installation
composer require aryaazadeh/laravel-seo-audit
Publish migrations and config:
php artisan vendor:publish --tag="seo-audit-migrations" php artisan vendor:publish --tag="seo-audit-config" php artisan migrate
CLI Usage
Primary command:
php artisan seo:audit
Legacy alias (kept for backwards compatibility):
php artisan laravel-seo-audit
Useful options:
php artisan seo:audit --format=json --fail-on=error --output=storage/app/seo-report.json --max-pages=100
--format=table|json|html--fail-on=error|critical--output=path--max-pages=int
Exit codes:
0: pass2: error threshold reached3: critical threshold reached
Dashboard
Route: /seo-audit/dashboard
Default protection:
- middleware:
web,auth - ability:
viewSeoAudit
You can configure both in config/seo-audit.php.
Dashboard capabilities:
- Select any recent run from the run switcher.
- Track score trend across recent runs.
- Inspect high-risk pages and rule-level issue share.
- Filter issues by
severity,rule, and text query (q/search) with pagination. - Apply text search to high-risk pages as well (URL and title matching).
- View separate
technical_scoreandcontent_scorebeside the overall score.
Content SEO (Yoast-like)
The package can run deterministic content checks and suggestions in addition to technical checks.
Content checks include:
- Title length quality
- Meta description length quality
- Thin content detection (word count)
- Missing H2 subheadings on long pages
- Missing image alt coverage
- Low internal linking on long pages
- Focus keyword presence in title/meta/H1/opening paragraph
Enable/adjust in config/seo-audit.php:
'content' => [ 'enabled' => true, 'site_name' => 'MYSITE', 'title' => ['min' => 30, 'max' => 60], 'meta_description' => ['min' => 120, 'max' => 160], 'min_word_count' => 300, 'focus_keywords' => [ '/fa/products/*' => 'محصولات', '/en/products/*' => 'products', // 'regex:/^\\/fa\\/blog\\/.+/' => 'وبلاگ', ], ],
Suggestions are attached to each issue in context, for example:
suggested_titlesuggested_meta_descriptionrecommendationmissing_in(for focus keyword placements)
Route Crawl Controls
For multilingual apps and dynamic endpoints, these options help keep reports clean:
crawl.exclude_parameterized_routes(default:true) skips routes like/products/{slug}.crawl.deduplicate_localized_routes(default:true) deduplicates locale-prefixed duplicates (for example/fa/about-usand/about-us).- Internal route redirects are followed before SEO rules are evaluated (for example
/products->/fa/products). crawl.route_http_fallback_on_error(default:true) retries route-based targets via real HTTP when internal CLI kernel matching returns4xx/5xxunexpectedly.crawl.link_discovery.enabled(default:false) discovers extra internal links from crawled HTML pages (useful for dynamic slug pages and old content archives).crawl.link_discovery.seed_pathscontrols where discovery starts (default:['/']).crawl.link_discovery.max_pageslimits discovery fetches (default:120).crawl.sitemap_discovery.enabled(default:false) imports URLs from sitemap files (urlsetandsitemapindex) for broad historical coverage.crawl.sitemap_discovery.seed_pathscontrols which sitemap files are loaded first (default:['/sitemap.xml', '/sitemap_index.xml']).crawl.sitemap_discovery.max_urlscaps the number of sitemap URLs added to the crawl queue (default:1000).
AI Layer (v1 Boundary)
The package exposes an AI provider contract but ships with a safe null provider by default.
- interface:
AryaAzadeh\LaravelSeoAudit\Contracts\LlmProviderInterface - default binding:
NullLlmProvider - feature flag:
seo-audit.ai.enabled
Testing
composer test