# SEO Suite — Improvement & Growth Plan

> Package: capell-app/seo-suite · Kind: package · Tier: premium · Product group: Capell Search & SEO · Bundle: search-seo · Status: Draft

## 1. Snapshot

SEO Suite is the premium search/SEO package for the Capell CMS. It bolts metadata panels, schema.org structured data, broken-link tracking, Google Search Console insights, PageSpeed audits, AI-assisted content/metadata generation (via Prism), and an "AI Discovery" surface (`llms.txt`, `llms-full.txt`, per-page Markdown, AI-crawler `robots.txt`) onto core pages and sites. Domain logic is correctly concentrated in ~90 Actions under `src/Actions`, with admin pages/widgets/extenders delegating to them, Data objects at boundaries, and public Blade/controllers driven by view composers and cached responses.

- **Surfaces:** `admin`, `frontend`, `console` (manifest `surfaces`).
- **Key Actions:** `BuildPageSeoReportAction`, `CalculateSeoScoreAction`, `SuggestInternalLinksAction`, `BuildSeoSuiteDoctorReportAction`, `GenerateLlmsTxtAction`, `BuildRobotsTxtAction`, `RunPageSpeedAuditAction`, `SyncSearchConsoleInsightsAction`, `ResolvePageStructuredDataAction`, `SchemaGraphAction`.
- **Models/tables (13 required):** `broken_links`, `page_seo_snapshots`, `page_speed_audit_runs`, `page_speed_audit_results`, `search_console_url_metrics`, `search_console_query_metrics`, `ai_generation_histories`, `ai_creator_contexts`, `ai_creator_sessions`, `ai_discovery_site_profiles`, `ai_discovery_page_profiles`, `ai_discovery_crawler_rules`, `ai_discovery_snapshots`.
- **Dependencies — requires:** `capell-app/admin`, `capell-app/frontend`, `capell-app/insights`, `capell-app/site-discovery`, plus `prism-php/prism ^0.100`. **supports:** `capell-app/blog`, `capell-app/publishing-studio`, `capell-app/url-manager`. **conflicts:** none.
- **Marketplace summary:** "Ship search-ready pages by default: live SEO scoring, schema.org structured data, broken-link and redirect management, Google Search Console insights, and first-class AI-discovery output (`llms.txt`, page Markdown, AI-crawler controls) — all inside the Capell page editor."
- **Screenshots in manifest:** 14 runner-backed light/dark admin PNGs are promoted from `docs/screenshots/`: page SEO panel, SEO audit, Search Console insights, broken links, AI Creator action, sitemap, and translation coverage.

## 2. Improvements (existing functionality)

- **Done/Shipped: the full `SeoCheckKeyEnum` set is wired into page reports.** `BuildPageSeoReportAction::enabledChecks()` now covers all 15 enum cases and `addTechnicalIssues()` emits canonical, schema, image-alt, internal-link, broken-link, redirect, social-image, translation, sitemap, `llms.txt`, and Search Console issues or passed checks. Evidence: `BuildPageSeoReportActionTest` asserts every SEO check key is accounted for in report issues or passed checks, and translation labels/messages exist for every wired check. `src/Actions/BuildPageSeoReportAction.php`, `src/Enums/SeoCheckKeyEnum.php`, `resources/lang/en/generic.php`, `tests/Integration/Actions/BuildPageSeoReportActionTest.php`. **Effort: L**

- **Done/Shipped: `SeoSuiteHealthCheck` performs real keyed diagnostics.** The manifest health keys now route to targeted diagnostics: page reports and broken links check storage plus service bindings, schema graph checks service bindings plus template registry, and AI Discovery checks storage, routes, services, and crawler policy. Evidence: `SeoSuiteHealthCheckTest` maps all four manifest keys and verifies unknown keys return no diagnostics. `src/Health/SeoSuiteHealthCheck.php`, `tests/Feature/Health/SeoSuiteHealthCheckTest.php`. **Effort: M**

- **Weight the SEO score instead of flat severity penalties.** `CalculateSeoScoreAction` is `100 − Σ severity penalty` (Critical 25 / Warning 10 / Notice 3). A page missing only canonical scores identically to one missing alt text; there is no per-check weight or category breakdown. Introduce check-category weights and return a structured breakdown (on-page / technical / structured-data / links) so the widget can show sub-scores. `src/Actions/CalculateSeoScoreAction.php`, `src/Enums/SeoIssueSeverityEnum.php`. **Effort: M**

