magendoo / module-catalog-quality
Catalog data quality observability for Magento 2 — completeness scoring, filter-blind detection, and gap reporting
Magendoo Catalog Quality — Magento 2 Module
Catalog data quality observability for Magento 2.
Know exactly which products are hurting your conversion rate before your customers find out.
What It Does
Magendoo_CatalogQuality scores every product in your catalog against a two-axis quality model — Enrichment (are the important attributes filled in?) and Consistency (do they meet your content rules?) — and combines them into a single Product Health Score (PHS) between 0 and 100. Products are graded A–E.
The module answers three questions that every Magento merchant needs:
- Which products are incomplete? — The Gap List shows every product's grade, PHS, priority gaps, and the specific missing attribute codes.
- Which products are invisible in layered navigation? — The Filter-Blind detector flags products that have no value for a filterable attribute, making them unfindable when shoppers use your category filters.
- Which filter attributes have the worst coverage across categories? — The Filter Coverage Matrix shows fill rates as a colour-coded heatmap, scoped by attribute set.
No auto-fix. No AI. Just clear, actionable diagnostic data.
Screenshots
Dashboard
[image: Catalog Quality Dashboard]
The dashboard shows the Catalog Health Index (CHI) — a revenue-weighted average PHS across all scored products — alongside grade distribution, filter-blind product count, and a 30-day CHI trend chart.
Product Gap List
[image: Product Gap List]
Every scored product in one grid: grade badge, PHS, P1/P2/P3 gap counts, a filter-blind chip, and colour-coded missing attribute chips. Red chips are filterable attributes directly causing filter-blindness; grey chips are other priority gaps.
Filter Coverage Matrix
[image: Filter Coverage Matrix]
Rows are user-defined filterable attributes; columns are active categories (filterable by attribute set). Each cell shows the fill-rate percentage, colour-coded from green (≥90 %) to red (<35 %). Click a cell to open the Gap List pre-filtered by that attribute and category.
Features
- Two-axis PHS scoring: Enrichment completeness × Consistency conformance multiplier
- A–E grade thresholds: ≥90 → A, ≥80 → B, ≥70 → C, ≥50 → D, <50 → E
- Revenue-weighted CHI: weights products by 90-day revenue when sales data is available
- Filter-blind detection: flags products invisible in layered navigation per store view
- Attribute Priority System: P1/P2/P3/P4/Ignore per attribute, with category and attribute-set overrides
- Placeholder blocklist: regex and literal patterns to catch values like "N/A", "TBD", "Lorem ipsum"
- 9 built-in quality rules: Meta Title, Meta Description, URL Key, Name, Description, Image, Category, Price, Filterable Attribute
- Conditional attribute groups: score module-specific attributes only when their control flag is on (e.g. base-price fields only when
baseprice_is_enabled = 1) - Magento indexer integration: incremental updates via MView, full reindex via CLI
- Nightly CHI snapshots: 30-day trend data stored automatically via cron
- CSV export of the Gap List and Priority table
- REST API: 6 endpoints for scores and priorities
- Inline-editable Priority Grid: change priority levels without leaving the listing
- Filter Coverage Matrix: attribute set filter, product counts per category column, click-through to Gap List
Requirements
| Dependency | Version |
|---|---|
| PHP | ≥ 8.2 |
| Magento Open Source / Adobe Commerce | 2.4.x |
magento/framework |
≥ 103.0 |
magento/module-catalog |
≥ 104.0 |
Installation
Via Composer (recommended)
composer require magendoo/module-catalog-quality
bin/magento module:enable Magendoo_CatalogQuality
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f
bin/magento cache:flush
Manual
- Copy the module directory into
app/code/Magendoo/CatalogQuality/ - Run the same CLI commands above
Initial Setup
After installation, run the full indexer to score all products:
bin/magento indexer:reindex magendoo_cq_product_score
This may take several minutes on large catalogs. The batch size is configurable under Stores → Configuration → Magendoo Extensions → Catalog Quality → Performance.
Admin Screens
Navigate to Catalog Quality in the top-level admin menu.
| Screen | URL | Description |
|---|---|---|
| Dashboard | /catalogquality/dashboard/index |
CHI, grade distribution, filter-blind count, 30-day trend |
| Product Gap List | /catalogquality/gaps/index |
All scored products; filterable by grade, filter-blind status |
| Filter Coverage Matrix | /catalogquality/filters/index |
Attribute fill-rate heatmap per category |
| Attribute Priorities | /catalogquality/priority/index |
Inline-editable priority rules |
Configuration
Stores → Configuration → Magendoo Extensions → Catalog Quality
| Setting | Default | Description |
|---|---|---|
| Enabled | Yes | Master switch |
| Revenue-weighted CHI | Yes | Weight CHI by 90-day product revenue |
| Indexer Batch Size | 500 | Products scored per batch during full reindex |
| Snapshot Retention | 90 days | How long nightly CHI snapshots are kept |
Scoring Algorithm
See docs/scoring-algorithm.md for the full specification.
Summary:
PHS(product, store_view) =
[Σ weight(attr) × completeness_score(attr)] / [Σ weight(attr)] ← enrichment
× conformance_multiplier ← consistency
× 100
completeness_score: empty / placeholder → 0.0 | present → 0.5 | meets_bar → 1.0
conformance_mult: 1.0 baseline; CRITICAL rule failure × 0.7; WARNING × 0.9
CHI = Σ(revenue_90d × PHS) / Σ(revenue_90d) (falls back to equal-weight)
Priority System
See docs/priority-system.md for the full hierarchy.
Quick reference:
| Level | Weight | Meaning |
|---|---|---|
| P1 | 100 | Critical — directly impacts conversions (name, price, image, meta) |
| P2 | 50 | Important — filterable attributes auto-floor here |
| P3 | 20 | Standard — user-defined attributes not yet classified |
| P4 | 5 | Low — nice-to-have |
| Ignore | 0 | Never scored (system attrs, optional promotional fields) |
Priority resolution order (first match wins):
- Explicit row with matching
category_id - Explicit row with matching
attribute_set_id - Explicit global row (no set, no category)
- Implicit: SEO attrs → P1; user-defined filterable → P2; user-defined → P3; else → Ignore
Conditional Attribute Groups
Some module attributes should only be scored when they are relevant for a specific product. Configure this in etc/di.xml:
<type name="Magendoo\CatalogQuality\Model\Scoring\ProductScorer">
<arguments>
<argument name="conditionalGroups" xsi:type="array">
<item name="baseprice" xsi:type="array">
<item name="enabledBy" xsi:type="string">baseprice_is_enabled</item>
<item name="attributes" xsi:type="array">
<item name="0" xsi:type="string">baseprice_product_amount</item>
<item name="1" xsi:type="string">baseprice_unit_id</item>
<item name="2" xsi:type="string">baseprice_reference_amount</item>
</item>
</item>
</argument>
</arguments>
</type>
The enabledBy attribute is never scored itself — it acts as a gate. The listed attributes are only evaluated when the gate attribute is truthy (1). The example above wires up Magendoo_BasePrice so that unit-pricing compliance fields only count as gaps on products where base pricing is switched on.
CLI Commands
# Full reindex — score all products (optionally scoped to a store)
bin/magento catalog-quality:rebuild [--store=<store_id>] [--batch=<size>]
# Debug a single product
bin/magento catalog-quality:score <sku> [--store=<store_id>]
# Example output:
# {"sku":"WH-X500","grade":"D","phs":42.15,"filter_blind":true,"p1_gaps":1,"p2_gaps":2,"missing":["cq_connectivity","cq_color"]}
# Export priorities to CSV
bin/magento catalog-quality:priorities:export [--set=<attribute_set_id>] [--format=csv]
REST API
See docs/rest-api.md for request/response schemas.
| Method | Endpoint | Description |
|---|---|---|
GET |
/V1/catalog-quality/scores/:sku |
Get quality score for a single SKU |
GET |
/V1/catalog-quality/gaps |
List gap records (supports search criteria) |
POST |
/V1/catalog-quality/priorities |
Create or update a single priority rule |
POST |
/V1/catalog-quality/priorities/bulk |
Bulk upsert priority rules |
GET |
/V1/catalog-quality/priorities |
List priority rules |
DELETE |
/V1/catalog-quality/priorities/:id |
Delete a priority rule |
All endpoints require an admin bearer token. Authenticate with POST /V1/integration/admin/token.
Database Tables
| Table | Purpose |
|---|---|
magendoo_cq_priority |
Attribute priority rules (P1–P4/Ignore) per attribute, set, and category |
magendoo_cq_priority_history |
Audit log of priority changes |
magendoo_cq_product_score |
Per-product PHS, grade, gap counts, filter-blind flag |
magendoo_cq_attribute_score |
Per-attribute value states for a product |
magendoo_cq_catalog_snapshot |
Nightly CHI snapshots for trend charts |
magendoo_cq_scope_profile |
Named scope profiles (sellable, pre-launch, full catalog) |
magendoo_cq_rule_config |
Per-rule enabled/severity/parameter overrides |
magendoo_cq_placeholder_blocklist |
Literal and regex patterns for placeholder detection |
magendoo_cq_remediation_queue |
Remediation work queues (Phase 2) |
magendoo_cq_remediation_queue_item |
Items within a remediation queue |
magendoo_cq_rule_run_log |
Indexer run audit log |
Extending
Adding a Custom Quality Rule
- Implement
Magendoo\CatalogQuality\Api\RuleInterface - Register it in
etc/di.xmlunderRulePool
<type name="Magendoo\CatalogQuality\Model\Rule\RulePool">
<arguments>
<argument name="rules" xsi:type="array">
<item name="my_custom_rule" xsi:type="object">
Vendor\Module\Model\Rule\Enrichment\MyCustomRule
</item>
</argument>
</arguments>
</type>
Adding a Conditional Attribute Group
Register a conditionalGroups item as shown in the Conditional Attribute Groups section above.
License
MIT — © 2025 Magendoo Interactive
No changelog yet
The vendor hasn't published a changelog. Tagged releases appear in the Versions tab.
Requires 8
| Package | Constraint |
|---|---|
| magento/framework | >=103.0 |
| magento/module-backend | >=102.0 |
| magento/module-catalog | >=104.0 |
| magento/module-eav | >=102.0 |
| magento/module-indexer | >=100.4 |
| magento/module-store | >=101.0 |
| magento/module-ui | >=101.2 |
| php | >=8.2 |
No QA results yet
QA pipelines haven't run for this version. Compatibility and quality results appear here once the vendor publishes a tagged release that gets ingested.
More from magendoo
View vendorEU Base Price (Grundpreis) display for Magento 2. Shows price per reference unit (kg, litre, m) on product pages, category listings, search results and cart. Compliant with EU Price Indication Directive 98/6/EC and German PAngV.
Shipping Restrictions module
Product labels for Magento 2 - first-class label entities with stable codes, manual assignment via product attribute, rule-computed assignments materialized by an indexer, PLP/PDP badges and GraphQL exposure
EU Omnibus Directive (2019/2161) price tracker for Magento 2. Records price changes with timestamps, computes the lowest prior price in the disclosure window, and displays it on PDP and PLP, with async queue processing for bulk operations.
Turn an existing module into recurring revenue.
If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.