Skip to content

[Epic] Usage & growth metrics: know how many people download, install, and keep using Pull Read #111

Description

@shellen

Why

We can answer "how many people signed up to download?" (the D1 subscribers table behind the download gate) but not "how many kept using it?" — and several counters we do have are leaky or ephemeral. Current state, verified 2026-07-18:

  • Download gate works: every pullread.com download click records email + platform in D1 (source = 'download').
  • Update check-ins are the only usage signal: latest.json download counts per tagged release ≈ installs checking daily (v0.4.10: 19 over ~4 days ≈ 4–5 daily actives).
  • Blind spots: direct GitHub downloads (README, releases page) bypass the gate; the rolling latest DMG counter resets on every push to main; GitHub traffic stats only cover a rolling 14 days; nothing correlates signups to retained installs.

Plan

Phase 1 — capture what already exists (no app changes)

  • Weekly metrics snapshot workflow: scheduled Action (like check-models.yml) that appends to data/metrics.csv: per-release asset download counts (latest.json, DMGs, .app.tar.gz), rolling latest counts (rescued before the next reset), repo traffic views/clones, and D1 subscriber counts by source/platform (via a small authenticated worker endpoint, see below).
  • Worker /api/stats endpoint: ADMIN_KEY-protected JSON counts (total/active subscribers, by source, by platform, by week) so the snapshot workflow and a curious human can pull numbers without exporting the full CSV of emails.
  • Close the direct-download blind spot where we control the links: point README and docs download links at pullread.com (gated) instead of raw GitHub asset URLs.

Phase 2 — active-install signal (ships with a client release, e.g. 0.5.1)

  • Worker-proxied updater endpoint: serve latest.json from pullread.com via the worker (302 or proxy to the GitHub asset), counting one row per check-in day with a salted IP hash for uniques — no PII beyond what a web server sees. Add it as the FIRST entry in tauri.conf.json updater endpoints, keeping the GitHub URL second as fallback so a worker outage never blocks updates.
  • Daily/weekly actives view: extend /api/stats with check-in counts so retention ≈ check-ins vs. gate signups is one query.

Phase 3 — decide on opt-in telemetry (separate decision, not started by default)

  • Evaluate an opt-in anonymous ping from the app (version + platform, weekly) with a Settings toggle and FAQ entry. Strongest signal; needs a deliberate privacy posture consistent with the AI-disclosure ethos. File as its own issue if we go ahead.

Non-goals

  • No third-party analytics SDKs in the app.
  • No tracking pixels in the Rundown email (it goes through the user's own SMTP; their reading habits are their business).

Success criteria

A monthly glance at one CSV (or /api/stats) answers: downloads this month, split by platform; active installs checking for updates; rough retention of gated signups.

Filed by Claude Code on behalf of @shellen; context in the 0.5.0 release session.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions