Skip to content

Commit 67f3c9c

Browse files
committed
events upd
1 parent 52275c7 commit 67f3c9c

File tree

10 files changed

+455
-68
lines changed

10 files changed

+455
-68
lines changed

apps/vscode-extension/TELEMETRY.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ We collect the following types of telemetry data:
2626
- When users get recommended integrating the toolbar into their project
2727
- Toolbar dependency auto-updating triggered (`toolbar_auto_update_prompt_sent`)
2828
- When users trigger an auto-update sequence for the toolbar packages
29+
- Component interaction events (`magic_chat_triggered`, `components_search_triggered`, `component_selected`, `agent_prompt_triggered_with_component`)
30+
- When users interact with UI components and Magic Chat features in the toolbar
2931
- Telemetry setting changes (`telemetry_disabled`, `telemetry_enabled`)
3032
- When users opt-out or opt-in to telemetry collection
3133

@@ -67,6 +69,16 @@ We collect the following types of telemetry data:
6769
- `toolbar_integration_notification_dismissed`: Triggered when the user dismisses the toolbar integration notification
6870
- No additional properties collected
6971

72+
#### Component Interaction Events
73+
- `magic_chat_triggered`: Triggered when the user invokes Magic Chat functionality
74+
- Includes: session ID, user input text, final prompt, DOM elements count, selected components array
75+
- `components_search_triggered`: Triggered when the user activates component search via Tab key
76+
- Includes: session ID, search query, search query length, search intent, DOM elements count, selected components array
77+
- `component_selected`: Triggered when the user selects a UI component from search results
78+
- Includes: session ID, demo ID/name, component name/description, search query and length
79+
- `agent_prompt_triggered_with_component`: Triggered when an agent prompt is sent with UI components selected
80+
- Includes: session ID, prompt text, component count/IDs, DOM elements count, runtime error status/message, prompt action
81+
7082
#### Privacy Events
7183
- `telemetry_disabled`: Triggered when a user disables telemetry collection
7284
- Tracked once when the setting changes, before telemetry is actually disabled

apps/vscode-extension/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"displayName": "21st.dev",
44
"private": true,
55
"description": "21st.dev Extension",
6-
"version": "0.0.9",
6+
"version": "0.0.10",
77
"publisher": "21st-dev",
88
"icon": "icon.png",
99
"author": "21st Labs Inc.",

apps/vscode-extension/src/activation/activate.ts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import {
22
DEFAULT_PORT,
3+
EventName,
34
getExtensionBridge,
45
} from '@21st-extension/extension-toolbar-srpc-contract';
5-
import { AnalyticsService, EventName } from 'src/services/analytics-service';
6+
import { AnalyticsService } from 'src/services/analytics-service';
67
import { EnvironmentInfo } from 'src/services/environment-info';
78
import { RegistryService } from 'src/services/registry-service';
89
import { StorageService } from 'src/services/storage-service';
@@ -34,13 +35,13 @@ const outputChannel = vscode.window.createOutputChannel('21st-extension');
3435
async function setupToolbarHandler() {
3536
await setupToolbar();
3637
await vscode.window.showInformationMessage(
37-
"The agent has been started to integrate 21st.dev Toolbar into this project. Please follow the agent's instructions in the chat panel.",
38+
"The agent has been started to integrate 21st.dev Toolbar into this project. Please follow the agent's instructions in the chat panel.",
3839
'OK',
3940
);
4041
}
4142

