Skip to content

Add analytics tracking and thumbs feedback to AI sidekick (V2 editor)#2441

Open
morgan-wowk wants to merge 1 commit into
masterfrom
ai-sidekick-analytics
Open

Add analytics tracking and thumbs feedback to AI sidekick (V2 editor)#2441
morgan-wowk wants to merge 1 commit into
masterfrom
ai-sidekick-analytics

Conversation

@morgan-wowk

@morgan-wowk morgan-wowk commented Jun 19, 2026

Copy link
Copy Markdown

Description

Adds analytics tracking and thumbs up/down feedback UI to the AI chat assistant.

When a user sends a message, an ai_assistant.message.submitted event is tracked with the prompt and current thread message count. Once the assistant responds, an ai_assistant.response.received event is tracked with the prompt, response content, and updated message count.

A new ResponseFeedback component is rendered below each assistant message, showing thumbs up and thumbs down buttons. Clicking either fires an ai_assistant.response.feedback event with the rating, prompt, and response, then fades out the buttons and displays a "Thank you for sharing your feedback" confirmation. The prompt for each assistant message is resolved by looking at the preceding user message in the thread.

Analytics events added

  • ai_assistant.message.submitted
  • ai_assistant.response.received
  • ai_assistant.response.feedback

Related Issue and Pull requests

Type of Change

  • Bug fix
  • New feature
  • Improvement
  • Cleanup/Refactor
  • Breaking change
  • Documentation update

Checklist

  • I have tested this does not break current pipelines / runs functionality
  • I have tested the changes on staging

Screenshots (if applicable)

image.png

Test Instructions

  1. Open the AI chat assistant and send a message.
  2. Verify that ai_assistant.message.submitted and ai_assistant.response.received events are fired in your analytics provider after the assistant replies.
  3. Confirm that thumbs up and thumbs down buttons appear below each assistant response.
  4. Click either button and verify the buttons fade out, the "Thank you for sharing your feedback" message appears, and an ai_assistant.response.feedback event is tracked with the correct rating, prompt, and response.
  5. Confirm that clicking a feedback button a second time has no effect.

Additional Comments

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown

🎩 Preview

A preview build has been created at: ai-sidekick-analytics/be6217a

Copy link
Copy Markdown
Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@morgan-wowk morgan-wowk marked this pull request as ready for review June 19, 2026 03:05
@morgan-wowk morgan-wowk requested a review from a team as a code owner June 19, 2026 03:05
@morgan-wowk morgan-wowk force-pushed the ai-sidekick-analytics branch from edc0ef3 to 4d1dbb5 Compare June 19, 2026 03:07
Tracks three events on the editor AI assistant:
- ai_assistant.message.submitted — fires on send with prompt + thread_message_count
- ai_assistant.response.received — fires after response completes with prompt, response, and thread_message_count
- ai_assistant.response.feedback — fires when user rates a response via thumbs up/down with rating, prompt, and response

Adds a ResponseFeedback component below each assistant message: outline thumbs icons that highlight to `text-info` on hover, then on click record the feedback event and fade (200ms out → 300ms in) to "Thank you for sharing your feedback".
@morgan-wowk morgan-wowk force-pushed the ai-sidekick-analytics branch from 4d1dbb5 to be6217a Compare June 19, 2026 03:12
if (lastMessage?.role === "assistant") {
track("ai_assistant.response.received", {
prompt,
response: lastMessage.content,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Response can be pretty beefy... not sure if we need to track it

Comment on lines +27 to +61
<div className="relative flex items-center h-5 mt-1.5">
<div
className={cn(
"flex gap-0.5 transition-opacity duration-200",
state === "submitted" ? "opacity-0" : "opacity-100",
)}
aria-hidden={state === "submitted"}
>
<button
onClick={() => handleFeedback("positive")}
disabled={state !== "idle"}
className="text-muted-foreground/30 hover:text-info transition-colors duration-150 p-0.5 rounded cursor-pointer"
aria-label="Helpful response"
>
<Icon name="ThumbsUp" size="xs" />
</button>
<button
onClick={() => handleFeedback("negative")}
disabled={state !== "idle"}
className="text-muted-foreground/30 hover:text-info transition-colors duration-150 p-0.5 rounded cursor-pointer"
aria-label="Not helpful response"
>
<Icon name="ThumbsDown" size="xs" />
</button>
</div>
<span
className={cn(
"absolute left-0 text-xs text-muted-foreground transition-opacity duration-300",
showThanks ? "opacity-100" : "opacity-0 pointer-events-none",
)}
>
Thank you for sharing your feedback
</span>
</div>
);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We must use UI primitives

Comment on lines +38 to +41
const precedingUserMessage =
msg.role === "assistant" && messages[i - 1]?.role === "user"
? messages[i - 1].content
: undefined;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If AI posted multiple messages (it may happen in theory), we're going to loose user prompt. I'm proposing another schema. That can simplify and solidify entire logic:

1. We can extend ChatMessage to carry prompt for assistant type message:

interface BaseChatMessage {
  id: string;
  content: string;
  componentReferences?: Record<string, ComponentRefData>;
}

export interface UserChatMessage extends BaseChatMessage {
  role: "user";
}

export interface AssistantChatMessage extends BaseChatMessage {
  role: "assistant";
  /**  Here: */
  prompt: string;
}

export type ChatMessage = UserChatMessage | AssistantChatMessage;

2. Next we need to update agentThread.ts so every answer tracks initial prompt:

this.messages = [
  ...this.messages,
  {
    id: generateMessageId(),
    role: "assistant",
    content: response.answer,
    prompt,
  },
];

3. Now we automatically have access to all required information in ChatMessage component.

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