User Statistics

manage.py user_stats prints aggregate statistics about user accounts for a date range as JSON: signups, activation, logins, newsletter consent, profile completeness and API/MCP adoption. It only reads, and it outputs counts, not usernames, email addresses or ids.

python manage.py user_stats                                   # last 30 days
python manage.py user_stats --since 2026-09-01 --until 2026-09-30
python manage.py user_stats --days 7 --free-text              # plus profile texts

Definitions

Staff and superusers are left out of every number.

Metric

Definition

Signup

date_joined is in the range.

Activated

The user has a verified email address (allauth EmailAddress.verified). Social signups arrive verified.

Funnel

Of the range’s signups: verified → ever logged in → created an API token → used an API token → connected an MCP client (OAuth grant or token).

Login

last_login is in the range. OLDP keeps no login history, so this is a lower bound: a user who also logged in after the range is not counted. Returning users joined before the range.

Newsletter subscriber

Opted in and confirmed the double opt-in (UserProfile.is_newsletter_subscriber).

Complete profile

Role and use case are set (UserProfile.is_profile_complete).

Email category

academic, freemail or other, from the email domain (see Settings).

Every range-scoped block is computed for the range (current) and for the equally long range right before it (previous), so trends can be read off directly. totals is the all-time state at the time of the run.

Settings

Variable name

Default value

Comment

DJANGO_USER_STATS_FREEMAIL_DOMAINS

gmail.com,web.de,gmx.de,…

Comma-separated domains counted as freemail.

DJANGO_USER_STATS_ACADEMIC_DOMAIN_LABELS

edu,ac

A domain with one of these labels is academic: mit.edu, ox.ac.uk.

DJANGO_USER_STATS_ACADEMIC_DOMAIN_PREFIXES

uni-,tu-,fh-,hs-,th-,hu-,fu-

A domain with a label starting with one of these is academic: uni-koeln.de, stud.tu-berlin.de.

DJANGO_USER_STATS_TOP_N

15

Length of the top lists (signups by country).

DJANGO_USER_STATS_FREE_TEXT_MAX_CHARS

1000

--free-text cuts longer use cases to this length.

Caveats

  • purge_unverified_users deletes never-verified signups after a grace period. Older ranges therefore show fewer signups and a higher activation ratio than they had at the time; compare ranges of the same age.

  • OAuth tokens expire and may be cleared, so the MCP numbers are a lower bound.

Free text

--free-text adds a free_text list with the display name, organization and use case of every user who signed up in the range, or completed their profile in it. Each row carries only the role, country and email category besides the text; joined_in_range tells the two groups apart. Use cases are cut at 1,000 characters.