4243
export async function activate(context: vscode.ExtensionContext) {
43-
console.log('Activating 21st.dev Extension');
44+
console.log('Activating 21st.dev Extension');
4445
try {
4546
// initialize all services in the correct order
4647
VScodeContext.getInstance().initialize(context);
@@ -168,6 +169,36 @@ export async function activate(context: vscode.ExtensionContext) {
168169
result: { success: true },
169170
};
170171
},
172+
trackEvent: async (request, sendUpdate) => {
173+
const sessionError = checkSessionId(request);
174+
if (sessionError) return sessionError;
175+
176+
try {
177+
await analyticsService.trackEvent(
178+
request.eventName as EventName,
179+
request.properties,
180+
);
181+
182+
return {
183+
sessionId: vscode.env.sessionId,
184+
result: { success: true },
185+
};
186+
} catch (error) {
187+
const errorMessage =
188+
error instanceof Error ? error.message : String(error);
189+
console.error(
190+
`[21st.dev Extension] Failed to track event: ${errorMessage}`,
191+
);
192+
193+
return {
194+
sessionId: vscode.env.sessionId,
195+
result: {
196+
success: false,
197+
error: errorMessage,
198+
},
199+
};
200+
}
201+
},
171202
openExternal: async (request, sendUpdate) => {
172203
const sessionError = checkSessionId(request);
173204
if (sessionError) return sessionError;

apps/vscode-extension/src/services/analytics-service.ts

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,15 @@
1+
import { EventName as EventNameContract } from '@21st-extension/extension-toolbar-srpc-contract';
12
import { createHash } from 'node:crypto';
23
import { PostHog } from 'posthog-node';
34
import * as vscode from 'vscode';
45
import { EnvironmentInfo } from './environment-info';
56
import { VScodeContext } from './vscode-context';
67

8+
export { EventNameContract as EventName };
9+
710
// Note: The API key should be your actual PostHog API key
811
const SALT = '21st-extension';
912

10-
export enum EventName {
11-
EXTENSION_ACTIVATED = 'extension_activated',
12-
ACTIVATION_ERROR = 'activation_error',
13-
14-
OPENED_WEB_APP_WORKSPACE = 'opened_web_app_workspace',
15-
16-
GETTING_STARTED_PANEL_SHOWN = 'getting_started_panel_shown',
17-
GETTING_STARTED_PANEL_MANUAL_SHOW = 'getting_started_panel_manual_show',
18-
INTERACTED_WITH_GETTING_STARTED_PANEL = 'interacted_with_getting_started_panel',
19-
DISMISSED_GETTING_STARTED_PANEL = 'dismissed_getting_started_panel',
20-
CLICKED_SETUP_TOOLBAR_IN_GETTING_STARTED_PANEL = 'clicked_setup_toolbar_in_getting_started_panel',
21-
CLICKED_OPEN_DOCS_IN_GETTING_STARTED_PANEL = 'clicked_open_docs_in_getting_started_panel',
22-
23-
POST_SETUP_FEEDBACK = 'post_setup_feedback',
24-
25-
TOOLBAR_AUTO_SETUP_STARTED = 'toolbar_auto_setup_started',
26-
27-
TOOLBAR_CONNECTED = 'toolbar_connected',
28-
29-
AGENT_PROMPT_TRIGGERED = 'agent_prompt_triggered',
30-
OPEN_EXTERNAL_URL = 'open_external_url',
31-
32-
SHOW_TOOLBAR_UPDATE_NOTIFICATION = 'show_toolbar_update_notification',
33-
TOOLBAR_UPDATE_NOTIFICATION_AUTO_UPDATE = 'toolbar_update_notification_auto_update',
34-
TOOLBAR_UPDATE_NOTIFICATION_IGNORED = 'toolbar_update_notification_ignored',
35-
TOOLBAR_UPDATE_NOTIFICATION_DISMISSED = 'toolbar_update_notification_dismissed',
36-
37-
SHOW_TOOLBAR_INTEGRATION_NOTIFICATION = 'show_toolbar_integration_notification',
38-
TOOLBAR_INTEGRATION_NOTIFICATION_IGNORE = 'toolbar_integration_notification_ignore',
39-
TOOLBAR_INTEGRATION_NOTIFICATION_DISMISSED = 'toolbar_integration_notification_dismissed',
40-
41-
TOOLBAR_AUTO_UPDATE_PROMPT_SENT = 'toolbar_auto_update_prompt_sent',
42-
}
43-
4413
export class AnalyticsService {
4514
private static instance: AnalyticsService;
4615
private context = VScodeContext.getInstance();
@@ -93,7 +62,7 @@ export class AnalyticsService {
9362
}
9463

9564
public async trackEvent(
96-
eventName: EventName,
65+
eventName: EventNameContract,
9766
properties?: Record<string, any>,
9867
): Promise<void> {
9968
if (!this.isAnalyticsEnabled()) {

apps/vscode-extension/telemetry.json

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,164 @@
162162
"classification": "SystemMetaData",
163163
"purpose": "FeatureInsight",
164164
"comment": "Tracks when a user dismisses the toolbar integration notification"
165+
},
166+
"magic_chat_triggered": {
167+
"classification": "EndUserPseudonymizedInformation",
168+
"purpose": "FeatureInsight",
169+
"comment": "Tracks when Magic Chat is triggered by the user",
170+
"properties": {
171+
"sessionId": {
172+
"classification": "EndUserPseudonymizedInformation",
173+
"purpose": "FeatureInsight",
174+
"comment": "IDE session identifier"
175+
},
176+
"text": {
177+
"classification": "EndUserPseudonymizedInformation",
178+
"purpose": "FeatureInsight",
179+
"comment": "User input text"
180+
},
181+
"prompt": {
182+
"classification": "EndUserPseudonymizedInformation",
183+
"purpose": "FeatureInsight",
184+
"comment": "Final processed prompt sent to Magic Chat"
185+
},
186+
"domSelectedElementsCount": {
187+
"classification": "SystemMetaData",
188+
"purpose": "FeatureInsight",
189+
"comment": "Number of DOM elements selected"
190+
},
191+
"selectedComponents": {
192+
"classification": "SystemMetaData",
193+
"purpose": "FeatureInsight",
194+
"comment": "Array of selected UI components with id and name"
195+
}
196+
}
197+
},
198+
"components_search_triggered": {
199+
"classification": "EndUserPseudonymizedInformation",
200+
"purpose": "FeatureInsight",
201+
"comment": "Tracks when component search is triggered via Tab key",
202+
"properties": {
203+
"sessionId": {
204+
"classification": "EndUserPseudonymizedInformation",
205+
"purpose": "FeatureInsight",
206+
"comment": "IDE session identifier"
207+
},
208+
"searchQuery": {
209+
"classification": "EndUserPseudonymizedInformation",
210+
"purpose": "FeatureInsight",
211+
"comment": "Search query text (may contain user intent)"
212+
},
213+
"searchQueryLength": {
214+
"classification": "SystemMetaData",
215+
"purpose": "FeatureInsight",
216+
"comment": "Length of search query"
217+
},
218+
"searchIntent": {
219+
"classification": "SystemMetaData",
220+
"purpose": "FeatureInsight",
221+
"comment": "Detected search intent"
222+
},
223+
"selectedDomElementsCount": {
224+
"classification": "SystemMetaData",
225+
"purpose": "FeatureInsight",
226+
"comment": "Number of DOM elements selected"
227+
},
228+
"selectedComponents": {
229+
"classification": "SystemMetaData",
230+
"purpose": "FeatureInsight",
231+
"comment": "Array of selected UI components with id and name"
232+
}
233+
}
234+
},
235+
"component_selected": {
236+
"classification": "EndUserPseudonymizedInformation",
237+
"purpose": "FeatureInsight",
238+
"comment": "Tracks when a user selects a UI component from search results",
239+
"properties": {
240+
"sessionId": {
241+
"classification": "EndUserPseudonymizedInformation",
242+
"purpose": "FeatureInsight",
243+
"comment": "IDE session identifier"
244+
},
245+
"demoId": {
246+
"classification": "SystemMetaData",
247+
"purpose": "FeatureInsight",
248+
"comment": "Unique identifier of the selected component demo"
249+
},
250+
"demoName": {
251+
"classification": "SystemMetaData",
252+
"purpose": "FeatureInsight",
253+
"comment": "Name of the selected component demo"
254+
},
255+
"componentName": {
256+
"classification": "SystemMetaData",
257+
"purpose": "FeatureInsight",
258+
"comment": "Name of the selected component"
259+
},
260+
"componentDescription": {
261+
"classification": "SystemMetaData",
262+
"purpose": "FeatureInsight",
263+
"comment": "Description of the selected component"
264+
},
265+
"searchQuery": {
266+
"classification": "EndUserPseudonymizedInformation",
267+
"purpose": "FeatureInsight",
268+
"comment": "Search query that led to component selection"
269+
},
270+
"searchQueryLength": {
271+
"classification": "SystemMetaData",
272+
"purpose": "FeatureInsight",
273+
"comment": "Length of search query"
274+
}
275+
}
276+
},
277+
"agent_prompt_triggered_with_component": {
278+
"classification": "EndUserPseudonymizedInformation",
279+
"purpose": "FeatureInsight",
280+
"comment": "Tracks when an agent prompt is triggered with UI components selected",
281+
"properties": {
282+
"sessionId": {
283+
"classification": "EndUserPseudonymizedInformation",
284+
"purpose": "FeatureInsight",
285+
"comment": "IDE session identifier"
286+
},
287+
"promptText": {
288+
"classification": "EndUserPseudonymizedInformation",
289+
"purpose": "FeatureInsight",
290+
"comment": "The prompt text entered by the user"
291+
},
292+
"componentCount": {
293+
"classification": "SystemMetaData",
294+
"purpose": "FeatureInsight",
295+
"comment": "Number of components selected"
296+
},
297+
"componentIds": {
298+
"classification": "SystemMetaData",
299+
"purpose": "FeatureInsight",
300+
"comment": "Array of component IDs"
301+
},
302+
"selectedDomElementsCount": {
303+
"classification": "SystemMetaData",
304+
"purpose": "FeatureInsight",
305+
"comment": "Number of DOM elements selected"
306+
},
307+
"hasRuntimeError": {
308+
"classification": "SystemMetaData",
309+
"purpose": "FeatureInsight",
310+
"comment": "Whether a runtime error was included"
311+
},
312+
"runtimeError": {
313+
"classification": "CallstackOrException",
314+
"purpose": "PerformanceAndHealth",
315+
"comment": "Runtime error message if included"
316+
},
317+
"promptAction": {
318+
"classification": "SystemMetaData",
319+
"purpose": "FeatureInsight",
320+
"comment": "The action taken with the prompt (send, copy, or both)"
321+
}
322+
}
165323
}
166324
}
167325
}

examples/react-example/src/App.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,17 @@ function App() {
2525
<button type="button" onClick={() => setCount((count) => count + 1)}>
2626
count is {count}
2727
</button>
28-
<button
29-
type="button"
28+
<button
29+
type="button"
3030
onClick={handleRuntimeError}
31-
style={{
32-
backgroundColor: '#ef4444',
33-
color: 'white',
34-
border: 'none',
35-
padding: '8px 16px',
36-
borderRadius: '4px',
31+
style={{
32+
backgroundColor: '#ef4444',
33+
color: 'white',
34+
border: 'none',
35+
padding: '8px 16px',
36+
borderRadius: '4px',
3737
marginLeft: '8px',
38-
cursor: 'pointer'
38+
cursor: 'pointer',
3939
}}
4040
>
4141
Trigger Runtime Error

packages/extension-toolbar-srpc-contract/index.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
export {
2+
contract,
3+
DEFAULT_PORT,
4+
EventName,
5+
PING_ENDPOINT,
6+
PING_RESPONSE,
7+
} from './src/contract';
8+
export type { PromptRequest, VSCodeContext } from './src/contract';
19
export { getExtensionBridge } from './src/extension-bridge';
210
export { getToolbarBridge } from './src/toolbar-bridge';
3-
export { contract } from './src/contract';
4-
export { DEFAULT_PORT, PING_ENDPOINT, PING_RESPONSE } from './src/contract';
5-
export type { PromptRequest, VSCodeContext } from './src/contract';

0 commit comments

Comments
 (0)