Add opt-in PostHog analytics with a fixed privacy boundary - #168
Conversation
📊 Coverage Report
|
🧪 E2E Test Results✅ 38 passed, 0 failed, 0 skipped
|
cb-jeeves
left a comment
There was a problem hiding this comment.
Adds an opt-in, fixed-payload PostHog ping from the main process with consent stored per installation. The boundary itself is tight and well tested; the one thing I would fix before merge is the published docs page, which still promises no analytics at all.
Minor: the docstring on Application.tsx still lists the panel's controls without the new analytics row.
… the docs privacy page The docs site still claimed no analytics of any kind. Scope the local-only bullet to clipboard data and describe the opt-in usage ping in the same terms as the README, linking to the analytics README. The settings row now uses the shared RowStatus slot instead of a generic alert. A failed opt-out re-reads the stored preference so the switch shows what is on disk, and the error message says reporting is paused now but may resume next launch. The initial read failure keeps its own message. Name the preference payload AnalyticsPreference in shared/types and use it in preload, the main client and the settings component. Add the analytics row to the Application panel docstring.
|
Responded to review round 1, pushed 269f05b:
|
cb-jeeves
left a comment
There was a problem hiding this comment.
Since last round: the docs privacy page now matches the README, the preference payload is a shared AnalyticsPreference type, and the settings row reports through the shared status slot. That closes all three earlier threads. One blocking issue remains in the new failed-opt-out path, plus one minor lifecycle gap in the same component.
…t and clear the saved label A failed opt-out re-read the preference from the main process, which had already dropped the ID in memory, so the switch flipped off while the consent file still said on. Keep the previous renderer value instead, which matches the file in both failure cases. Clear the saved label after SAVED_LABEL_MS like every other row in the panel.
|
Responded to review round 2, pushed d02bc14:
|
cb-jeeves
left a comment
There was a problem hiding this comment.
Since last round: the failed-opt-out path no longer re-reads the preference, so the switch stays on for the current mount, and the saved label now clears after the shared delay. That closes both round-two threads. One follow-on remains in the main-process side of the same failed-opt-out case; it is the last thing I would change before merge.
setEnabled clears the sending ID before writing so a failed opt-out never keeps sending, but preference() derived the reported flag from that ID. After a failed rename the file still said enabled while the settings switch showed off on every remount, with no way to retry. Track the persisted consent separately: it is set on load and only flipped after the rename succeeds, and preference() reports it. Add a client test for the failed-write case and remount the settings component in the renderer test.
|
Responded to review round 3, pushed c052e79:
|
cb-jeeves
left a comment
There was a problem hiding this comment.
Since last round: preference() reports the on-disk consent through a separate persisted flag, so a failed opt-out keeps the switch on across remounts while the cleared sending ID keeps the process quiet, which closes the last open thread.
cb-jeeves
left a comment
There was a problem hiding this comment.
Since last round: the analytics row moved out of Application into its own Privacy panel under Window, the docs and README point at the new location, and the unit and E2E panel counts and viewport assertions cover it. Nothing in the privacy boundary changed. One minor layout suggestion below; the PR is otherwise ready.
Analytics was the only settings panel framed by General.tsx. Rename it to Privacy, move the Panel wrapper into the component, and drop the Panel import from General so it is a list of self-contained panels again.
|
Responded to review round 5, pushed e75267c:
|
Summary
Clipless now asks once in the main window whether to send optional metrics to improve the app. Reporting stays off until the user explicitly chooses Send analytics. No thanks and Escape decline, and either saved choice prevents future prompts. Existing consent is respected.
Added
Changed
Validation
Operational notes
Live ingestion has not been verified. Set the PostHog project to discard client IP data; direct connections still expose network IPs. Counts represent opted-in installations, not exact people or all users. Chart feature_used by feature with unique users for adoption and total events for frequency. Low adoption alone does not explain why a feature is unused. Previously received events are not deleted by opting out.