# TEEI Impact Measurement Methodology

> How TEEI produces the figures it publishes: what counts as a session, how attendance is verified, how hours are calculated, what is excluded and why, and where the data is weak. Written so the numbers can be reproduced and cited.

Source: https://theeducationalequalityinstitute.org/about/impact/methodology/
Dataset version: 2.3.0
Historical half frozen: 2026-07-23
Live half: continuous, at https://theeducationalequalityinstitute.org/api/impact-stats.json
Maintainer: Henrik (TEEI) / Documentation Team
Licence: CC BY 4.0

---

## 1. What we measure

Four figures carry TEEI's public claims: completed sessions, verified conversation hours, member countries, and active volunteer and learner countries. Each is read from system records rather than reported by hand.

- **Hours basis.** CONVERSATION basis chosen by Henrik 2026-07-22 ("JA oppdater til å bruke dette"): bothInVideoTime = measured minutes both participants were in video, the strongest verifiable claim. Scheduled-duration kept as secondary.
- **Countries basis.** MEMBERS footprint chosen as the headline (all profiles with valid ISO country, 100% coverage) with active-volunteer countries as the second line.

The stricter choice was taken in both cases.

## 2. Data sources

| Source | Period | What it provides |
|---|---|---|
| Third-party platform used until 2026 | 2022-04-22 to 2026-07-23 | 16,312 language bookings and 863 mentorship bookings, pulled in full from the booking API. Frozen. |
| TEEI's own platform | 2026 onward | Booking records and per-session attendance settlements written by the video infrastructure. Re-queried continuously. |

Neither source is a registration count. The two halves are added, never joined: the historical records live in quarantined tables the live query is structurally forbidden from reading.

## 3. Definition of a completed session

> Source-specific legacy completed bookings plus live attendance-verified 1:1 bookings. The combined total is not proof that every legacy booking passed the live attendance threshold. Group attendance remains a separate metric.

Both conditions must hold: the booking status reached completed, and the attendance settlement written afterwards independently agrees, with shared presence above the floor.

## 4. How attendance is verified

Attendance comes from the video infrastructure's join and leave events, not from anyone marking a box. For each session the system takes both participants' connected intervals and computes the **overlap**: time both people were in the room simultaneously. Reconnections do not double count.

| Rule | Value |
|---|---|
| Presence floor | 5 minutes of shared presence; below this the session does not count |
| Crediting cap | measured time, capped at booked window plus 30 minutes grace |
| Fallback cap | 4 hours, only when a booking window cannot be parsed |
| Rounding | floored to a tenth of an hour, never rounded up |

The floor is enforced in four independent places, including a database constraint that refuses to store a completed settlement below it.

## 5. How hours are calculated

> ONE basis on both sides since v2.3.0. Kintell: bothInVideoTime minutes on completed bookings. Live platform: a stored per-session field holding the shared connected time, the overlap of the two participants' connected intervals, credited at min(measured, booked window + 30 min grace). Both measure the same thing: time BOTH participants were in the room. The v2.2.0 mixed basis (live on scheduled duration) is retired.

Because time is floored and capped, and sessions below the floor contribute zero, the published hours figure is a **lower bound**.

## 6. How participants and countries are counted

> A Kintell profile with a valid ISO-2 country (9,888 of 9,889) or a live-platform tutor/learner record with a resolvable country.

> Legacy activity/card criterion where recorded; live profile inclusion uses a different basis. Do not describe the country/profile projection as all recently active volunteers.

Country figures count **countries, not people**, on a **RESIDENCE (where the person is). Frozen from v2.0.0, unchanged by the v2.1.0 origin layer.** basis: where a person is, not citizenship or affiliation.

| Figure | Countries | Underlying records |
|---|---|---|
| Members | 148 | 10,028 |
| Active volunteers | 127 | 2,722 |
| Active learners | 65 | 1,036 |

**127 plus 65 does not equal 148, and should not.** The two role sets overlap in 64 countries, so their union is 128. Both are strict subsets of the member set; the remaining 20 countries have registered members with no recorded session. Never sum the role figures.

## 7. Duplicate and invalid-record handling

Bookings that did not result in a verified session are excluded, not adjusted. Historical language dataset:

| Status | Bookings excluded |
|---|---|
| `provisional-request-expired` | 2,413 |
| `cancelled-confirmed` | 1,651 |
| `cancelled-provisional` | 876 |
| `expired-learner-no-show` | 353 |
| `expired-advisor-no-show` | 312 |
| `expired-both-no-show` | 136 |
| `confirmed` | 13 |
| `completed` (kept, then attendance-tested) | 10,558 |

> Kintell member counts are per-profile per-group (a person in both LFU and MFU counts in each). Cross-platform (Kintell vs live) dedup is best-effort, mirrors teei.core.yaml.

On the live platform each booking carries at most one attendance settlement, enforced by a primary key. Triggers forbid a settlement disagreeing with its booking status, and forbid rewriting a status once a final settlement exists.

**Not excluded, stated openly:** no filter for staff, internal or test accounts. There is no person-level deduplication across the two eras.

## 8. Programme coverage

Headline figures cover one-to-one sessions across TEEI Language and TEEI Mentorship as a single number. Group sessions are measured but reported separately and never added.

