Skip to content

PostHog: replace the default dashboards with three tiles that answer this site's question #75

Description

@robbyrob42

PostHog is collecting the right events and displaying the wrong things. The project is still showing the default dashboards, which are SaaS product templates — activation, retention, stickiness, feature adoption. Those assume returning users with accounts. This site has neither, and the analytics client is deliberately configured so that it never will: persistence: 'sessionStorage' means identity is scoped to a single tab visit. Every retention and stickiness tile in the project is therefore structurally empty rather than merely low, and reading them as performance is a mistake waiting to be made.

This issue replaces them with three tiles that answer the question the site is actually built around.

Before building anything: the data floor

Filter every insight to on or after 2026-08-26, 18:15 PDT. Before that timestamp the client used persistence: 'memory', which issued a fresh identity on every page load. The result was six visitors, six pageviews, six sessions, a 100% bounce rate, and a two-step pageview funnel that dropped 100% at step two — none of which was behavior. Internal navigation was also being recorded as external referral traffic for the same reason. That data is unusable and should not be included in any tile.

The event set

Autocapture is off, so the declared set in sites/forensics/src/lib/analytics.ts is the complete set. There is nothing else to build from:

Event Properties
$pageview standard
expand_clicked from, to, section
criterion_link_clicked to
rates_viewed path
scope_started path
scope_submitted path

Tile 1 — rates_viewed against sessions

Trend: unique sessions firing rates_viewed, over total sessions, as a rate.

This is the disqualification marker and the reason the event exists. The site is built to rule people out: a partner who reads the published rates and leaves has been served correctly. A bounce rate cannot distinguish that reader from one who never engaged, and those two mean opposite things. rates_viewed fires on a 50% intersection threshold and once per page load, so it means the rate card was genuinely on screen rather than clipped past.

The diagnostic reading matters as much as the number. A low share is not a pricing signal — it means /engagements is not being reached, which is an information-architecture problem. Only once the share is healthy does the exit-after-viewing rate say anything about the rates themselves.

Tile 2 — expand_clicked broken down by section

Bar chart, expand_clicked count with a breakdown on the section property.

section names the screening criterion the reader was in when they chose to go deeper, which makes this a copy input rather than a vanity metric. Sections with near-zero expansion are ambiguous in a useful way: either the summary already satisfied the reader, or the section is invisible on the page. Pair it with Tile 1's path data before concluding which.

Worth adding criterion_link_clicked as a secondary series on the same tile — it covers the testimony-record link out of the screening index, which is the highest-intent click on the root page that is not the intake form.

Tile 3 — scope_startedscope_submitted funnel

Two-step funnel, session-scoped, over the same date floor.

This measures the intake form's own friction and nothing else. scope_submitted is a signal, not a record — the submission itself lands in D1, which stays the source of truth for what was actually sent and for anything about lead quality. The gap between the two steps is the number to watch; a wide one is a form problem, and the form is currently long.

Non-goals, stated so they do not get built

Bounce rate, session duration, retention, and stickiness. All four are either meaningless here or actively misleading given the disqualification model and the sessionStorage identity scope. If a tile of this kind appears on the dashboard, it is a default that was not removed.

Session replay stays off, permanently

/scope carries a 5,000-character textarea in which an attorney describes a live matter, written before any conflict check has run. Recording that keystroke by keystroke into a third-party system is not a risk this practice can carry. The client sets disable_session_recording: true, which is authoritative for this site, but the project-level recording toggle should also be confirmed off so that a second property added to this project later does not start recording by inheritance.

Settings audit, folded in here

An earlier session noted features enabled in the PostHog project that nobody had turned on deliberately. That was flagged and never chased. As part of this work, walk the project settings and record what is enabled and why — replay, autocapture, heatmaps, web analytics, surveys, exception capture, and any beta features. Anything that cannot be justified against the constraints above gets turned off.

Acceptance

  • One dashboard, three insights, no default tiles left on it.
  • The 2026-08-26 18:15 PDT floor applied and visible on each insight.
  • Project-level session replay confirmed off.
  • A written note of what the settings audit found.

Open

Whether this dashboard is pinned and shared, or kept private. It carries no client data, but it does carry the conversion shape of the practice.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions