Skip to content

Commit 2aa9ce5

Browse files
committed
posthog migration: part 4 (#7366)
# Analytics Event Reporting System This PR introduces a structured analytics event reporting system for the dashboard app using PostHog. It provides clear guidelines and standardized patterns for tracking user actions. ## Key Features - Added a centralized analytics reporting system in `src/@/analytics/report.ts` - Implemented standardized naming conventions for events (`<subject> <verb>`) and reporting functions (`report<Subject><Verb>`) - Created comprehensive documentation in `apps/dashboard/src/@/analytics/README.md` - Added mandatory JSDoc requirements to document the purpose and ownership of each event - Integrated the first event: `reportContractDeployed` to track contract deployments - Updated the contract deployment form to use the new analytics system ## Guidelines - Events should only be added when they answer concrete product/business questions - All events must include typed properties and proper documentation - Analytics code is client-side only (never import `posthog-js` in server components) - Developers should notify #core-services before renaming or removing events This standardized approach will make our analytics more maintainable, discoverable, and purposeful. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Documentation** - Added comprehensive guidelines and a README for analytics event reporting, including naming conventions, usage examples, and requirements for event tracking in the dashboard app. - **New Features** - Introduced new analytics events covering contract deployments and multiple stages of team onboarding, such as plan selection, member invitations, and onboarding completion. - **Refactor** - Centralized analytics reporting by replacing generic event tracking with dedicated reporting functions across contract deployment and team onboarding flows. - Removed redundant and granular event tracking calls, simplifying analytics integration and improving consistency. <!-- end of auto-generated comment: release notes by coderabbit.ai --> <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on enhancing analytics event reporting for onboarding and contract deployment processes across the application, ensuring better tracking of user interactions and feedback. ### Detailed summary - Added `.eslintignore` entries for markdown files. - Updated `InviteTeamMembers` and `InviteSection` to report success counts on invites. - Introduced new reporting functions in `report.ts` for onboarding and contract events. - Removed unused `trackEvent` calls, replacing them with specific reporting functions. - Enhanced documentation for analytics guidelines and event reporting in `README.md` files. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent d9eee50 commit 2aa9ce5

File tree

16 files changed

+435
-161
lines changed

16 files changed

+435
-161
lines changed

.cursor/rules/dashboard.mdc

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ description: Rules for writing features in apps/dashboard
33
globs: dashboard
44
alwaysApply: false
55
---
6-
76
# Reusable Core UI Components
87

98
- Always import from the central UI library under `@/components/ui/*` – e.g. `import { Button } from "@/components/ui/button"`.
@@ -101,3 +100,29 @@ Guidelines:
101100
- Keep `queryKey` stable and descriptive for cache hits.
102101
- Prefer API routes or server actions to keep tokens secret; the browser only sees relative paths.
103102
- Configure `staleTime` / `cacheTime` according to freshness requirements.
103+
104+
# Analytics Event Reporting
105+
106+
- **Add events intentionally** – only when they answer a concrete product/business question.
107+
- **Event name**: human-readable `<subject> <verb>` phrase (e.g. `"contract deployed"`).
108+
- **Reporting helper**: `report<Subject><Verb>` (PascalCase); all live in `src/@/analytics/report.ts`.
109+
- **Mandatory JSDoc**: explain *Why* the event exists and *Who* owns it (`@username`).
110+
- **Typed properties**: accept a single `properties` object and pass it unchanged to `posthog.capture`.
111+
- **Client-side only**: never import `posthog-js` in server components.
112+
- **Housekeeping**: ping **#core-services** before renaming or removing an event.
113+
114+
```ts
115+
/**
116+
* ### Why do we need to report this event?
117+
* - Tracks number of contracts deployed
118+
*
119+
* ### Who is responsible for this event?
120+
* @jnsdls
121+
*/
122+
export function reportContractDeployed(properties: {
123+
address: string;
124+
chainId: number;
125+
}) {
126+
posthog.capture("contract deployed", properties);
127+
}
128+
```

AGENTS.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,41 @@ Welcome, AI copilots! This guide captures the coding standards, architectural de
104104
-- Configure staleTime / cacheTime based on freshness requirements (default ≥ 60 s).
105105
-- Keep tokens secret by calling internal API routes or server actions.
106106

107+
6.5 Analytics Event Reporting
108+
109+
- **When to create a new event**
110+
-- Only add events that answer a clear product or business question.
111+
-- Check `src/@/analytics/report.ts` first; avoid duplicates.
112+
113+
- **Naming conventions**
114+
-- **Event name**: human-readable phrase in the form `<subject> <verb>` (e.g. "contract deployed").
115+
-- **Reporting function**: `report<Subject><Verb>` (PascalCase).
116+
-- All reporting helpers currently live in the shared `report.ts` file.
117+
118+
- **Boilerplate template**
119+
-- Add a JSDoc header explaining **Why** the event exists and **Who** owns it (`@username`).
120+
-- Accept a single typed `properties` object and forward it unchanged to `posthog.capture`.
121+
-- Example:
122+
123+
```ts
124+
/**
125+
* ### Why do we need to report this event?
126+
* - Tracks number of contracts deployed
127+
*
128+
* ### Who is responsible for this event?
129+
* @jnsdls
130+
*/
131+
export function reportContractDeployed(properties: {
132+
address: string;
133+
chainId: number;
134+
}) {
135+
posthog.capture("contract deployed", properties);
136+
}
137+
```
138+
139+
- **Client-side only**: never import `posthog-js` in server components.
140+
- **Housekeeping**: Inform **#eng-core-services** before renaming or removing an existing event.
141+
107142
108143

109144
7. Performance & Bundle Size
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Analytics Guidelines
2+
3+
This folder centralises the **PostHog** tracking logic for the dashboard app.
4+
Most developers will only need to add or extend _event-reporting_ functions in `report.ts`.
5+
6+
---
7+
8+
## 1. When to add an event
9+
1. Ask yourself if the data will be **actionable**. Every event should have a clear product or business question it helps answer.
10+
2. Check if a similar event already exists in `report.ts`. Avoid duplicates.
11+
12+
---
13+
14+
## 2. Naming conventions
15+
| Concept | Convention | Example |
16+
|---------|------------|---------|
17+
| **Event name** (string sent to PostHog) | Human-readable phrase formatted as `<subject> <verb>` | `"contract deployed"` |
18+
| **Reporting function** | `report<Subject><Verb>` (PascalCase) | `reportContractDeployed` |
19+
| **File** | All event functions live in the shared `report.ts` file (for now) ||
20+
21+
> Keeping names predictable makes it easy to search both code and analytics.
22+
23+
---
24+
25+
## 3. Boilerplate / template
26+
Add a new function to `report.ts` following this pattern:
27+
28+
```ts
29+
/**
30+
* ### Why do we need to report this event?
31+
* - _Add bullet points explaining the product metrics/questions this event answers._
32+
*
33+
* ### Who is responsible for this event?
34+
* @your-github-handle
35+
*/
36+
export function reportExampleEvent(properties: {
37+
/* Add typed properties here */
38+
}) {
39+
posthog.capture("example event", {
40+
/* Pass the same properties here */
41+
});
42+
}
43+
```
44+
45+
Guidelines:
46+
1. **Explain the "why".** The JSDoc block is mandatory so future contributors know the purpose.
47+
2. **Type everything.** The `properties` object should be fully typed—this doubles as documentation.
48+
3. **Client-side only.** `posthog-js` must never run on the server. Call these reporting helpers from client components, event handlers, etc.
49+
50+
---
51+
52+
## 4. Editing or removing events
53+
1. Update both the function and the PostHog event definition (if required).
54+
2. Inform the core services team before removing or renaming an event.
55+
56+
---
57+
58+
## 5. Identification & housekeeping (FYI)
59+
Most devs can ignore this section, but for completeness:
60+
61+
- `hooks/identify-account.ts` and `hooks/identify-team.ts` wrap `posthog.identify`/`group` calls.
62+
- `resetAnalytics` clears identity state (used on logout).
63+
64+
---
65+
66+
## 6. Need help?
67+
Ping #eng-core-services in slack.
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import posthog from "posthog-js";
2+
3+
import type { Team } from "../api/team";
4+
5+
// ----------------------------
6+
// CONTRACTS
7+
// ----------------------------
8+
9+
/**
10+
* ### Why do we need to report this event?
11+
* - To track the number of contracts deployed
12+
* - To track the number of contracts deployed on each chain
13+
*
14+
* ### Who is responsible for this event?
15+
* @jnsdls
16+
*
17+
*/
18+
export function reportContractDeployed(properties: {
19+
address: string;
20+
chainId: number;
21+
publisher: string | undefined;
22+
contractName: string | undefined;
23+
}) {
24+
posthog.capture("contract deployed", properties);
25+
}
26+
27+
/**
28+
* ### Why do we need to report this event?
29+
* - To track the number of contracts that failed to deploy
30+
* - To track the error message of the failed contract deployment (so we can fix it / add workarounds)
31+
*
32+
* ### Who is responsible for this event?
33+
* @jnsdls
34+
*
35+
*/
36+
export function reportContractDeployFailed(properties: {
37+
errorMessage: string;
38+
}) {
39+
posthog.capture("contract deploy failed", properties);
40+
}
41+
42+
// ----------------------------
43+
// ONBOARDING (TEAM)
44+
// ----------------------------
45+
46+
/**
47+
* ### Why do we need to report this event?
48+
* - To track the number of teams that enter the onboarding flow
49+
*
50+
* ### Who is responsible for this event?
51+
* @jnsdls
52+
*
53+
*/
54+
export function reportOnboardingStarted() {
55+
posthog.capture("onboarding started");
56+
}
57+
58+
/**
59+
* ### Why do we need to report this event?
60+
* - To track the number of teams that select a paid plan during onboarding
61+
* - To know **which** plan was selected
62+
*
63+
* ### Who is responsible for this event?
64+
* @jnsdls
65+
*
66+
*/
67+
export function reportOnboardingPlanSelected(properties: {
68+
plan: Team["billingPlan"];
69+
}) {
70+
posthog.capture("onboarding plan selected", properties);
71+
}
72+
73+
/**
74+
* ### Why do we need to report this event?
75+
* - To track the number of teams that skip the plan-selection step during onboarding
76+
*
77+
* ### Who is responsible for this event?
78+
* @jnsdls
79+
*
80+
*/
81+
export function reportOnboardingPlanSelectionSkipped() {
82+
posthog.capture("onboarding plan selection skipped");
83+
}
84+
85+
/**
86+
* ### Why do we need to report this event?
87+
* - To track the number of teams that invite members during onboarding
88+
* - To track **how many** members were invited
89+
*
90+
* ### Who is responsible for this event?
91+
* @jnsdls
92+
*
93+
*/
94+
export function reportOnboardingMembersInvited(properties: {
95+
count: number;
96+
}) {
97+
posthog.capture("onboarding members invited", {
98+
count: properties.count,
99+
});
100+
}
101+
102+
/**
103+
* ### Why do we need to report this event?
104+
* - To track the number of teams that skip inviting members during onboarding
105+
*
106+
* ### Who is responsible for this event?
107+
* @jnsdls
108+
*
109+
*/
110+
export function reportOnboardingMembersSkipped() {
111+
posthog.capture("onboarding members skipped");
112+
}
113+
114+
/**
115+
* ### Why do we need to report this event?
116+
* - To track how many teams click the upsell (upgrade) button on the member-invite step during onboarding
117+
*
118+
* ### Who is responsible for this event?
119+
* @jnsdls
120+
*
121+
*/
122+
export function reportOnboardingMembersUpsellButtonClicked() {
123+
posthog.capture("onboarding members upsell clicked");
124+
}
125+
126+
/**
127+
* ### Why do we need to report this event?
128+
* - To track which plan is selected from the members-step upsell during onboarding
129+
*
130+
* ### Who is responsible for this event?
131+
* @jnsdls
132+
*
133+
*/
134+
export function reportOnboardingMembersUpsellPlanSelected(properties: {
135+
plan: Team["billingPlan"];
136+
}) {
137+
posthog.capture("onboarding members upsell plan selected", properties);
138+
}
139+
140+
/**
141+
* ### Why do we need to report this event?
142+
* - To track the number of teams that completed onboarding
143+
*
144+
* ### Who is responsible for this event?
145+
* @jnsdls
146+
*
147+
*/
148+
export function reportOnboardingCompleted() {
149+
posthog.capture("onboarding completed");
150+
}

0 commit comments

Comments
 (0)