Skip to content

Catalogue Coverage

A quiz can only recommend products the question flow knows how to score. Catalogue Coverage is the admin page that shows you, per product, whether your current published flow can actually surface it — and if not, what the maximum score it could currently achieve is.

It exists so you can answer “is my recommendation logic complete?” with a chart instead of a hunch.

[SCREENSHOT: The Catalogue Coverage scatter chart, with the “Needs attention” list on the right.]

Dino Discover → Catalogue Coverage in the admin sidebar. The page opens on a scatter chart of every product in your catalogue, with the “Needs attention” list alongside.

The scatter chart plots every published WooCommerce product. Each point sits at the maximum total upvotes that product could receive given the current question flow — i.e. “if a shopper picked the answers that were maximally favourable to this product, how many upvotes would it get?”

Three regions:

  • Top right (well-covered). Products the flow can reach with strong upvote totals. The recommendation engine ranks these competitively.
  • Middle band. Reachable but only modestly — the flow can surface these in some answer combinations but never strongly. Worth checking if there’s an answer that should be upvoting them harder.
  • Bottom (unreachable or near-unreachable). Products the flow can’t recommend at all, or only via a very weak path. These show up in the Needs attention list.

The right column is a sorted list of products with the lowest maximum upvote score, capped at the few-dozen worst. Each row shows:

  • The product name, image, and price.
  • The current maximum score.
  • The number of answers that touch the product (zero is the common flag).

Click a row to open the product’s detail view, which shows the actual answer paths that score this product, ranked by total upvote. From there, you can jump directly into the relevant question in the Builder and add an upvote row.

The default coverage engine (CoverageCalculator) walks every node in the published snapshot, computes the maximum upvote sum a product could achieve along any path through the flow, and writes the per-product result to the dd_coverage_* tables.

A few important properties:

  • It runs against the published snapshot, not the draft. Edits in the Builder don’t change the Coverage page until you publish.
  • It runs nightly on a schedule. The CoverageRefreshJob runs once per day via Action Scheduler.
  • It runs on every publish, debounced. The CoverageDebouncer collapses bursty publishes into a single recompute. So if you publish ten times in a row to iterate on copy, coverage runs once at the end, not ten times.
  • It runs on demand. A Refresh now button at the top of the page schedules an immediate recompute.

Almost never. The scheduled runs and publish-driven runs cover the normal cases. The button is for the rare case where you’ve added or removed products from WooCommerce without changing the quiz — those changes get picked up on the next nightly run, but Refresh now short-circuits the wait.

The page has a small filter bar across the top:

  • By category / tag. Drill into a slice of the catalogue.
  • By score range. Show only products below a threshold, or above one.
  • Include / exclude unreachables. Toggle products with score 0.

The per-product detail view (click any point or list row) shows the top-scoring paths through the flow that would land on this product, plus a “this product is reachable from question X via answer Y” map.

If you want a different reachability metric, the engine is filterable. Implement CoverageEngineInterface:

CoverageEngineInterface::refresh(
DateTimeImmutable $now,
?array $product_ids = null
): CoverageReport;

Return your own CoverageReport value object and use the dino_discover_coverage_engine filter to substitute it. The scatter chart and Needs attention list will read your report instead of the default one.