- **Done/Shipped: public-output leak scanning covers Capell authoring/admin markers.** `PublicOutputLeakScanner` now detects bounded admin/Filament URLs, authoring routes, Livewire internals, editor metadata keys, structured model/page/field identifiers, permission markers, and draft/unpublished flags while avoiding ordinary prose false positives. Evidence: unit coverage for marker detection/redaction/false positives plus doctor command coverage for generated output leak labels. `src/Support/PublicOutputLeakScanner.php`, `tests/Unit/Support/PublicOutputLeakScannerTest.php`, `tests/Feature/Console/SeoSuiteDoctorCommandTest.php`. **Effort: M**

- **Upgrade internal-link suggestions beyond ≥4-char token overlap.** `SuggestInternalLinksAction` tokenises titles/content and scores by literal token intersection, capped at 5. The package already ships an AI/embedding stack (Prism, `AiTokenCounter`) yet links ignore it. Offer an optional embedding/semantic-similarity strategy and surface anchor-text suggestions, not just target pages. `src/Actions/SuggestInternalLinksAction.php`, `src/Support/InternalLinks/InternalLinkCandidateRepository.php`. **Effort: L**

- **Make `defaultPageSpeedDigestRecipients()` query-efficient.** It calls `$userModel::query()->get()` and filters every user in PHP via `hasRole`/`isGlobalAdmin`. On a large user table this loads the whole table into memory each schedule resolve. Push the role filter into the query (`whereHas('roles', …)` / role scope). `src/Providers/SeoSuiteServiceProvider.php` (L849-868). **Effort: S**

- **Persist AI cost, not just tokens.** `RecordAiGenerationAction` stores `prompt_tokens`/`completion_tokens`/`total_tokens`/`duration` but no monetary cost and no model-price table; `PrismProvider::chat()` logs token metrics at `debug` only. Buyers expect a spend dashboard. Add a cost column/derivation and roll it into `AiUsageWidget`. `src/Actions/Ai/RecordAiGenerationAction.php`, `src/Support/PrismProvider.php`. **Effort: M**

- **Scope the AI circuit breaker per provider/site.** `PrismProvider` uses a single global cache key `ai_circuit_breaker_state`; one site's provider outage trips AI generation for every site and provider. Key it by provider (and optionally site). `src/Support/PrismProvider.php` (`CIRCUIT_BREAKER_KEY`). **Effort: S**

- **Index the duplicate-title check.** `BuildPageSeoReportAction::duplicateTitleExists()` runs `whereHas('translations', … where 'meta->title' = ?)`, a JSON-path scan per audited page with no supporting index. At scale this is slow and runs inside the synchronous report. Consider a generated/indexed title column or a cached title set. `src/Actions/BuildPageSeoReportAction.php`. **Effort: M**

- **Surface crawler-preview reports in the admin UI.** Both `docs/overview.md` ("Remaining Roadmap") and the action `BuildCrawlerPreviewReportAction` exist, but the README still lists "Wire crawler-preview reports into the admin diagnostics UI" as outstanding — the report has no admin page/tab. `src/Actions/BuildCrawlerPreviewReportAction.php`, `src/Filament/Pages/`. **Effort: M**

- **Shipped 2026-06-08: consume media alt text in image schema.** `BuildPageImageSchemaAction` now falls back to media `alt` metadata for the ImageObject description when no explicit image description exists, so Media AI-generated alt text and Media Library metadata feed SEO structured output. `capell.json` now declares `media-library` / `media-ai` supports plus `seo-suite-media-metadata`. `src/Actions/BuildPageImageSchemaAction.php`, `tests/Unit/Actions/BuildPageImageSchemaActionTest.php`. **Effort: S**

## 3. Missing Features (gaps)

- **On-page content analysis (H1 presence/uniqueness, heading order, word count, keyword in title/URL/first paragraph, keyword density, readability).** Absent entirely — the audit never inspects rendered body content. Ties to capability `seo-suite` / `seo-suite-structured-data-audit` adjacency. **Table-stakes** (core Yoast/RankMath feature).

- **Focus-keyword workflow.** There is a `NormalizeTargetKeywordsAction` and keyword plumbing into prompts, but no per-page "focus keyword + scored analysis" loop that the audit grades against. **Table-stakes.**

- **OG/Twitter card validation + live preview correctness.** `BuildSocialMetaAction`/`SocialMetaData` build tags and the report has a `socialPreview`, but `socialPreview.imageUrl` is hard-coded `null` in `BuildPageSeoReportAction`, and there is no validation (missing OG image, wrong dimensions, missing `twitter:card`). **Table-stakes.**

