Technical documentation · dataset version 2.3.0
Impact Measurement Methodology
This page documents 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. It is written so the numbers can be reproduced and cited, not to persuade.
- Dataset version
- 2.3.0
- Historical half frozen
- 2026-07-23
- Live half
- continuous
- Maintainer
- Henrik (TEEI) / Documentation Team
- 1. What we measure
- 2. Data sources
- 3. Definition of a completed session
- 4. How attendance is verified
- 5. How hours are calculated
- 6. How participants and countries are counted
- 7. Duplicate and invalid-record handling
- 8. Programme coverage
- 9. Known data limitations
- 10. Validation and integrity checks
- 11. Reporting period and update frequency
- 12. Dataset version and citation
- 13. Relationship to our other published figures
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 defined below, and each is read from system records rather than reported by hand.
Two decisions determine what the headline numbers mean. Both were made deliberately and are recorded in the data contract rather than left implicit.
| Decision | What was chosen, and why |
|---|---|
| Hours | 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 | 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. Conversation hours count only time both people were demonstrably present, which is a smaller number than scheduled time and a much smaller number than registrations.
2. Data sources
The figures come from two systems, and the boundary between them matters because they are merged, never joined.
| Source | Period | What it provides |
|---|---|---|
| Third-party platform used until 2026 (Kintell) | 2022-04-22 to 2026-07-23 | 16,312 language bookings and 863 mentorship bookings, pulled in full from the platform's booking API. Frozen: this half does not change again. |
| 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. A person signing up produces no session, no hour and no attendance record. Country figures are the exception and are explicitly registration-based; section 6 says so.
The two halves are added, not joined. The historical records live in quarantined tables the live query is structurally forbidden from reading, which is what makes double counting impossible rather than merely unlikely.
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.
Two conditions must both hold. The booking status must have reached completed, and the attendance settlement written afterwards must independently agree, with shared presence above the floor. A booking marked complete by a person, with no measured attendance behind it, is not a session here.
4. How attendance is verified
Attendance is derived 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, sorts them, and computes the overlap: the time both people were in the room at the same time. Reconnections do not double count, and adjacent intervals that never overlap contribute nothing.
| Rule | Value |
|---|---|
| Presence floor | 5 minutes of shared presence. Below this the session does not count at all. |
| Crediting cap | measured time, capped at the booked window plus 30 minutes grace |
| Fallback cap | 4 hours, used 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, so no code path can forget it: a database constraint that refuses to store a completed settlement below it, a single shared query predicate every reader must use rather than restate, an object-level check on the same rule, and the same threshold in the group-session path. A session below the floor is therefore not filtered out at reporting time; it never becomes a completed session in the first place.
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.
Both eras therefore answer the same question: for how long were both people actually in the room together. Scheduled duration is kept as a separate, secondary figure and is never published as conversation time.
One consequence worth stating plainly: because time is floored and capped, and because sessions below the floor contribute zero, the published hours figure is a lower bound. It understates rather than overstates.
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 are counts of countries, not of people, and the basis is RESIDENCE (where the person is). Frozen from v2.0.0, unchanged by the v2.1.0 origin layer.. That means where a person is, not citizenship or affiliation. A Ukrainian in exile is recorded where she actually is.
| 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 volunteer and learner sets overlap heavily: 64 countries have both, so their union is 128, not 192. Both are strict subsets of the member set. The remaining 20 countries have registered members but no recorded session on either side, because member is a registration with a valid country while active requires having appeared in a booking. Never sum the two role figures.
7. Duplicate and invalid-record handling
Bookings that did not result in a verified session are excluded, not adjusted. For the historical language dataset the excluded statuses were:
| 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 |
On deduplication:
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 can carry at most one attendance settlement, enforced by a primary key, so a session cannot be counted twice. Database triggers additionally forbid a settlement whose outcome disagrees with its booking's status, and forbid rewriting a booking's status once a final settlement exists.
What is not excluded, stated openly: the live query applies no filter for staff, internal or test accounts. If a TEEI staff member takes a real session with a real participant and both are present for five minutes, it counts. There is also no person-level deduplication across the two eras; the same individual active on both platforms is counted in each.
8. Programme coverage
The headline figures cover one-to-one sessions across TEEI Language and TEEI Mentorship, counted as a single number. Group sessions are measured but reported separately and are never added to the totals.
The reason is not tidiness. A group session can be marked ended automatically without anyone having attended, so its scheduled duration is not evidence of anything. At the snapshot, ended clubs carried 12.78 scheduled hours, and zero participants had passed the five-minute floor; four had no enrolments at all. Publishing those hours would have invented impact.
9. Known data limitations
These are published because a figure whose weaknesses are hidden cannot be checked. Each was found by us and is recorded in the contract's exception ledger.
| Limitation | Effect on the figures |
|---|---|
| 130 completed sessions have an explicit measured time of zero | They contribute no hours and are not backfilled with scheduled duration. Conversation hours are understated by at most 85.5 hours. |
| 1 profile of 9,889 lacks a valid country code | Excluded from country counts. Country coverage is therefore 99.99 percent, not 100. |
| Some live-platform records carry a residence field that cannot be resolved to a country | Counted in totals, absent from the country breakdown. Most are placeable by country of origin, which is kept as a separate layer and never merged into the residence figures. |
| Per-country figures below 5 are shown as <5 | Affects 110 of 148 countries. Totals are unaffected; only the breakdown is masked. |
| Cross-era person-level deduplication is best effort | Member records may double count an individual who was active on both the old and the new platform. |
A limitation we corrected
An earlier version of this dataset reported roughly 500 bookings lost to pagination drift. That was wrong, and the correction is part of the record: 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. A second early claim, that the measured-time field was unset on hundreds of sessions, was also wrong: the field was never unset, and the sessions in question carry a measured zero.
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. Two consecutive builds have produced identical checksums. Every source file is recorded with its size and SHA-256.
| ID | Check | What it 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. |
Separately, the published country counts are frozen by assertion I13. If a rebuild produced different numbers, it would fail rather than quietly publish them.
11. Reporting period and update frequency
| Half | Period | Updates |
|---|---|---|
| Historical (third-party platform) | 2022 to 2026-07-23 | Frozen. Changes only with a documented contract rebuild. |
| Live (TEEI platform) | 2026-07-23 onward | Continuous. Public endpoint caches for one hour. |
| Country breakdown | snapshot 2026-07-23 | Rebuilt with the contract, not continuously. |
This is why the live totals below differ from the snapshot figures in the contract, and why both are shown. The method has not changed; the sessions have accumulated.
Current measured totals from /api/impact-stats.json
- Completed sessions
- —
- Conversation hours
- —
- Member countries
- —
Fetching. If this does not resolve, the endpoint is reachable directly at the URL above.
12. Dataset version and citation
| Field | Value |
|---|---|
| Dataset version | 2.3.0 |
| Snapshot (historical half) | 2026-07-23 |
| Maintainer | Henrik (TEEI) / Documentation Team |
| Licence | CC BY 4.0 |
| Machine-readable | /data/, /api/impact-stats.json, this page as markdown |
How to cite
The Educational Equality Institute (2026). TEEI Impact Measurement Methodology, dataset version 2.3.0. https://theeducationalequalityinstitute.org/about/impact/methodology/
@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
TEEI publishes other numbers elsewhere, and they are not interchangeable with these. The relationships are fixed and are stated here so the figures are not accidentally combined.
| 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. |
| retiredFigures |
The single most important one: conversation hours are a strict subset of volunteer hours. They measure time in video between two people; volunteer hours include preparation, coordination and everything else volunteers give. They are never summed.