feat(telemetry): instrument the three unmeasured steps of the PLG funnel - #6115
Merged
Conversation
The PLG funnel dashboard had three steps with no event behind them, so a missing bar was indistinguishable from a step nobody reached: - `task_board_opened` — a ref callback on the board root, not an effect (banned), guarded by a dataset flag so a re-invoked ref can't double-count. - `task_marked_done` — a PERSON moving a card to done. Deliberately not `task_run_completed`, which is the agent's run finishing. Fired in the `update` mutation, the single choke point every status change routes through, so drag-drop, the bulk bar and the task dialog are all covered by one call site instead of ten. - `task_limit_banner_shown` — the subscription paywall actually rendering, next to the existing server-side `task_quota_blocked` (which records the block, not whether anyone saw it). Carries the `kind` so the three refusal reasons stay distinguishable. All three carry `organization_id`, matching the other org-scoped events. No tests: these are telemetry call sites in React, which the two-tier policy in TESTING.md puts outside unit tests, and asserting a PostHog capture over the wire is not something the e2e suite is set up to observe.
viktormarinho
force-pushed
the
viktormarinho/plg-funnel-gaps
branch
from
August 14, 2026 19:08
bd181ec to
c2f5f1e
Compare
decocms Bot
pushed a commit
that referenced
this pull request
Aug 18, 2026
PR: #6115 feat(telemetry): instrument the three unmeasured steps of the PLG funnel Bump type: minor - decocms (apps/api/package.json): 4.222.0 -> 4.223.0 - @decocms/native (apps/native/package.json): 4.222.0 -> 4.223.0 Deploy-Scope: web
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The PLG funnel dashboard maps 17 steps to events. Three had no event at all, so on the board a missing bar and a step nobody reached looked identical:
task_run_completedis the agent's run finishing, not a persontask_quota_blockedrecords the server-side block, not whether anyone saw the paywallWhat
task_board_opened— ref callback on the board root, not an effect (banned byplugins/ban-use-effect.ts). Adatasetflag guards a re-invoked ref from double-counting, mirroringtrackGateRefinreports/auth-gate.tsx.task_marked_done— fired inside theupdatemutation inuseTaskBoardItemActions. That is the single choke point every status change routes through, so drag-drop, the bulk action bar and the task dialog are covered by one call site instead of ten scattered ones.task_limit_banner_shown— inonDelegateError, where the paywall dialog is actually opened. Carrieskindso the three refusal reasons stay distinguishable.All three carry
organization_id, consistent with the other org-scoped events.Follow-up (not in this PR)
The funnel still cannot be a native PostHog funnel end to end, because the Studio server events key on
organization_idwhile the engine events key ondomain. Two things surfaced while measuring this:$process_person_profile: falsesilently drops group attachment.captureOrgEventsets that flag when there is no user, and events sent that way arrive with$groupspopulated but$group_0empty — so anyunique_groupmath returns zero for them.task_run_enqueuedandtask_run_completedare affected;task_quota_claimedis affected only for its user-less half (67 of 84). Dashboard tiles were switched to countorganization_iddirectly as a workaround.COMMERCE_DISCOVERY_BINDtakessiteUrlper call and the mapping lives in the engine's database. Persisting it and havingcaptureOrgEventattachdomainwould let one native funnel span the whole flow — worth its own PR, since it needs a migration and touches the shared telemetry path.Verification
bun run fmt,bun run checkclean.bun run lint: 0 errors (18 pre-existing warnings, none in the touched files).No tests: these are telemetry call sites in React, which
TESTING.md's two-tier policy puts outside unit tests, and the e2e suite is not set up to observe a PostHog capture over the wire.Summary by cubic
Instruments three missing PLG funnel steps so funnel gaps are measurable. Previously these steps had no events; now we emit them without changing user flows.
task_board_opened: Fires once per mount via a root ref guarded by adatasetflag. Sendsorganization_id.task_marked_done: Fires in theupdatemutation only when a person sets status todone. Sendsorganization_idandtask_board_item_id. Not the agent’stask_run_completed.task_limit_banner_shown: Fires when the subscription paywall dialog opens. Sendsorganization_idand refusalkind.Written for commit c2f5f1e. Summary will update on new commits.