Skip to content

Timer reach metric: attach audience_size to timer_started events #107

Open

Description

@ShuhaoZQGG

Goal

Measure timer reach — how many meeting participants the timer serves — instead of only counting operator starts. A class with 20 people where the teacher starts the timer 15 times currently looks identical to 15 solo web starts.

Proposed client change

In apps/zoom-app/src/components/LiveTab.jsx, attach the meeting headcount to the timer_started event:

  1. Import the existing hook: import useZoomParticipants from '../hooks/useZoomParticipants';
  2. Call it alongside the other hooks: const { participants: meetingParticipants, restricted: participantsRestricted } = useZoomParticipants();
  3. Add to the timer_started properties:
...(!participantsRestricted && meetingParticipants.length > 0
  ? { audience_size: meetingParticipants.length }
  : {}),

Full diff is in ~/workspace/goals/hone-my-tech-products-and-services/files/timer-reach-audience-size.patch (Jarvis workspace).

Privacy

Count only — participant names never leave the device. The property is omitted (not zeroed) when:

  • the web version (no Zoom SDK), or
  • the participant list is withheld (non-host/co-host), where the list may contain only self.

Analytics treats missing as reach of 1 (the operator), which is a defensible lower bound.

Analytics side (already done)

  • Daily/weekly traffic report (traffic_report.py): new "Timer reach" line = sum of per-meeting max audience_size per day (grouped by zoom_meeting_id, falling back to distinct_id; 15 starts in one class count once). Shows n/a until the client ships.
  • PostHog dashboard "Toastmusters Traffic" + saved insight "Timer reach (daily)".

No backfill possible — data starts when the instrumented build deploys.

Acceptance

  • Host/co-host starts timer in a meeting → timer_started carries audience_size = full participant count
  • Non-host starts timer → property absent
  • Web timer start → property absent
  • PostHog "Timer reach (daily)" insight starts showing reach > starts once deployed

Activity

  1. ShuhaoZQGG commented on Nov 11, 2026

    @ShuhaoZQGG
    ContributorAuthor

    Notes for the plan:

    • Count at START, not at mount. useZoomParticipants() fetches the participant list once, when the component mounts, and never refreshes it. LiveTab mounts when the app opens, so a count taken from the hook misses everyone who joined later, and audience_size comes out too low. Instead, call getZoomParticipants() (apps/zoom-app/src/utils/zoomSdk.js) inside the idle callback that sends timer_started. Leave the property out when restricted is true or the list is empty. This also avoids a third mount-time fetch alongside SpeakerInput and StageSpeakerPicker.
    • The patch in the Jarvis workspace isn't in this repo. The change described in this issue, adjusted as above, is the spec.
    • AC-4, the PostHog "Timer reach (daily)" insight, can only be checked after a production release.
    • The non-host case needs a second Zoom account that isn't host or co-host, so it's a human step in the Zoom run.
  2. removed
    factory:readyFactory: promoted; the plan station picks it up
    on Nov 11, 2026
  3. added 4 commits that reference this issue on Nov 11, 2026
  4. added 2 commits that reference this issue on Nov 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions