---
title: How the Catalog Health Score Is Calculated
description: "The catalog health score in [Catalog Health Scanner for WooCommerce Pro](https://wpfactory.com/item/catalog-health-scanner-for-woocommerce/) is a single number out of 100 that summarises how much of your catalog passed the checks a scan actually ran. This page explains exactly how it is produced,…"
url: "https://wpfactory.com/docs/catalog-health-score/"
updated: "2026-10-05"
category: References
tags:
  - Catalog Audit
---

# How the Catalog Health Score Is Calculated

The catalog health score in [Catalog Health Scanner for WooCommerce Pro](https://wpfactory.com/item/catalog-health-scanner-for-woocommerce/) is a single number out of 100 that summarises how much of your catalog passed the checks a scan actually ran. This page explains exactly how it is produced, so you can predict what a fix will do to it before you make one.

Nothing about the score is a black box: it is a weighted pass ratio, computed from counters stored on the scan itself. Catalog Health Scanner keeps those counters so a score can be recomputed later without rescanning.

### Step 1: every check is worth its severity weight

Each check that ran contributes a fixed number of points, set by its severity:

| Severity | Weight |
| --- | --- |
| Critical | 4 |
| High | 2 |
| Medium | 1 |
| Low | 0.5 |

A check is worth the same whether it flagged one product or a thousand. What changes is how much of its weight you earn.

### Step 2: each check earns its weight in proportion to the products that passed

During a scan, every check keeps two counters: `checked` (how many products the check actually ran on) and `failed` (how many of those produced an open issue). The points earned are:

`earned = weight x (checked - failed) / checked`

So a High check (weight 2) that ran on 400 products and failed on 40 earns 2 x (360 / 400) = 1.8 of its 2 points. A check with `checked` of zero, because nothing in the catalog matched its product type or its store condition, is left out of the score entirely rather than scored as a pass.

The nine cross-product checks work slightly differently: their `checked` value is the total published product count of the scan, and `failed` is the number of distinct products with an open issue from that pass.

### Step 3: category fractions

Points are added up per category as *earned* over *possible*. The category cards on the dashboard show that fraction, and the band badge is that fraction expressed as a percentage. A category with 6 of 7 points is at 85.7 percent, which is a Minor issues badge.

### Step 4: the weighted total

The overall score is the sum of every category earned divided by the sum of every category possible, multiplied by 100 and rounded to two decimals:

`total = (sum of earned / sum of possible) x 100`

Because the divisor is the total possible points rather than a fixed 100, categories with more checks and heavier severities carry more of the score. Purchasability, with five critical checks, moves the number far more than Feed Readiness does. If a scan produced no scorable checks at all, the total is 100.

### Step 5: one open critical issue caps the total at 89

If the arithmetic produces more than 89 while any scored critical check has at least one failure, the total is set to **89.00** and the scan is marked as capped. A store with a product that cannot be bought is not in a healthy state, whatever the average says, and the cap keeps it out of the green band.

Three details matter here:

- The cap is derived from the scan's own counters, not from a live query, so recalculating an old scan reproduces exactly what that scan saw.
- Critical checks in a group that is not scored (not applicable, or report only) cannot trigger the cap.
- Ignored issues never increment `failed`, so an ignored critical does not cap anything.

### Score bands

| Score | Band | Reading |
| --- | --- | --- |
| 90 to 100 | Healthy | Nothing critical is open and the rest is largely clean. |
| 75 to 89.99 | Minor issues | Worth a triage pass. Any capped score lands here. |
| 50 to 74.99 | Needs attention | A meaningful share of the catalog is failing checks that cost money. |
| Below 50 | Critical | Most of what was scanned is failing. Start with the Revenue Blockers profile. |

The same bands are reused for the category cards, applied to that category's own earned over possible fraction.

![Catalog Health Scanner showing 84% overall health score and detailed category analysis.](https://wpfactory.com/wp-content/uploads/Catalog-Health-Scanner-Dashboard.png)

### What leaves the score, and how

| Situation | Does the check run? | Effect on the score |
| --- | --- | --- |
| Group set to *Not applicable*, or auto-detected as not applicable | No | The check leaves both sides of the fraction. Nothing is earned and nothing is possible, so the remaining checks are judged on their own terms. |
| Group set to *Report, but do not score* | Yes | Issues are found and listed, but the check leaves both sides of the fraction and cannot trigger the critical cap. |
| Check unticked under Settings > Individual checks | No | It leaves both sides of the fraction, on every scan, until you tick it again. |
| Check not part of the profile you ran | No | It leaves both sides of the fraction for that scan only. |
| Issue ignored on a product | Yes | The product is counted in `checked` but never in `failed`, so it counts as passing. |
| Product inside the grace window, or in an excluded category | Not for that product | The product is counted as skipped and is absent from every counter, so it neither helps nor hurts. |

The important consequence of "leaves both sides" is that removing a check never inflates or deflates the score by itself. A store that turns off Shipping is not rewarded with free points; it is scored on the checks that remain.

### A worked example

Take a store with 200 published products, running a profile with five checks in two categories. After the scan the counters look like this:

| Check | Severity | Weight | Checked | Failed | Earned |
| --- | --- | --- | --- | --- | --- |
| `no_price` | Critical | 4 | 200 | 2 | 4 x (198 / 200) = **3.96** |
| `sale_not_lower` | High | 2 | 200 | 10 | 2 x (190 / 200) = **1.90** |
| `hidden_from_catalog` | Medium | 1 | 200 | 0 | 1 x (200 / 200) = **1.00** |
| `image_missing` | High | 2 | 200 | 20 | 2 x (180 / 200) = **1.80** |
| `image_alt_missing` | Medium | 1 | 180 | 90 | 1 x (90 / 180) = **0.50** |

Note that `image_alt_missing` only ran on 180 products: the 20 products with no featured image at all are skipped by it, because they are already covered by `image_missing`.

Category totals:

| Category | Earned | Possible | Fraction | Band |
| --- | --- | --- | --- | --- |
| Purchasability | 6.86 | 7.00 | 98.0% | Healthy |
| Media | 2.30 | 3.00 | 76.7% | Minor issues |

Weighted total: (6.86 + 2.30) / (7.00 + 3.00) x 100 = **91.6**.

But `no_price` is Critical and failed on two products, so the cap applies and the dashboard shows **89.00** with a note that a critical issue is holding it there.

Now price those two products and rescan. `no_price` earns its full 4 points, Purchasability reaches 7.00 of 7.00, the total becomes (7.00 + 2.30) / 10.00 x 100 = **93.0**, and the cap no longer applies. Two products moved the headline number by four points, because they were the only thing standing between the store and the green band.

Fixing the 90 missing alt texts instead would have earned 0.5 more points, moved the raw total from 91.6 to 96.6, and still displayed 89.00 while the two unpriced products stayed open. That is the cap doing its job.

### Historic scores are recalculated when applicability changes

A trend line is only useful if every point on it was measured the same way. When you change any applicability setting and save, Catalog Health Scanner replays the stored counters of up to the last 500 completed scans through the current configuration and rewrites the scores that come out different.

- Nothing is rescanned. Only the stored per-check counters are re-scored.
- A scan whose score does not change is left untouched.
- A scan whose score does change records the time of the recalculation and its original score, so the history screen can mark it.

This is why the number next to an old scan can differ from the number you remember: switching Tax to *Not applicable* removes tax checks from every historic score at once, rather than producing a step in the graph that means nothing.

### Common reasons a score does not move

- The score is capped at 89 by an open critical issue somewhere else in the catalog.
- You fixed a Low severity check, worth 0.5 points out of a possible total that may run into the dozens.
- You fixed a handful of products on a check that failed on hundreds, so the pass ratio barely moved.
- The check belongs to a group set to *Report, but do not score*.
- The profile you rescanned with does not include the check you fixed.

More on this in the [FAQ and troubleshooting](https://wpfactory.com/docs/catalog-health-faq/) article.

### Related reading

- [Check library: all 70 checks](https://wpfactory.com/docs/catalog-health-checks-reference/), with the severity of every check
- [Applicability: why checks are skipped](https://wpfactory.com/docs/check-applicability/)
- [The dashboard and health score](https://wpfactory.com/docs/catalog-health-dashboard/)
- [Scan history and comparison](https://wpfactory.com/docs/scan-history-compare/)

### Need help?

If a score does not match what you expect after reading this, contact [Catalog Health Scanner support](https://wpfactory.com/support/) with the scan date, the profile you ran, and the category breakdown from the dashboard.

Related articles

- [Catalog Health Scanner Settings Reference](https://wpfactory.com/docs/catalog-health-settings/)
- [What Catalog Health Scanner Does (and What It Does Not)](https://wpfactory.com/docs/catalog-health-scanner-overview/)
- [Install Catalog Health Scanner and Run the Setup Wizard](https://wpfactory.com/docs/install-catalog-health-scanner/)
- [Catalog Health Scanner Developer Reference](https://wpfactory.com/docs/catalog-health-developers/)
- [Run Your First Catalog Scan](https://wpfactory.com/docs/run-your-first-scan/)
