Skip to content

Add PostHog events for group chat actions - #781

Merged
tentamdin merged 4 commits into
developfrom
feat/chatAnalytics
Sep 17, 2026
Merged

tentamdin merged 4 commits into
developfrom
feat/chatAnalytics

Conversation

@harshal-2304

@harshal-2304 harshal-2304 commented Sep 16, 2026

Copy link
Copy Markdown
Member

What

Instruments group chat with the six PostHog events from the chat roadmap (Task 6):

Event Fired when Properties
group_chat_opened the chat screen first has a room to talk in (once per visit) group_id, room_id, source (resolved / firstSend / live)
group_message_sent the server accepts a message group_id, room_id, message_id, is_reply
group_message_replied the accepted message is a reply (fires alongside sent) group_id, room_id, message_id, parent_message_id
group_message_deleted a delete is confirmed, one event per message room_id, message_id
group_message_reacted a reaction call is confirmed room_id, message_id, emoji, action (added / removed / swapped, taken from the request that was sent)
group_message_reported the server accepts a report room_id, message_id, reason (wire value)

How

  • Event names and property keys are added to AnalyticsEvents / AnalyticsProperties.
  • A small GroupChatAnalytics helper (presentation/utils/chat_analytics.dart) owns the payloads and is exposed through groupChatAnalyticsProvider. Calls are fire-and-forget; a capture that throws is logged, never surfaced.
  • Reactions and deletes fire from GroupChatThreadNotifier, sends and opens from GroupChatScreen, reports from ChatReportRequest.
  • ChatReportRequest (presentation/utils/chat_report_request.dart, moved out of the thread widget) and ChatOpenTracker (the once-per-screen rule, in chat_analytics.dart) sit outside the widgets so they can be unit tested.

Decisions worth a look

  • Every event fires after server confirmation, never optimistically. A failed reaction, delete, send or report fires nothing.
  • A swap fires once, for the new emoji, not again for the cleanup DELETE of the old one.
  • Bulk delete fires one event per message, so the bulk route and the one-call-each fallback report identically.
  • group_chat_opened fires 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 from group_chat_joined, which read like a count of new members.) source says whether the room was found on open, created by this member's first send, or reported over the socket.
  • A repeat report still fires group_message_reported, because the data layer folds the server's 409 into success.

Also in this PR

  • Selection header picks up Delete/Report once the profile loads. A selection made while /users/info was 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 on feat/chatUIupdate (firebase_messaging dependency, PushNotificationService, PushMessageNavigator with the CHAT / GROUP case) and are unchanged here.

Tests

  • chat_analytics_test.dart covers each helper payload, the reply double-fire, the swallowed capture error, and ChatOpenTracker (once per screen, again on a new screen, nothing after dispose except a first send).
  • New analytics group in group_chat_thread_providers_test.dart covers confirmed-only firing for reactions and deletes, including swap, failure, bulk, refusal and fallback cases.
  • New chat_report_request_test.dart: an accepted report fires group_message_reported; a refused or failed one fires nothing; a successful retry fires once.
  • New group_chat_thread_selection_test.dart: a selection made before the profile loads gets Delete once it lands (fails without the listener).
  • Adds a shared RecordingAnalyticsService fake under test/core/analytics/.
  • flutter analyze --no-pub clean on the touched paths. flutter test test/features/group_chat test/core/analytics: 376 pass, 1 fails — prayer_requests_providers_test.dart does not compile because its fake repository is missing deleteMessages. That is pre-existing and not touched here.

Not verified end to end: no local .env carries 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 as live is not covered by a test.

@greptile-apps

greptile-apps Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

The PR should not merge until the chat-open event name matches the stated PostHog tracking contract or the contract is explicitly migrated.

Findings

  1. P1 Event name breaks contract
Fix with agent prompt
### Issue 1
lib/core/analytics/analytics_events.dart:26
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.

Summary

This PR adds PostHog instrumentation for group-chat opens, sends, replies, reactions, deletions, and reports.

  • Centralizes group-chat event payloads and fire-and-forget error handling in GroupChatAnalytics.
  • Emits action events only after repository confirmation, including per-message bulk-delete events.
  • Extracts reporting into a reusable request object and adds analytics-focused unit and widget coverage.
  • The chat-open event currently uses a different name from the stated tracking contract.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  U[Group-chat action] --> R[Repository request]
  R -->|Failure| N[No analytics event]
  R -->|Confirmed| H[GroupChatAnalytics]
  H --> P[AnalyticsService / PostHog]
  H -->|Capture failure| L[Log and suppress]
Loading

Reviews (1) · Last reviewed commit: "Address review on group chat analytics"

Comment thread lib/features/group_chat/presentation/screens/group_chat_screen.dart Outdated
Comment thread lib/features/group_chat/presentation/screens/group_chat_screen.dart Outdated
Comment thread lib/features/group_chat/presentation/widgets/group_chat_thread.dart
@harshal-2304
harshal-2304 changed the base branch from main to develop September 16, 2026 06:01
@harshal-2304
harshal-2304 changed the base branch from develop to feat/chatUIupdate September 16, 2026 06:02
@harshal-2304
harshal-2304 added this pull request to stack #782 September 16, 2026 06:02
@harshal-2304
harshal-2304 marked this pull request as draft September 16, 2026 06:02
@harshal-2304
harshal-2304 marked this pull request as ready for review September 16, 2026 06:02
@harshal-2304
harshal-2304 marked this pull request as draft September 16, 2026 06:51
@harshal-2304
harshal-2304 marked this pull request as ready for review September 16, 2026 06:52
@harshal-2304 harshal-2304 self-assigned this Sep 16, 2026
Base automatically changed from feat/chatUIupdate to develop September 17, 2026 10:58
harshal-2304 and others added 3 commits September 17, 2026 16:28
`_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>
- 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';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 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.

Suggested change
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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this is intentional

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

@tentamdin
tentamdin merged commit 6088f00 into develop Sep 17, 2026
1 of 2 checks passed
@TenzDelek
TenzDelek deleted the feat/chatAnalytics branch September 18, 2026 06:25
@tentamdin tentamdin mentioned this pull request Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants