# Pulse Metrics — Product Requirements (v7.1)

Pulse Metrics is a product-analytics workspace. After connecting a project with its token, a product team builds conversion funnels, reads weekly retention cohorts, charts event counts with release annotations, watches a live event feed, opens user profiles, and keeps saved reports and cohorts. The demo project "Shopfront (production)" holds 3,200 users and 23,929 events from 2026-04-06 to 2026-09-30.

**Problem.** Product teams make release and growth decisions from these numbers, so funnel, retention and count figures must be exact for the chosen steps, window, filters and dates, and must let a team find a regression such as a checkout drop on one platform.

## Users
- **Product manager** — Build a funnel, compare platforms and date ranges, and save the analysis as a report.
- **Growth analyst** — Read retention by cohort and segment events by interval and property.
- **Support engineer** — Follow a live event to the user behind it and read that user’s timeline.

## Goals
- Funnel and retention numbers are exact for every combination of steps, window, breakdown and filters.
- A team can trace a conversion drop to a platform and a release date.
- Saved reports reopen with the same parameters and numbers.

## Connecting a project (CON)

Project-token gate and disconnect.

- **FR-CON-01** (Must) Entering the project token and choosing "Connect" opens the workspace on Funnels with the project name and totals in the header.
  - Before connecting: heading "Connect a project", field "Project token", "Connect" disabled while the field is empty
  - Sidebar: Funnels, Retention, Insights, Live view, Reports; header "Shopfront (production)" with "3,200 users · 23,929 events"
  - Tab title "Funnels · Pulse Metrics"
- **FR-CON-02** (Must) A wrong token never opens the workspace; surrounding spaces in a correct token are ignored.
  - Error "That project token was rejected." and the connect screen stays
  - A correct token with leading and trailing spaces connects
  - The analytics API refuses a wrong key with 401 "unauthorized"
- **FR-CON-03** (Could) "Disconnect" returns to the empty connect screen.
  - Heading "Connect a project" and an empty token field

## Funnels (FUN)

Step builder, window, breakdown, dates and the resulting numbers.

- **FR-FUN-01** (Must) The default funnel counts users who did step 1 in the date range and completed each next step within the window of step 1.
  - Defaults: Sign up, View product, Add to cart, Start checkout, Purchase; 2026-08-02 to 2026-09-30; window 7 days; Breakdown None
  - "All users": Sign up 1,340; View product 1,062 (79.3% overall); Add to cart 552 (41.2% overall · 52.0% step); Start checkout 386 (28.8% · 69.9% step); Purchase 205 (15.3% · 53.1% step)
  - Stat card "All users" 15.3% "205 of 1,340 converted"
  - Caption "Users who did step 1 between 2026-08-02 and 2026-09-30, completing each next step within 7 day(s) of step 1."
- **FR-FUN-02** (Must) The conversion window changes the result: a shorter window converts fewer users and a longer one more, and the caption names the window used.
  - 1 day: View product 739 (55.1%), Purchase 16 (1.2%), caption "within 1 day(s)"
  - 30 days: View product 1,151 (85.9%), Purchase 206 (15.4%), caption "within 30 day(s)"
  - The service clamps a window above 30 to 30
- **FR-FUN-03** (Should) A breakdown splits the funnel by platform, plan or country, with one row and one overall figure per value.
  - Platform: Android 7.7% (35 of 455); iOS 19.1% (99 of 519); Web 19.4% (71 of 366); Purchase step Android 25.9%, iOS 67.8%, Web 67.6%
  - Plan: Free 14.4% (157 of 1,088); Pro 19.1% (48 of 252)
  - The service accepts breakdown platform, country or plan and otherwise answers 422 "breakdown must be one of platform, country, plan"
- **FR-FUN-04** (Must) Changing the date range allows the Android checkout drop to be tied to the release of 2026-08-17.
  - 2026-06-01 to 2026-08-16 by platform: Android Purchase step 69.3% (106 users), iOS 67.8%, Web 59.4%
  - 2026-08-17 to 2026-09-30: Android Purchase step 16.0% (17 of 106 who started checkout), iOS 68.3%, Web 72.6%
  - Insights lists the annotation 2026-08-17 "Release 3.8.0 (new checkout)"
- **FR-FUN-05** (Should) Steps can be removed, reordered with arrow buttons, and added, within 2 to 8 steps; order matters for the result.
  - Removing down to two steps disables every remove button; Sign up to Purchase: 1,340 to 205 (15.3%)
  - "Move step 2 up" gives Purchase then Sign up: Purchase 213 to Sign up 2 (0.9%); first "up" and last "down" are disabled
  - "+ Add step" three times gives 8 steps, then it is disabled; new steps default to "Sign up"
  - The service refuses one step: 422 "A funnel needs at least 2 steps" and an unknown name: 422 "Unknown event \"Signup\""
- **FR-FUN-06** (Could) Steps can also be reordered by dragging a step onto another; the results table follows the new order.
  - Dragging Purchase onto Sign up gives Purchase, Sign up, View product, Add to cart, Start checkout; the table header starts "1. Purchase"
- **FR-FUN-07** (Could) The date inputs are bounded by the dataset.
  - From is not before 2026-04-06 and not after To; To is not after 2026-09-30 and not before From

## Retention (RET)

Weekly cohorts and filters.

- **FR-RET-01** (Must) Retention shows weekly cohorts with every cohort at 100.0% in week 0, followed by the share still active each later week; weeks not yet reached stay empty.
  - Defaults: cohorts from 2026-06-01, Platform All, Plan All, Weeks 8; columns W0 to W8; 18 cohort rows
  - Average row: Users 2,482; W0 100.0%, W1 47.8%, W2 43.3%, W4 36.7%, W8 24.1%
  - Cohort 2026-06-01: 124 users, W0 100.0%, W1 52.4%, W8 28.2%
  - Cohort 2026-09-28: 81 users, W0 100.0%, W1 to W8 empty with the hover "Not reached yet"
- **FR-RET-02** (Should) Platform and plan filters combine and apply to every cohort.
  - Android and Pro: cohort 2026-06-01 has 9 users; W1 66.7%; W3 33.3%; W8 22.2%
- **FR-RET-03** (Could) The Weeks selector sets the number of columns.
  - Weeks 4 gives W0 to W4; Weeks 12 gives W0 to W12

## Insights (INS)

Event counts over time with annotations.

- **FR-INS-01** (Must) The default insight counts Purchase events by platform per week for the last 90 days and marks annotations on the axis.
  - Defaults: Event Purchase, Measure Total events, Breakdown platform, Interval Week, Range Last 90 days, chart Line
  - Legend totals: Android 87, iOS 152, Web 108
  - 14 weekly buckets from 2026-06-29 to 2026-09-28; a red dashed line marks the 2026-08-17 bucket
- **FR-INS-02** (Should) Unique users counts each user once; when no user purchased twice it equals the total events.
  - Breakdown None, Unique users and Total events both read "Purchase 347" (87 + 152 + 108)
- **FR-INS-03** (Should) The month interval aggregates the whole range.
  - Last 6 months by month: 2026-04 to 2026-09 with 42, 87, 108, 136, 108, 108; legend "Purchase 589"
  - Daily Sign up for 2026-09-01 to 2026-09-30 gives 30 buckets and a total of 682 (service)
  - Unknown event: 422 "Unknown event \"Nope\""
- **FR-INS-04** (Could) Legend items toggle a series on and off.
  - Clicking "Android" greys it (aria-pressed false) and hides its line; clicking again shows it, also in Stacked bar
- **FR-INS-05** (Should) Annotations are listed in date order and can be added and deleted.
  - Seed: 2026-06-01 "Summer campaign start", then 2026-08-17 "Release 3.8.0 (new checkout)"
  - Adding 2026-09-01 "Pricing page redesign" lists three items, the new one last; delete returns to two

## Live view and users (LIV)

Event feed and user profiles.

- **FR-LIV-01** (Should) The live view lists the newest events, can be filtered by event and can be paused.
  - "23,929 matching events · refreshing every 5s"; first row "Invite teammate" Android · BR 2026-09-30
  - Event Purchase: "589 matching events" and every row is Purchase
  - "❚❚ Pause" becomes "▶ Resume" and the pulse dot is hidden
- **FR-LIV-02** (Could) Expanding an event shows its properties and links to the user profile.
  - First row: distinct_id U-03187, $os Android, mp_country_code BR, plan Free
  - Clicking "U-03187" opens /users/U-03187, tab title "User profile · Pulse Metrics"
- **FR-LIV-03** (Could) A user profile shows properties and a timeline; an unknown user shows a clear error.
  - U-00042: Signed up 2026-09-20; Platform Android; Country IN; Plan Free; Funnel depth 2 / 5; Active weeks 1; Events 3; timeline starts 2026-09-20 with "Sign up"
  - "Find user" with "U-99999": "No user with distinct_id “U-99999”."; the service answers 404 "No user U-99999"

## Reports and cohorts (REP)

Saved analyses and named cohorts.

- **FR-REP-01** (Must) A funnel can be saved as a report, listed under Reports with its type and id, and reopened with the same parameters and numbers.
  - Platform breakdown, window 14 days: status "Saved as RPT-0003"
  - Listed "Funnel: Sign up → Purchase by platform" with badge "funnel"
  - Opening it restores Breakdown platform and window 14 days with Android, iOS and Web rows
  - Seed RPT-0001 "Checkout funnel by platform" opens /funnels?report=RPT-0001 with window 7 days and Android 7.7%, iOS 19.1%, Web 19.4%
- **FR-REP-02** (Should) Reports can be searched, filtered by type, renamed and deleted.
  - Seed list sorted by name: "Checkout funnel by platform" (RPT-0001), "Weekly retention — all users" (RPT-0002)
  - Search "weekly" shows only RPT-0002; rename to "Android checkout" re-sorts it first; delete leaves RPT-0002
  - Type filter Insight with none shows "No reports match."
- **FR-REP-03** (Should) Cohorts are created from one or more rules with a required name.
  - Seed: "Android Pro" — "platform = Android AND plan = Pro"
  - Empty name: "Cohort name is required"
  - Rules country is JP and plan is Pro named "Pro users in Japan" lists "country = JP AND plan = Pro" and resets the form
- **FR-REP-04** (Could) A report must be of type funnel, retention or insight; any other type is rejected.
  - Missing name: 422 with missing ["name"]
  - Type "zzz": 422, type must be funnel, retention or insight, and nothing is stored

## Glossary and rules

- **Conversion window** — The number of days after step 1 within which each later step must happen to count.
- **Cohort** — A group of users who first appeared in the same week (retention) or share property rules (saved cohort).
- **Annotation** — A dated note, such as a release, drawn on insight charts.

## Out of scope

- Chart pixel rendering beyond legend and axes
- Real-time ingestion (the dataset is fixed)