- **Redirect manager UI.** `CreateRedirectForBrokenLinkAction` and `BuildRedirectOpportunityReportAction` exist, but there is no first-class redirect CRUD/import surface (regex/410/bulk) — redirect creation is only a reaction to broken links. **Table-stakes** for an "SEO suite."

- **XML sitemap ownership clarity / sitemap index + image/video/news sitemaps.** Sitemaps are delegated to `capell-app/site-discovery`; SEO Suite only reports parity. Buyers expect the SEO product to own sitemap segmentation, priority, and submission. **Differentiator** if pulled in, otherwise document the boundary loudly.

- **AI-answer / GEO visibility tracking.** The package writes `llms.txt` and AI-crawler rules but never measures whether the site is cited by ChatGPT/Perplexity/AI Overviews. Given the AI Discovery investment this is the natural premium **differentiator**.

- **Search Console: query→page opportunity surfacing (CTR/position striking-distance).** Metrics are imported (`search_console_query_metrics`) and there are movement/decline actions, but no "position 11-20 striking-distance" or "high-impressions/low-CTR" opportunity report tied to the page editor. **Differentiator.**

- **Bulk metadata editing / CSV export-import of titles & descriptions.** AI suggests them one page at a time; there is no grid bulk-edit or import. **Table-stakes** at premium tier.

- **User-level authorization for AI generation.** `AiCreatorPolicy` only answers "is the feature enabled for this site" — there is no per-user gate on who may spend AI budget. **Table-stakes** (cost-control / security).

- **Scheduled site-wide re-crawl / broken-link sweep.** Broken links are recorded reactively via `UrlVisitFailed`; there is no scheduled crawler that proactively re-checks known URLs. **Table-stakes.**

## 4. Issues / Risks

- **Done/Shipped: AI Discovery public-output safety is covered for anonymous and non-admin users.** `GenerateLlmsTxtActionTest` now reuses `PublicOutputLeakScanner` for the existing anonymous output test and adds signed-in non-admin coverage for `/llms.txt`, `/index.md`, and `/robots.txt`, asserting generated content contains no admin/editor leak labels. Broader leak scanner strengthening remains a separate Now row. **`tests/Integration/AiDiscovery/GenerateLlmsTxtActionTest.php`, `src/Support/PublicOutputLeakScanner.php`.**

- **Done/Shipped: manifest cache-safety metadata now reflects generated AI Discovery output.** `capell.json` declares `cacheable: true`, `variesBy: ["site", "locale"]`, and invalidation sources for `Page`, `AiDiscoverySiteProfile`, `AiDiscoveryPageProfile`, and `AiDiscoveryCrawlerRule` saves/deletes, matching the cached `llms.txt`/Markdown/robots output contract. **`capell.json` (performance.cacheSafety), `src/Http/Controllers/*`, `src/Providers/SeoSuiteServiceProvider.php`.**

- **`frontendRenderBudgetMs: 20` is at risk for schema rendering.** `WebsiteSchemaComposer`/`SchemaComponentComposer` run during frontend render and call `SiteMetaSchemaAction`/`PageMetaSchemaAction`/`BreadcrumbsSchemaAction` synchronously; `BuildPageImageSchemaAction` triggers `loadMissing(['image','media'])` via `registerFrontendContextHydration`. With multiple schema components on a page, hitting a 20 ms budget without view caching is optimistic. Add a render benchmark/guard. **`src/View/Composers/`, `src/Actions/SiteMetaSchemaAction.php`, `capell.json` (performance).**

- **Done/Shipped: manifest settings, permissions, PageSpeed, and shipped admin surfaces are declared.** `capell.json` lists `AIOrchestratorSettings` and `SeoSuiteSettings`, page/settings/AI permissions, Search Rankings and Translation Coverage admin-page contributions, AI Discovery routes, supported Blog/Publishing Studio/URL Manager integrations, and PageSpeed audit/digest capabilities. Marketplace/automation can now read the shipped SEO Suite surface area from the manifest. **`capell.json`.**

- **Empty CHANGELOG.** `CHANGELOG.md` has only a placeholder "Prepared package metadata…" line. A premium first-party paid package with priority support needs real release notes. **`CHANGELOG.md`.**

- **Docs drift.** `docs/overview.md` lists migrations dated `2026_04_18_*` and omits `RobotsTxtController` in one place / PageSpeed tables; actual migrations are `2026_05_10_*` and `2026_05_29_*`. **`docs/overview.md`.**

