@consilioweb/payload-seo-analyzer
v1.21.1
Published
Payload CMS SEO plugin — 50+ checks, dashboard, Lexical JSON support, Flesch FR/EN readability, i18n
Maintainers
Readme
📑 Table of Contents
- Features
- Quick Start
- Installation
- Usage
- API Reference
- Configuration
- Performance
- Examples
- FAQ
- Troubleshooting
- Security
- Contributing
- Changelog
- Roadmap
- Support
- License
✨ Features
🔍 50+ On-Page Checks
A deterministic, offline engine across ~21 rule groups: title, meta, content, headings, images, linking, readability, schema, E-E-A-T and more.
🤖 SEO 2026 Ready
Entities & topical authority (sameAs/knowsAbout), AI/GEO extractability, real per-type JSON-LD validation, and GSC-driven content grading.
📊 9-View Admin Dashboard
Site-wide audit, link graph (with crawl budget), redirect manager, schema builder, cannibalization, keyword research, performance and config.
🌍 Bilingual & i18n
FR/EN readability scoring (Flesch + Kandel–Moles), 39-language meta labels, FR/EN dashboard auto-locale, and per-locale audit/caching.
🔐 Hardened & Typed
RBAC gate, SSRF protections, open-redirect/robots sanitization, bounded cache and rate limiting — fully typed, with 391 tests.
⚡ Built for Real Hosts
Single-flight, throttled background audit; paginated loading; bounded LRU cache; LLM timeouts — stays responsive on constrained shared hosting.
🚀 Quick Start
// payload.config.ts
import { buildConfig } from 'payload'
import { seoAnalyzerPlugin } from '@consilioweb/payload-seo-analyzer'
export default buildConfig({
plugins: [
seoAnalyzerPlugin({
collections: ['pages', 'posts'],
siteUrl: 'https://example.com',
}),
],
})pnpm payload generate:importmap
pnpm devOpen /admin/seo for the dashboard, or edit any page/post to see the live SEO score in the sidebar.
📦 Installation
npm
npm install @consilioweb/payload-seo-analyzeryarn
yarn add @consilioweb/payload-seo-analyzerpnpm
pnpm add @consilioweb/payload-seo-analyzerPeer dependencies: payload@^3, @payloadcms/next@^3 (and optionally @payloadcms/ui@^3, react@^18 || ^19). After adding admin components, run pnpm payload generate:importmap.
💻 Usage
Basic
seoAnalyzerPlugin({ collections: ['pages', 'posts'] })Advanced
seoAnalyzerPlugin({
collections: ['pages', 'posts', 'products'],
globals: ['home'],
siteUrl: 'https://example.com',
locale: 'fr',
features: {
gscApi: true, // Google Search Console (OAuth)
aiFeatures: true, // AI assists (needs ANTHROPIC_API_KEY)
alerts: true, // monitoring digest (webhook/email)
},
})Frontend metadata (Next.js)
import { buildSeoMetadata } from '@consilioweb/payload-seo-analyzer'
export const generateMetadata = ({ doc }) =>
buildSeoMetadata(doc, { siteUrl: 'https://example.com' })🔌 API Reference
seoAnalyzerPlugin(config)
The Payload plugin. Adds SEO fields, admin views, editor components and API endpoints.
seoAnalyzerPlugin(config: SeoPluginConfig): PluginanalyzeSeo(input, config)
Runs the full engine programmatically and returns the score, level and checks.
analyzeSeo(input: SeoInput, config?: SeoConfig): SeoAnalysisFrontend helpers
buildSeoMetadata(doc, opts): Metadata // Next.js <head> metadata
buildJsonLd(type, values): Record<string, unknown> // schema.org JSON-LD
renderJsonLdScript(jsonLd): string // <script type="application/ld+json">Key HTTP endpoints (under /api/seo-plugin, auth required)
| Method | Path | Purpose |
|---|---|---|
| GET/POST | /validate | Full per-document analysis. |
| GET | /audit | Site-wide audit (background, throttled). |
| GET | /indexation-audit | Cross-page indexation hygiene. |
| GET | /link-graph | Internal link graph + crawl budget. |
| GET | /content-grade | GSC-driven coverage grade (opt-in). |
| POST | /ai-optimize, /ai-alt-text, /ai-content-brief | AI assists (opt-in). |
| GET | /robots.txt, /sitemap.xml, /llms.txt | Public, generated. |
⚙️ Configuration
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| collections | string[] | ['pages','posts'] | Collections to analyze. |
| globals | string[] | [] | Globals to analyze. |
| siteUrl | string | env | Base URL (canonical, GSC, sitemaps). |
| locale | 'fr' \| 'en' | 'fr' | Analysis language. |
| features | SeoFeatures | all true | Granular feature flags. |
| disabledRules | RuleGroup[] | [] | Disable rule groups. |
| thresholds | SeoThresholds | defaults | Override numeric thresholds. |
Environment variables
| Env var | Default | Description |
|---------|---------|-------------|
| ANTHROPIC_API_KEY | — | Enables AI assists (server-side). Heuristic fallback without it. |
| SEO_AI_MODEL | claude-sonnet-4-6 | Model override (claude-opus-4-8 = max quality, claude-haiku-4-5 = cheapest). |
| SEO_REQUIRE_ADMIN_ROLE | — | 1 disables the RBAC fail-open. |
| SEO_FETCH_MAX_DOCS | 5000 | Memory cap for site-wide analysis. |
| SEO_STRICT_READ_ACCESS | — | 1 makes single-document reads respect the caller's collection/field-level ACL (overrideAccess: false). |
| SEO_LLMS_TXT | — | 1 enables the opt-in /llms.txt generator. |
| SEO_GSC_ENCRYPTION_KEY | — | 32-byte key to encrypt GSC tokens at rest (recommended). |
| SEO_AUDIT_DOC_DELAY_MS | 10 | Per-document pause during the audit build — gentler on the CPU so the site stays responsive (raise on rich-content sites; 0 = fastest build). |
| SEO_AUDIT_* / SEO_ALERT_* | see docs | Audit throttling (batch size/delay/depth/max-docs) & monitoring digest. |
⚡ Performance
Engineered to stay responsive on constrained shared hosting (no fabricated benchmarks — characteristics depend on your content volume and host):
| Concern | Approach |
|---------|----------|
| Site-wide audit | Single-flight, background-built, throttled (env-tunable); never blocks or OOM-kills the process. |
| Heavy endpoints | Periodic event-loop yielding + rate limiting (keyed by user id). |
| Document loading | Paginated with a memory cap (SEO_FETCH_MAX_DOCS). |
| Caching | LRU-bounded, locale-aware invalidation; Core Web Vitals cached to protect the PSI quota. |
| External APIs | LLM calls have timeouts and retry/backoff. |
Tune via the
SEO_AUDIT_*env vars on the tiniest hosts.
📚 Examples
Disable a rule group and re-weight another
seoAnalyzerPlugin({
collections: ['pages'],
disabledRules: ['ecommerce'],
overrideWeights: { social: 1 },
})Custom thresholds
seoAnalyzerPlugin({
collections: ['posts'],
thresholds: { TITLE_LENGTH_MAX: 65, META_DESC_LENGTH_MAX: 165 },
})❓ FAQ
No. The core analysis is offline and deterministic. Google Search Console and AI assists are opt-in and use your own credentials.
Node.js 18+, Payload 3.x, and React 18 or 19.
Yes — the package is fully typed and ships its own type definitions; IntelliSense works out of the box.
The base plugin is free and offline. Only AI assists (Anthropic) and PageSpeed/GSC quotas involve your own external usage.
See the Contributing section. Bug reports, ideas and pull requests are all welcome.
🔧 Troubleshooting
Admin components not updating
Solution: regenerate the import map.
pnpm payload generate:importmapSQLITE_BUSY during imports
Solution: the plugin serializes its own writes; ensure your seed/import scripts also write sequentially on SQLite.
Audit feels heavy on a small host
Solution:
- Raise
SEO_AUDIT_BATCH_DELAY_MS - Set
SEO_AUDIT_DEPTH=0 - Disable
features.warmCache
🔐 Security
Security is a first-class concern. The plugin reads secrets only from environment variables (never the DB), encrypts GSC tokens at rest, validates redirect targets, sanitizes robots.txt rules, and protects outbound fetches against SSRF (private-IP allowlist, DNS-rebinding guard, manual redirect re-validation).
Reporting Security Issues
Please email [email protected] instead of opening a public issue.
Best Practices
- ✅ Keep the plugin up-to-date
- ✅ Set
SEO_GSC_ENCRYPTION_KEYandSEO_REQUIRE_ADMIN_ROLE=1in production - ✅ Read all secrets from environment variables
- ✅ Enforce a rate limit at your reverse proxy
🤝 Contributing
Contributions are very welcome!
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'feat: add AmazingFeature') - Push the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Run the checks before submitting:
pnpm typecheck && pnpm test && pnpm build📝 Changelog
See CHANGELOG.md for the full history.
[1.21.0]
- 🗃️ Build-time audit cache: pre-compute the site-wide audit at CI via
buildAuditToFile()and serve it in prod through the newauditCacheFileoption — no heavy live rebuild on memory-constrained hosts. Stale-guarded (ignored once content changes); runtime kill-switchSEO_AUDIT_FILE_CACHE=0.
[1.19.0]
- ✨ SEO 2026: entities & topical authority, AI/GEO extractability, GSC-driven content grade, indexation hygiene, crawl-budget analysis, opt-in
llms.txt. - ⚡ Performance: paginated loading, bounded LRU cache, event-loop yielding, LLM timeouts/retries.
- 🔐 Security: IDOR allowlists, open-redirect & robots sanitization, residual-SSRF fix,
user.idrate limiting,SEO_REQUIRE_ADMIN_ROLE.
- 1.18.2 — Fix: false "broken links" & "orphan pages" for posts linked via
/posts/<slug> - 1.18.1 — Fix: dashboard audit returned HTTP 429 mid-build (polling throttled itself)
- 1.18.0 — Accurate readability on list-heavy content (sentence boundaries at block ends)
- 1.17.3 — Audit build no longer freezes the site (per-document yield)
- 1.17.2 — Fix: admin tools 403 for legit admins on role-less setups
- 1.17.1 — Fix: GSC panels showed "Error 404" when the feature is off
- 1.17.0 — Audit throttling (no more server saturation)
- 1.16.0 — IndexNow (proactive indexing)
- 1.15.0 — Module health / observability
- 1.14.0 — One-click "Optimize site" + per-locale audit
- 1.13.0 — CTR opportunities (GSC data → targeted meta rewrite)
- 1.12.0 — Bulk meta correction (preview/export/apply) + audit hardening
- 1.11.0 — AI content brief, News/Image/Video sitemaps, multi-location local SEO
- 1.10.0 — Rank tracking, frontend render helpers, monitoring alerts, AI alt-text
- 1.9.0 — AI SEO Optimize + dashboard OOM hardening
- 1.8.0–1.8.1 — SEO 2026 "desintox" pass + low-memory audit
- 1.3.0–1.7.0 — Early releases (core engine, i18n, dashboard)
See CHANGELOG.md for full details of every release.
🗺️ Roadmap
- [x] SEO-2026 feature set (entities, GEO, content grade, indexation hygiene)
- [x] Security & performance hardening
- [x] End-to-end UI test harness — admin views (
e2e/) - [x] Optional strict field-level access control — opt-in via
SEO_STRICT_READ_ACCESS=1 - [x] Entity input fields in the Schema Builder — author
sameAs, OrganizationknowsAbout - [ ] Lazy-loading of the heaviest admin views — deferred: needs live-admin verification (the current RSC / single client-bundle architecture would require a build-time entry split)
☕ Support
If this plugin saves you time, consider buying me a coffee!
📄 License
Licensed under the MIT License. See the LICENSE file for details.
