Skip to content

fix(funnels): correct breakdown bar widths in top-to-bottom layout - #71816

Merged
sampennington merged 2 commits into
masterfrom
posthog-code/fix-funnel-horizontal-breakdown-widths
Jul 17, 2026
Merged

fix(funnels): correct breakdown bar widths in top-to-bottom layout#71816
sampennington merged 2 commits into
masterfrom
posthog-code/fix-funnel-horizontal-breakdown-widths

Conversation

@sampennington

Copy link
Copy Markdown
Contributor

Problem

In a funnel with optional steps and "conversion rate relative to previous step", the top-to-bottom (horizontal bars) layout rendered breakdown bar widths that contradicted the percentages printed under each step: a step with a ~5% conversion could render a full-width bar. The left-to-right layout of the same insight rendered correctly.

Why: the breakdown path in the top-to-bottom chart recomputed each segment's basis from the immediately preceding step's count. The precomputed conversion rates treat the last non-optional step as "previous", so an optional step that out-counts its immediate (optional) predecessor produced fractions above 100%, clamped to a full bar.

Changes

  • buildBreakdownSegments now distributes the step's precomputed aggregate rate (conversionRates.fromBasisStep) across breakdown variants by count, so the stacked bar total always equals the rate shown in the step footer — for any step reference, with or without optional steps.
  • Removed the now-unused stepReference build option (the precomputed rate already encodes it).

How did you test this code?

  • Added a regression test where an optional step out-counts its immediate predecessor with a breakdown: previously the recomputed fraction exceeded 100% and clamped to a full bar; the test asserts segments are sized from the precomputed aggregate rate and the stack always closes the 0–100 track. No existing test covered a breakdown step whose neighbor-derived basis diverges from fromBasisStep.
  • Removed two tests that existed only to exercise the deleted stepReference option.
  • Ran the full funnelBarHorizontalTransforms Jest suite (32 passed) and the frontend TypeScript check (remaining errors are pre-existing and unrelated).
  • Not able to verify visually in a running app in this environment.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Docs update

Not needed — rendering bug fix, no behavior/API/config change.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Diagnosed from two screenshots of the same funnel in both layouts: bar widths in the top-to-bottom view matched count-over-immediately-preceding-step while the footers matched count-over-last-non-optional-step, which pointed at buildBreakdownSegments recomputing the basis via getReferenceStep instead of using the precomputed conversionRates. Considered threading the optional-steps list into the transform, but deriving segment widths from the already-correct fromBasisStep is simpler and keeps the bar consistent with the footer by construction. Skills invoked: /writing-tests.


Created with PostHog Code

The top-to-bottom (horizontal bar) funnel recomputed breakdown segment widths from the neighboring step's count, ignoring optional steps. With "relative to previous step" set, the precomputed conversion rates treat the last non-optional step as previous, so an optional step that out-counts its immediate predecessor rendered a bar clamped to full width while the footer showed the correct (much smaller) percentage. Size breakdown stacks from the step's precomputed aggregate rate instead, so the bar always matches the footer.

Generated-By: PostHog Code
Task-Id: f8598b0d-a131-4a04-815b-d57d0f976912
@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

🤖 CI report

⚠️ Bundle size — 🔺 +37 B (+0.0%)

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 64.81 MiB · 🔺 +37 B (+0.0%)

No file changed by more than 1000 B.

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

Eager graph — within budget

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.22 MiB · 22 files no change ███░░░░░░░ 28.4% of 4.29 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
8.14 MiB · 2,987 files 🔺 +62 B (+0.0%) █████████░ 88.0% of 9.25 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4.5 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
3.9 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.4 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
789 B src/scenes/ChunkLoadErrorBoundary.tsx
762 B src/index.tsx
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
281.3 KiB ../node_modules/.pnpm/posthog-js@1.404.0/node_modules/posthog-js/dist/rrweb.js
267.7 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
235.5 KiB src/taxonomy/core-filter-definitions-by-group.json
223.2 KiB ../node_modules/.pnpm/posthog-js@1.404.0/node_modules/posthog-js/dist/module.js
164.0 KiB src/queries/validators.js
154.3 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
105.8 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
92.7 KiB ../packages/quill/packages/quill/dist/index.js

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

Dist folder size — 🔺 +5.2 KiB (+0.0%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 1327.31 MiB · 🔺 +5.2 KiB (+0.0%)

Generated-By: PostHog Code
Task-Id: f8598b0d-a131-4a04-815b-d57d0f976912
@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

🦔 Hogbox preview · ✅ ready

▶ Open the preview

🔑 Login test@posthog.com / 12345678 (demo data)
🧩 Running this PR's backend and frontend, on the PostHog :master base
🔗 Link stable across rebuilds — a re-push swaps the box underneath, the URL stays
🔒 Access tailnet only (PostHog VPN)
🛠️ Admin inspect & debug state in hogland
💤 Idle sleeps after ~30 min idle (snapshot to S3, zero node cost) and wakes on your next visit in ~30s, behind a brief "waking up" screen

commit 338d54c · box box-5ed3f3902ca9 · ready in 673s (push → usable) · build log · rebuilds on every push, torn down on close

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested a review from a team July 17, 2026 06:27
@greptile-apps

greptile-apps Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "chore(funnels): tighten comments in hori..." | Re-trigger Greptile

@sampennington sampennington left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 sp-ship · 💬 Suggestions only

Nothing blocks merge: the fix is arithmetically sound (distributing the precomputed rate by count share exactly reconstructs the footer percentage), the stepReference removal is complete, and the regression test verifiably fails against the old neighboring-step basis. Two small cleanups are suggested inline — reusing the existing funnelConversionRate guard and renaming a now-stale describe block.

@sampennington sampennington added the stamphog Request AI approval (no full review) label Jul 17, 2026 — with PostHog

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Contained frontend fix to funnel breakdown bar-width math with a solid regression test; author owns this area with strong familiarity, and the bot review's two suggestions are explicitly non-blocking follow-ups.

  • Author wrote 90% of the modified lines and has 12 merged PRs in these paths (familiarity STRONG).
  • 👍 on the PR from greptile-apps[bot], hex-security-app[bot].
Gate mechanics and policy version
Gate Result
prerequisites all clear
deny-list no deny categories matched
size 17L, 2F substantive, 79L/3F incl. docs/generated/snapshots — within ceiling
tier T1-agent / T1b-small (79L, 3F, single-area, fix)
stamphog 2.0.0b3 .stamphog/policy.yml @ a2e125e · reviewed head 338d54c

@trunk-io

trunk-io Bot commented Jul 17, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic BadgeStatic Badge

View Full Report ↗︎Docs

@sampennington
sampennington enabled auto-merge (squash) July 17, 2026 06:42
@sampennington
sampennington merged commit bcd95eb into master Jul 17, 2026
354 of 356 checks passed
@sampennington
sampennington deleted the posthog-code/fix-funnel-horizontal-breakdown-widths branch July 17, 2026 07:18
@deployment-status-posthog

deployment-status-posthog Bot commented Jul 17, 2026

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-07-17 07:43 UTC Run
prod-us ✅ Deployed 2026-07-17 07:57 UTC Run
prod-eu ✅ Deployed 2026-07-17 07:57 UTC Run

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

Labels

stamphog Request AI approval (no full review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant