Add PostHog events for group chat actions - #781
Conversation
|
`_send` returned on `!mounted` before folding the result, so a message the server accepted while the member was leaving lost both `message_sent` and the first-send `group_chat_joined`. Both are now recorded straight after the request resolves, before any lifecycle check, matching how the thread notifier already handles reactions and deletions. `_trackJoined` lets the first-send source through after dispose for the same reason. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
4a0606f to
558bf33
Compare
- Rename group_chat_joined to group_chat_opened: it fires on every visit to a chat that has a room, not once per member. - Label reaction events from the flags that chose the request. - Move the report request and the once-per-screen open rule out of the widgets so they can be tested. - Test the open rule, the report event, and the selection header picking up Delete once the profile loads.
| static const String malaMantraSwitched = 'mala_mantra_switched'; | ||
|
|
||
| // Group chat | ||
| static const String groupChatOpened = 'group_chat_opened'; |
There was a problem hiding this comment.
The tracking contract requires group_chat_joined, but this constant emits group_chat_opened. The analytics service forwards this value directly to PostHog, so dashboards and funnels querying the specified event will receive no join data. Please use the roadmap event name or coordinate a tracking-plan migration.
| static const String groupChatOpened = 'group_chat_opened'; | |
| static const String groupChatOpened = 'group_chat_joined'; |
Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/core/analytics/analytics_events.dart
Line: 26
Comment:
**Event name breaks contract**
The tracking contract requires `group_chat_joined`, but this constant emits `group_chat_opened`. The analytics service forwards this value directly to PostHog, so dashboards and funnels querying the specified event will receive no join data. Please use the roadmap event name or coordinate a tracking-plan migration.
```suggestion
static const String groupChatOpened = 'group_chat_joined';
```
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
Understood — group_chat_opened is intentional and matches the updated tracking contract described in this PR. I’ll withdraw this comment.
Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.
What
Instruments group chat with the six PostHog events from the chat roadmap (Task 6):
group_chat_openedgroup_id,room_id,source(resolved/firstSend/live)group_message_sentgroup_id,room_id,message_id,is_replygroup_message_repliedsent)group_id,room_id,message_id,parent_message_idgroup_message_deletedroom_id,message_idgroup_message_reactedroom_id,message_id,emoji,action(added/removed/swapped, taken from the request that was sent)group_message_reportedroom_id,message_id,reason(wire value)How
AnalyticsEvents/AnalyticsProperties.GroupChatAnalyticshelper (presentation/utils/chat_analytics.dart) owns the payloads and is exposed throughgroupChatAnalyticsProvider. Calls are fire-and-forget; a capture that throws is logged, never surfaced.GroupChatThreadNotifier, sends and opens fromGroupChatScreen, reports fromChatReportRequest.ChatReportRequest(presentation/utils/chat_report_request.dart, moved out of the thread widget) andChatOpenTracker(the once-per-screen rule, inchat_analytics.dart) sit outside the widgets so they can be unit tested.Decisions worth a look
group_chat_openedfires once per screen open. It counts visits, not members: every visit to a chat that has a room fires it again, and a chat with no room fires nothing until one exists. (Renamed fromgroup_chat_joined, which read like a count of new members.)sourcesays whether the room was found on open, created by this member's first send, or reported over the socket.group_message_reported, because the data layer folds the server's 409 into success.Also in this PR
/users/infowas still loading had no viewer to compare senders against, so Delete and Report stayed off until the next tap. The thread now republishes the selection when the viewer's id or email changes.Push notifications
The card also lists FCM registration and tap deep-linking into
/groups/:id/chat. Both were already onfeat/chatUIupdate(firebase_messagingdependency,PushNotificationService,PushMessageNavigatorwith theCHAT/GROUPcase) and are unchanged here.Tests
chat_analytics_test.dartcovers each helper payload, the reply double-fire, the swallowed capture error, andChatOpenTracker(once per screen, again on a new screen, nothing after dispose except a first send).analyticsgroup ingroup_chat_thread_providers_test.dartcovers confirmed-only firing for reactions and deletes, including swap, failure, bulk, refusal and fallback cases.chat_report_request_test.dart: an accepted report firesgroup_message_reported; a refused or failed one fires nothing; a successful retry fires once.group_chat_thread_selection_test.dart: a selection made before the profile loads gets Delete once it lands (fails without the listener).RecordingAnalyticsServicefake undertest/core/analytics/.flutter analyze --no-pubclean on the touched paths.flutter test test/features/group_chat test/core/analytics: 376 pass, 1 fails —prayer_requests_providers_test.dartdoes not compile because its fake repository is missingdeleteMessages. That is pre-existing and not touched here.Not verified end to end: no local
.envcarries a PostHog key, so events were not observed landing in a PostHog project. The ordering that keeps a first send's socket echo from being counted asliveis not covered by a test.