- **i18n completeness unverified for new strings.** Only `resources/lang/en/` exists. Every new check label, doctor message, and PageSpeed/notification string must resolve via `__()` keys (`capell-seo-suite::generic.seo_check_*`); there is no second locale to prove keys exist and no test asserting all `SeoCheckKeyEnum` labels have translations. **`resources/lang/en/*`, `src/Enums/SeoCheckKeyEnum.php`.**

- **AI robustness edge: token-usage assumption.** `PrismProvider::chat()` reads `$response->usage->promptTokens + completionTokens` and `$response->usage` unconditionally for the debug log; a provider returning null usage (some Prism providers / Ollama) would throw inside the success path after a successful generation. Guard usage access. **`src/Support/PrismProvider.php`.**

- **Done/Shipped: keyed SEO Suite health diagnostics.** `SeoSuiteHealthCheck` now exposes the full diagnostic set plus key-specific checks for the four manifest health rows, avoiding one generic dashboard result for every SEO surface. **`src/Health/SeoSuiteHealthCheck.php`, `tests/Feature/Health/SeoSuiteHealthCheckTest.php`.**

## 5. Marketplace & Selling

**Critique of current copy.** The `capell.json` marketplace `summary` and composer `description` diverge. Composer says "SEO tools for Capell (metadata panels, structured data, social meta, AI ai-orchestrator)" — note the literal, unpolished token "AI ai-orchestrator", which also leaks into the config prompt strings ("You are a helpful ai-orchestrator…"). The manifest summary is a flat, comma-spliced feature list ("adds X, Y, Z, and diagnostics") with no benefit, no audience, and no hook — it reads like a changelog, not a pitch.

**Improved 1-sentence summary:**

> Ship search-ready pages by default: live SEO scoring, schema.org structured data, broken-link and redirect management, Google Search Console insights, and first-class AI-discovery output (`llms.txt`, page Markdown, AI-crawler controls) — all inside the Capell page editor.

**Improved 3–4 sentence listing description:**

> SEO Suite turns Capell into a search-and-AI optimisation platform. Editors get an in-context SEO panel that scores every page, previews Google and social results, and suggests internal links and metadata with optional AI assistance, while operators get broken-link tracking, redirect opportunities, Search Console dashboards, and PageSpeed audits. It is the only Capell package built for the AI-search era: generate and govern `llms.txt`, `llms-full.txt`, and per-page Markdown, and control exactly which AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, CCBot) may train on or surface your content. A built-in doctor verifies route ownership, content types, cache headers, sitemap parity, and public-output safety so generated SEO output never leaks admin internals.

**Screenshot/media gaps.** The marketplace block now promotes 14 committed Capell runner PNGs for page SEO, audit, Search Console, broken links, AI Creator, sitemap, and translation coverage. Remaining high-converting captures require runner fixture depth rather than metadata edits: AI Discovery profiles, SEO settings, not-found URL data from Insights, public `llms.txt`/`robots.txt`/Markdown plain-text output, an animated GIF of the AI metadata-suggestion flow, a before/after SEO-score shot, and the AI-crawler policy toggle screen.

**Pricing/tier/bundle positioning.** `premium` + `search-seo` bundle + `paid`/`first-party`/`priority`/private-docs is appropriate — this is a deep, schema-owning, AI-integrated package, not an add-on. Manifest supports now explicitly name `capell-app/blog`, `capell-app/publishing-studio`, `capell-app/url-manager`, `capell-app/media-library`, and `capell-app/media-ai`, matching shipped article schema, publish gates, redirect opportunities, and media metadata consumers. Position AI Discovery + Search Console as the upsell hook over a hypothetical free/basic metadata tier, and bundle naturally with an Insights/Analytics Extension Suite.

**Top differentiators / value props.** (1) AI-search/GEO readiness as a native, governed feature — rare in CMS SEO plugins. (2) Public-output safety doctor — a trust feature no Yoast competitor markets. (3) One editor surface spanning metadata, schema, links, Search Console, and PageSpeed. **Target buyer persona:** the Capell agency/site-operator who manages multi-site, multi-language properties and is being asked by clients "are we visible in ChatGPT/AI Overviews?".

**Suggested keywords/tags:** `seo`, `structured-data`, `schema.org`, `llms.txt`, `ai-seo`, `generative-engine-optimization`, `search-console`, `pagespeed`, `broken-links`, `redirects`, `meta-tags`, `open-graph`.

## 6. Prioritized Roadmap

