Skip to content

Commit 25a7ad7

Browse files
committed
[TOOL-4176] Dashboard: Add tracking to nebula floating chat (#6777)
<!-- ## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes" If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000): ## Notes for the reviewer Anything important to call out? Be sure to also clarify these in your comments. ## How to test Unit tests, playground, etc. --> <!-- start pr-codex --> --- ## PR-Codex overview This PR enhances the `NebulaFloatingChatButton` and related components by introducing a `pageType` prop, allowing the chat functionality to differentiate between "chain" and "contract" contexts. It also integrates tracking events for user interactions. ### Detailed summary - Added `pageType` prop to `NebulaFloatingChatButton`, `FloatingChatContent`, and `FloatingChatContentLoggedIn`. - Updated the `label` for the chat button to reflect the context ("chain" or "contract"). - Integrated tracking events for button clicks and message sends, capturing the `pageType`. - Adjusted rendering logic in `FloatingChatContent` to use the new `pageType` prop. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent ac8b09f commit 25a7ad7

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed

apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/layout.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ The following is the user's message:
100100
return (
101101
<>
102102
<NebulaFloatingChatButton
103+
pageType="chain"
103104
authToken={authToken ?? undefined}
104105
label="Ask AI about this chain"
105106
client={client}

apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/layout.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ The following is the user's message:`;
115115
client={client}
116116
>
117117
<NebulaFloatingChatButton
118+
pageType="contract"
118119
authToken={authToken ?? undefined}
119120
label="Ask AI about this contract"
120121
client={client}

apps/dashboard/src/app/nebula-app/(app)/components/FloatingChat/FloatingChat.tsx

+30-1
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ import {
1515
useState,
1616
} from "react";
1717
import type { ThirdwebClient } from "thirdweb";
18+
import { useTrack } from "../../../../../hooks/analytics/useTrack";
1819
import type { ExamplePrompt } from "../../data/examplePrompts";
1920
import { NebulaIcon } from "../../icons/NebulaIcon";
2021

2122
const LazyFloatingChatContent = lazy(() => import("./FloatingChatContent"));
2223

2324
export function NebulaFloatingChatButton(props: {
25+
pageType: "chain" | "contract";
2426
authToken: string | undefined;
2527
examplePrompts: ExamplePrompt[];
2628
label: string;
@@ -37,6 +39,7 @@ export function NebulaFloatingChatButton(props: {
3739
const [hasBeenOpened, setHasBeenOpened] = useState(false);
3840
const closeModal = useCallback(() => setIsOpen(false), []);
3941
const [isDismissed, setIsDismissed] = useState(false);
42+
const trackEvent = useTrack();
4043

4144
if (isDismissed) {
4245
return null;
@@ -50,6 +53,12 @@ export function NebulaFloatingChatButton(props: {
5053
onClick={() => {
5154
setIsOpen(true);
5255
setHasBeenOpened(true);
56+
trackEvent({
57+
category: "floating_nebula",
58+
action: "click",
59+
label: "open",
60+
page: props.pageType,
61+
});
5362
}}
5463
variant="default"
5564
className="gap-2 rounded-full"
@@ -60,7 +69,15 @@ export function NebulaFloatingChatButton(props: {
6069
<Button
6170
variant="outline"
6271
className="size-10 rounded-full bg-card p-0"
63-
onClick={() => setIsDismissed(true)}
72+
onClick={() => {
73+
setIsDismissed(true);
74+
trackEvent({
75+
category: "floating_nebula",
76+
action: "click",
77+
label: "dismiss",
78+
page: props.pageType,
79+
});
80+
}}
6481
>
6582
<XIcon className="size-4" />
6683
</Button>
@@ -75,6 +92,7 @@ export function NebulaFloatingChatButton(props: {
7592
client={props.client}
7693
nebulaParams={props.nebulaParams}
7794
examplePrompts={props.examplePrompts}
95+
pageType={props.pageType}
7896
/>
7997
</>
8098
);
@@ -86,6 +104,7 @@ function NebulaChatUIContainer(props: {
86104
hasBeenOpened: boolean;
87105
authToken: string | undefined;
88106
examplePrompts: ExamplePrompt[];
107+
pageType: "chain" | "contract";
89108
client: ThirdwebClient;
90109
nebulaParams:
91110
| {
@@ -98,6 +117,7 @@ function NebulaChatUIContainer(props: {
98117
const ref = useOutsideClick(props.onClose);
99118
const shouldRenderChat = props.isOpen || props.hasBeenOpened;
100119
const [nebulaSessionKey, setNebulaSessionKey] = useState(0);
120+
const trackEvent = useTrack();
101121

102122
return (
103123
<div
@@ -112,6 +132,14 @@ function NebulaChatUIContainer(props: {
112132
className="group flex items-center gap-2"
113133
target="_blank"
114134
href="https://thirdweb.com/nebula"
135+
onClick={() => {
136+
trackEvent({
137+
category: "floating_nebula",
138+
action: "click",
139+
label: "nebula-landing",
140+
page: props.pageType,
141+
});
142+
}}
115143
>
116144
<h2 className="font-semibold text-lg tracking-tight">Nebula</h2>
117145
<ExternalLinkIcon className="size-4 text-muted-foreground/70 group-hover:text-foreground" />
@@ -158,6 +186,7 @@ function NebulaChatUIContainer(props: {
158186
nebulaParams={props.nebulaParams}
159187
key={nebulaSessionKey}
160188
examplePrompts={props.examplePrompts}
189+
pageType={props.pageType}
161190
/>
162191
</Suspense>
163192
)}

apps/dashboard/src/app/nebula-app/(app)/components/FloatingChat/FloatingChatContent.tsx

+16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { usePathname } from "next/navigation";
44
import { useCallback, useState } from "react";
55
import type { ThirdwebClient } from "thirdweb";
66
import { Button } from "../../../../../@/components/ui/button";
7+
import { useTrack } from "../../../../../hooks/analytics/useTrack";
78
import type { NebulaContext } from "../../api/chat";
89
import { createSession } from "../../api/session";
910
import type { ExamplePrompt } from "../../data/examplePrompts";
@@ -20,6 +21,7 @@ export default function FloatingChatContent(props: {
2021
authToken: string | undefined;
2122
client: ThirdwebClient;
2223
examplePrompts: ExamplePrompt[];
24+
pageType: "chain" | "contract";
2325
nebulaParams:
2426
| {
2527
messagePrefix: string;
@@ -38,13 +40,15 @@ export default function FloatingChatContent(props: {
3840
client={props.client}
3941
nebulaParams={props.nebulaParams}
4042
examplePrompts={props.examplePrompts}
43+
pageType={props.pageType}
4144
/>
4245
);
4346
}
4447

4548
function FloatingChatContentLoggedIn(props: {
4649
authToken: string;
4750
client: ThirdwebClient;
51+
pageType: "chain" | "contract";
4852
examplePrompts: ExamplePrompt[];
4953
nebulaParams:
5054
| {
@@ -60,6 +64,7 @@ function FloatingChatContentLoggedIn(props: {
6064
const [chatAbortController, setChatAbortController] = useState<
6165
AbortController | undefined
6266
>();
67+
const trackEvent = useTrack();
6368
const [isChatStreaming, setIsChatStreaming] = useState(false);
6469
const [enableAutoScroll, setEnableAutoScroll] = useState(false);
6570

@@ -90,6 +95,15 @@ function FloatingChatContentLoggedIn(props: {
9095
setIsChatStreaming(true);
9196
setEnableAutoScroll(true);
9297

98+
trackEvent({
99+
category: "floating_nebula",
100+
action: "send",
101+
label: "message",
102+
message: userMessage,
103+
page: props.pageType,
104+
sessionId: sessionId,
105+
});
106+
93107
// if this is first message, set the message prefix
94108
const messageToSend =
95109
props.nebulaParams?.messagePrefix && !userHasSubmittedMessage
@@ -145,6 +159,8 @@ function FloatingChatContentLoggedIn(props: {
145159
sessionId,
146160
props.nebulaParams?.messagePrefix,
147161
userHasSubmittedMessage,
162+
trackEvent,
163+
props.pageType,
148164
],
149165
);
150166

0 commit comments

Comments
 (0)