A group session can be marked ended automatically without anyone attending, so its scheduled duration is not evidence. At the snapshot, ended clubs carried 12.78 scheduled hours and **zero** participants over the five-minute floor.

## 9. Known data limitations

| Limitation | Effect |
|---|---|
| 130 completed sessions have an explicit measured time of zero | No hours contributed, not backfilled. Conversation hours understated by at most 85.5 hours. |
| 1 profile of 9,889 lacks a valid country code | Excluded from country counts. Coverage is 99.99 percent, not 100. |
| Some live records carry an unresolvable residence field | Counted in totals, absent from the country breakdown. |
| Per-country figures below 5 shown as `<5` | Affects 110 of 148 countries. Totals unaffected. |
| Cross-era person-level deduplication is best effort | An individual active on both platforms may be counted in each. |

**A limitation we corrected.** An earlier version reported roughly 500 bookings lost to pagination drift. That was wrong: it was a parameter bug in our own extraction code, not data loss. The complete pull is 16312/16312 bookings, 0 failed pages and 863/863 bookings, 0 failed pages.

## 10. Validation and integrity checks

The dataset is rebuilt by a script that asserts 17 invariants and aborts rather than emit numbers that fail any of them. Every source file is recorded with size and SHA-256.

| ID | Check | Asserts |
|---|---|---|
| I1 | `no-negative-counts` | No country carries a negative member, volunteer or learner count. |
| I2 | `country-presence` | Every listed country has at least one member, volunteer or learner. Empty rows are not published. |
| I3 | `geometry-total-coverage` | Every country with data resolves to a map geometry. |
| I4 | `claimed-equals-rendered` | Nothing is counted that is not drawn, and nothing is drawn that is not counted. |
| I5 | `crimea-in-ukraine` | A point at 34.0E, 45.3N resolves to Ukraine, not Russia. The map cannot silently adopt a different border. |
| I6 | `live-record-conservation` | Records scanned equals records attributed plus records dropped. Nothing disappears unexplained. |
| I7 | `extract-map-consistency` | Country totals sum to the extract-s own count of profiles with a valid country. |
| I8 | `canon-floor-sessions` | Session count is at or above the published canonical floor. |
| I9 | `invalid-country-codes-empty` | No unrecognised country code survives into the dataset. |
| I10 | `totals-match-table` | Headline record counts equal the sum of the per-country table. |
| I11 | `bothInVideo-coverage` | At least 95 percent of completed historical sessions carry a measured two-sided time. |
| I12 | `origin-never-exceeds-records` | Origin-country attributions never exceed the records scanned, per source. |
| I13 | `residence-headline-frozen` | The published country counts are exactly 148 members, 127 volunteers, 65 learners. Drift aborts the build. |
| I14 | `live-learner-attribution` | At least 95 percent of live learner records resolve to a country. |
| I15 | `clubs-never-in-totals` | Group-session hours are never added to the headline totals. |
| I16 | `live-hours-are-measured-not-scheduled` | Measured hours and scheduled hours are provably different figures, so one cannot be published as the other. |
| I17 | `club-hours-have-no-attendance-evidence` | Excluded club hours carry zero participants over the attendance floor. If a club ever clears it, the exclusion is revisited rather than left hardcoded. |

## 11. Reporting period and update frequency

| Half | Period | Updates |
|---|---|---|
| Historical | 2022 to 2026-07-23 | Frozen; changes only with a documented rebuild |
| Live | 2026-07-23 onward | Continuous; public endpoint caches one hour |
| Country breakdown | snapshot 2026-07-23 | Rebuilt with the contract |

Live totals therefore exceed the snapshot figures. The method has not changed; the sessions have accumulated.

## 12. Dataset version and citation

| Field | Value |
|---|---|
| Dataset version | 2.3.0 |
| Snapshot | 2026-07-23 |
| Maintainer | Henrik (TEEI) / Documentation Team |
| Licence | CC BY 4.0 |
| Machine-readable | /data/, /api/impact-stats.json, this file |

How to cite:

    The Educational Equality Institute (2026). TEEI Impact Measurement Methodology, dataset version 2.3.0. https://theeducationalequalityinstitute.org/about/impact/methodology/

BibTeX:

```bibtex
@misc{teei_impact_methodology,
  author       = {{The Educational Equality Institute}},
  title        = {TEEI Impact Measurement Methodology},
  year         = {2026},
  version      = {2.3.0},
  howpublished = {\url{https://theeducationalequalityinstitute.org/about/impact/methodology/}},
  note         = {Historical half frozen at 2026-07-23; live figures at /api/impact-stats.json}
}
```

## 13. Relationship to our other published figures

| Other figure | Relationship |
|---|---|
| 9,337+ | Floor from dashboard-era snapshot; API ground truth is 11080 Kintell completed. Consistent. Canon EXCLUDES live-platform sessions (49). |
| 10,000+ | Broader measure, floor phrasing. Board shows it only as the canon line. |
| 8537.3 | Verified conversation time. STRICT SUBSET of canonical volunteerHours (canon also counts non-session volunteer activity). Never summed with canon. |
|  |  |

The most important: conversation hours are a **strict subset** of volunteer hours and are never summed with them.