| Item                                                                                                                                                                                                                                                | Bucket | Effort | Impact | Section ref                                                                                  |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ------ | ------ | -------------------------------------------------------------------------------------------- |
| Done/Shipped: Add anonymous/non-admin public-output safety tests for `/llms.txt`, `/index.md`, `/robots.txt`. Evidence: `GenerateLlmsTxtActionTest` covers anonymous and signed-in non-admin AI Discovery output through `PublicOutputLeakScanner`. | Done   | M      | High   | §4                                                                                           |
| Done/Shipped: Wire up the 11 dormant `SeoCheckKeyEnum` checks (canonical, schema, alt, links…). Evidence: `BuildPageSeoReportAction` covers all 15 enum cases and integration coverage asserts every key appears in issues or passed checks.        | Done   | L      | High   | §2                                                                                           |
| Done/Shipped: Make `SeoSuiteHealthCheck` perform real per-key probes. Evidence: `SeoSuiteHealthCheckTest` covers manifest key mapping for page report, schema graph, broken links, and AI Discovery.                                                | Done   | M      | High   | §2/§4                                                                                        |
| Done/Shipped: Strengthen `leakMatches()` beyond `signature=`/`expires=`. Evidence: scanner tests cover authoring/admin/Livewire/editor/model/page/draft markers plus false-positive-safe public prose.                                              | Done   | M      | High   | §2/§4                                                                                        |
| Shipped 2026-06-05: Correct manifest `cacheSafety`, `permissions`, `settings`, PageSpeed capabilities                                                                                                                                               | Done   | S      | Med    | §4                                                                                           |
| Fix `defaultPageSpeedDigestRecipients()` to filter in-query                                                                                                                                                                                         | Done   | S      | Med    | §2 — Done 2026-06-04: role filtering now stays in the recipient query with focused coverage. |
| Done/Shipped: Scope AI circuit breaker per provider; guard null Prism usage. Evidence: `PrismProviderAndCacheTest` covers provider-isolated breaker state and missing Prism usage on the chat success path.                                         | Done   | S      | Med    | §2/§4                                                                                        |
| Done/Shipped 2026-06-08: Weighted SEO score with category breakdown. Evidence: `CalculateSeoScoreActionTest` covers category weighting and bounded scores, and the page SEO panel renders breakdown data.                                           | Done   | M      | High   | §2                                                                                           |
| Done/Shipped 2026-06-08: On-page content analysis (H1, headings, word count, keyword density). Evidence: `AnalyzePageContentActionTest` covers heading order, H1 count, word count, and keyword density inputs.                                     | Done   | L      | High   | §3                                                                                           |
| Done/Shipped 2026-06-08: Focus-keyword workflow graded by the audit. Evidence: `BuildPageSeoReportActionTest` proves missing H1, heading order, and focus keyword issues enter the report and score breakdown.                                      | Done   | M      | High   | §3                                                                                           |
| Done/Shipped 2026-06-08: Redirect manager UI (bulk/regex/410). Evidence: URL Manager now imports empty-target 410 rows, resolves managed 410 rules separately from redirects, and registers middleware before 404 capture.                          | Done   | L      | High   | §3                                                                                           |
| Done/Shipped 2026-06-08: User-level AI-generation authorization + cost persistence/dashboard. Evidence: lifecycle, pipeline, policy, and AI metrics tests cover permission checks, cost recording, and dashboard spend totals.                      | Done   | M      | Med    | §2/§3                                                                                        |
| Recapture SEO Suite workflow screenshots before promotion; generic dashboard/settings and duplicate Site Health captures were demoted. Deferred until styled runner recapture is available; not an implementation blocker.                          | Later  | S      | Med    | §5                                                                                           |
| Done/Shipped: Promote real screenshots + rewrite marketplace summary/description. Evidence: `capell.json` and Composer copy now share the search-ready summary, and marketplace media promotes 14 committed Capell runner PNGs.                     | Done   | S      | High   | §5                                                                                           |
| Shipped 2026-06-08: Consume Media Library / Media AI image metadata in schema output                                                                                                                                                                | Done   | S      | Med    | §2/§5                                                                                        |
| Embedding/semantic internal-link + anchor-text suggestions                                                                                                                                                                                          | Later  | L      | Med    | §2/§3                                                                                        |
| AI-answer/GEO visibility tracking (ChatGPT/Perplexity/AI Overviews citations)                                                                                                                                                                       | Later  | L      | High   | §3                                                                                           |
| Search Console striking-distance opportunity report in editor                                                                                                                                                                                       | Later  | M      | Med    | §3                                                                                           |