Skip to main content

Built-in auditors

Each auditor is a stateless service implementing Byte8\SeoSuite\Model\IndexBudget\AuditorInterface. Registered in the AuditorPool via DI.

out_of_stock_indexable

Class: Byte8\SeoSuite\Model\IndexBudget\Auditor\OutOfStock Severity: warning Auto-fix:meta_robots = noindex,follow

Finds enabled, in-catalog (visibility > 1) products that are out of stock and don't already have noindex in their meta_robots value.

Why this matters

OOS products that stay indexable bleed crawl budget and dilute internal PageRank — Google keeps re-crawling them and they rarely produce conversions. The standard fix is noindex,follow (so link equity still flows to other products) until stock returns.

Auto-fix detail

SuggestionApplier loads the product, sets meta_robots = noindex,follow, saves via productRepository->save(). The OOS Rules Engine auto-reverts noindex,follow when stock returns — so this fix doesn't strand products in noindex permanently.

Per-store

Runs once per store. A product OOS in store 1 but in stock in store 2 will be flagged for store 1 only.


disabled_url_rewrite

Class: Byte8\SeoSuite\Model\IndexBudget\Auditor\DisabledIndexable Severity: warning Auto-fix: ✅ Delete the url_rewrite rows

Direct SQL join across url_rewrite × catalog_product_entity_int (status attribute) to find products with status = 2 (disabled) that still have non-redirect rewrite rows.

Why this matters

Magento doesn't auto-clean url_rewrite rows when a product is disabled — it just stops the controller from rendering. But the URL still resolves (typically with a 200 + empty product page or redirects to home), wasting crawl budget. The orphaned rows persist forever unless manually cleaned.

Auto-fix detail

IssueFixer runs:

DELETE FROM url_rewrite
WHERE entity_type = 'product'
AND entity_id = ?
AND store_id = ?

Once the rewrite is gone, requests to the old URL produce a 404 (correct behaviour for a discontinued product).

Per-store

The auditor fires per-store and the auto-fix is per-store. A product disabled in store 1 but enabled in store 2 will keep its store-2 rewrite intact.


layered_nav_explosion

Class: Byte8\SeoSuite\Model\IndexBudget\Auditor\LayeredNav Severity: warning (≥6 filterable attributes), error (≥10) Auto-fix: — (recommendation only)

Counts user-defined product attributes with is_filterable > 0. Above the warning threshold, fires a per-store finding with a recommendation. Also flags top-level categories with no description (thin-content findings, severity info).

Why this matters

With 10 filterable attributes, a single category can produce ~2^10 = 1024 URL variants from filter combinations alone. With pagination + sort options layered on, you can hit hundreds of thousands of crawlable URLs per category. Google will pick a tiny sample and ignore the rest — and your important URLs lose crawl priority.

Two complementary actions:

  1. Reduce is_filterable to attributes that actually drive purchase decisions
  2. Enable Layered Navigation SEO controls to noindex filtered URLs

The auditor's recommendation links to both.

Per-store

Fires once per store (reads global attribute config) plus per-category for thin-content top-level categories.


canonical_config

Class: Byte8\SeoSuite\Model\IndexBudget\Auditor\CanonicalConfig Severity: error (product canonical), warning (category canonical, product URL uses categories) Auto-fix: — (config recommendation)

Three sub-checks against Magento's built-in canonical config:

Sub-codeSeverityMagento config path
product_canonical_offerrorcatalog/seo/product_canonical_tag
category_canonical_offwarningcatalog/seo/category_canonical_tag
product_url_uses_categorieswarningcatalog/seo/product_use_categories

Why this matters

  • Product canonical OFF → products in multiple categories produce duplicate URLs (one per category path); without canonical, Google sees them as separate pages
  • Category canonical OFF → paginated/filtered category URLs don't point back to the unfiltered base
  • Product URL uses categories ON without canonical → catastrophic combination — N categories × M products = N×M crawlable URLs

Toggle the relevant flags via Stores → Configuration → Catalog → Catalog → Search Engine Optimization. The recommendations include the exact admin path.

Per-store

Per-store scope — flags each store independently.


cms_missing_meta

Class: Byte8\SeoSuite\Model\IndexBudget\Auditor\CmsMeta Severity: info Auto-fix: — (manual or AI generate)

Active CMS pages with empty meta_title and/or meta_description. Severity is info because it's a quality issue, not a crawl-budget bleed.

Why this matters

CMS pages with no meta let Google generate one from page content (often awkward), or worse leave the SERP entry blank. Quick to fix manually OR via the AI Meta Generator.

Per-row Generate AI Meta action

When AI is configured (byte8_seosuite/ai/is_active = 1), the Index Budget grid shows a Generate AI Meta button on each cms_missing_meta row. Click it → calls Claude → queues a suggestion → marks the row resolved. Same recipe described in AI Review queue.

Multi-store

CMS pages are typically multi-store (assigned to multiple stores). The auditor records the first store the page is assigned to (or 0 = admin/all stores).


Roadmap (v2.9+)

  • pagination_indexed — detects category pagination URLs without proper canonical strategy
  • xml_sitemap_orphans — sitemap URLs that 404 or noindex
  • redirect_chains — multi-hop 301 chains that bleed link equity
  • mixed_https_canonical — http/https canonical inconsistencies