# Coverage methodology

URL: https://igregulator.io/docs/coverage-methodology/
Markdown: https://igregulator.io/docs/coverage-methodology.md

> How iGregulator measures domain coverage per jurisdiction: what counts in the numerator and denominator of /v1/health/coverage domain_coverage, and its limits.

`/v1/health/coverage` returns a `domain_coverage` object per
jurisdiction:

```json
"MGA": {
  "domain_coverage": {
    "operators_with_domain": 106,
    "normative_operators": 114,
    "coverage_pct": 93
  }
}
```

This page explains what those three numbers mean — because the
honest answer depends on which question you're asking. It covers domain
coverage only; how we read each register and which regulator page sets
each licence status is in our [methodology](https://igregulator.io/methodology/).

## The numbers

| Field | Meaning |
| --- | --- |
| `normative_operators` | Operators in this jurisdiction whose license type is one where **domain disclosure is normative** — i.e., the operator is consumer-facing and the regulator publishes (or could publish) a website field. |
| `operators_with_domain` | Subset of those operators that have **≥1 linked domain** (a row in `domain_operators`) in our DB. |
| `coverage_pct` | `operators_with_domain / normative_operators` × 100. The honest "what fraction of operators we *should* have a domain for, do we?" number. |

## Why exclude non-consumer license types

Different regulators license different activities. A B2B software
supplier or a non-remote arcade operator can hold a perfectly valid
license without ever running a consumer website. Including them in
the denominator deflates coverage in a way that has nothing to do
with our scraper quality — it just measures the regulator's mix of
consumer-facing vs. supplier licenses.

The normative subset filters them out. What's left is operators
where a missing domain is *interesting* — either we missed it
(scraper bug we can fix) or the regulator didn't publish it
(upstream ceiling, defer to enrichment).

## Per-jurisdiction filter

| Jur | Normative subset | Excluded |
| --- | --- | --- |
| **UKGC** | `license_type_raw = 'Remote'` | `Non-Remote` (physical premises), `Ancillary Remote` (B2B suppliers, game studios) |
| **MGA** | `license_number LIKE 'MGA/B2C/%'` | `MGA/B2B/*` (suppliers), `MGA/CRP/*` (Critical Gaming Supply / Recognition / Personal) |
| **CW** | `license_type_raw ILIKE 'b2c%'` | `b2b` (suppliers post-LOK) |
| **KH** | `license_type_raw = 'Interactive Gaming Permit'` | `CSPA` (Casino Software Provider Authorisation, B2B suppliers) |
| **AN** | `'B2C' = ANY(license_types)` | pure-B2B and pure-White-Labeling-only operators |
| **TGC** | `license_type_raw = 'B2C'` | `B2B` (suppliers) |
| **IOM** | `license_type_raw = 'Full'` | `Network Services`, `Software Supply` (B2B — networks and game suppliers) |

For MGA we filter on the license-number prefix because
`license_type_raw` carries the gaming-service breakdown
(`Type 1, Type 2, Type 3, Type 4`), not the B2B/B2C class
distinction.

For AN, operators with mixed `license_types` (e.g., `["B2C","B2B"]`)
**are included** — having any B2C component makes the operator
consumer-facing.

For IOM, `Full` is the Online Gambling Regulation Act licence to offer
gambling to the public; the Isle of Man Gambling Supervision Commission
lists a website in a licensee's profile only "where a licence holder is
actively offering services to the public". A `Network Services` licensee
(a poker network, say) can run a consumer site and still falls outside
the subset — the filter follows the licence type the Commission names.

## Reading the numbers

For a given jurisdiction, `coverage_pct` is the most useful single
indicator of "how complete is iGregulator on this regulator?"
**relative to what's recoverable**. It's not the same as "% of all
licensees that have a domain" — that older framing mixed B2B and
consumer-facing operators and obscured the real ceiling.

Two consequences worth flagging:

- A `coverage_pct` of 0 means either (a) the upstream regulator
  doesn't publish website data at all, or (b) our
  scraper hasn't started picking up the field yet.
- A `coverage_pct` near 100 means we're at the upstream ceiling —
  any remaining gap is operators who haven't disclosed a domain to
  the regulator, not a scraper bug.

## Regulator-verified domains (Curaçao, Tobique)

Curaçao and Tobique publish **no bulk domain list** — but both run a
per-domain verification surface of their own: the CGA certificate
portal (`cert.cga.cw`, including the `/token` registry that lists each
licence's complete approved-domain cluster) and the Tobique validation
seal (`validate.thetgc.ca`). Our coverage for these two jurisdictions
is built directly on those pages:

- Every CW/TGC domain we hold carries the regulator's own
  `verification_url` — surfaced on `/v1/check` so you can confirm the
  verdict against the primary source yourself.
- A **nightly re-verification pass** re-reads up to 500 stored pages
  per jurisdiction, oldest first — every Tobique seal each night, each
  Curaçao certificate every 2–3 days — and
  moves `domain_status` only on a clean read of the regulator's own
  words — in both directions (`active` ↔ `delisted`), never on a
  guess. A page we cannot fetch or parse changes nothing.
- **Weekly discovery** finds what's new: a CGA `/token` registry sweep
  (more complete than the published OGL PDF) and a Tobique
  headless-render pass over candidate casino sites (the seal is
  JS-injected in site footers, so a plain fetch can't see it).

This makes CW/TGC domain rows *stronger* than a register listing: each
one is backed by a regulator page we re-checked within the last three
days.

## Numbers can shift when methodology changes

The `1.4.0` changelog (2026-04-28) introduced this metric. Prior
versions reported coverage as `total_domains / total_licenses` per
jurisdiction, which inflated KH (3+ domains per IGL holder average
made it read 91% even though only 42 of 61 holders had any domain
disclosed) and deflated UKGC (the 17.3% denominator was 2,660 total
ops including 1,594 non-remote licensees, dragging the rate down).

If you compare numbers in a `1.3.x` response to numbers in `≥1.4.0`,
expect movement. The DB hasn't changed — only the question we're
asking it.

## Current per-jurisdiction status

As of 2026-09-30 (read from
[`/v1/health/coverage`](https://api.igregulator.io/v1/health/coverage),
where the live numbers always are):

| Jur | `coverage_pct` | With domain / normative | Reading |
| --- | --- | --- | --- |
| AN | 99% | 1,394 / 1,405 | Near-ceiling — the remaining AN operators chose not to disclose a domain upstream |
| CW | 93% | 566 / 607 | Was 0% until 1.9.0 — built from the CGA's own verification portal (`/token` clusters + certificates), ~4,850 domain links, each re-verified against its certificate every 2–3 days |
| MGA | 93% | 106 / 114 | Post-enrichment ceiling (a handful of B2C operators omit the Website Urls section upstream) |
| KH | 73% | 46 / 63 | Matches the upstream ceiling — the missing IGL holders chose not to disclose |
| UKGC | 55% | 520 / 937 | Upstream ceiling — only Remote-license holders in `domain-names.csv` can be covered |
| TGC | 16% | 28 / 171 | Seal-discovery live (weekly headless-render pass) — growing run by run; the register itself publishes no website column |
| IOM | 88% | 14 / 16 | At the upstream ceiling — the two `Full` licensees without a domain (PlaySmart IOM, Premier Gateway International) have no website in their register profile. 50 domain links across 27 licensees in all, suppliers included |

Questions about a specific jurisdiction's upstream behaviour —
[founder@igregulator.io](mailto:founder@igregulator.io).
