Compare commits

..

2 Commits

Author SHA1 Message Date
Tomek Gargula c23cc83a49 changeset
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-20 12:26:25 +02:00
Tomek Gargula f11d07fc06 Track Ask AI trigger clicks in insights
Send an ask_trigger_click event from each Ask entry point (site button, paragraph, text selection, code block, page actions) and open the code block assistant with the code reference.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-20 12:26:25 +02:00
8 changed files with 28 additions and 9 deletions
-5
View File
@@ -1,5 +0,0 @@
---
"gitbook": patch
---
Adjust tab panel and tab button padding so tabbed content has more breathing room.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Track `ask_trigger_click` insights event when an Ask entry point is clicked.
@@ -1,6 +1,7 @@
'use client';
import type { Assistant } from '../AI';
import { useIsMobile } from '../hooks/useIsMobile';
import { useTrackEvent } from '../Insights';
import { Button } from '../primitives';
import { KeyboardShortcut } from '../primitives/KeyboardShortcut';
import { useLanguage } from '@/intl/client';
@@ -18,6 +19,7 @@ export function AIChatButton(props: {
}) {
const { assistant, showLabel = true, withShortcut = true } = props;
const language = useLanguage();
const trackEvent = useTrackEvent();
const isMobile = useIsMobile(MOBILE_BREAKPOINT, '[data-gb-header-content]');
return (
@@ -39,7 +41,12 @@ export function AIChatButton(props: {
</div>
}
aria-label={tString(language, 'ai_chat_ask', assistant.label)}
onClick={() => assistant.open(undefined, 'site')}
onClick={() => {
if (assistant.id === 'gitbook-assistant') {
trackEvent({ type: 'ask_trigger_click', trigger: 'site' });
}
assistant.open(undefined, 'site');
}}
>
{showLabel ? t(language, 'ask') : null}
</Button>
@@ -6,6 +6,7 @@ import { createPortal } from 'react-dom';
import { AIChatIcon } from '../AIChatIcon';
import { useAIChatController, useAIConfig } from '@/components/AI';
import { useTrackEvent } from '@/components/Insights';
import { Button } from '@/components/primitives';
import { isAIChatEnabled } from '@/components/utils/isAIChatEnabled';
import { t, tString, useLanguage } from '@/intl/client';
@@ -24,6 +25,7 @@ export function AskAIParagraphButton() {
const config = useAIConfig();
const language = useLanguage();
const chatController = useAIChatController();
const trackEvent = useTrackEvent();
const [target, setTarget] = React.useState<HTMLElement | null>(null);
const enabled = isAIChatEnabled(config.aiMode);
@@ -52,6 +54,7 @@ export function AskAIParagraphButton() {
}
const onClick = () => {
trackEvent({ type: 'ask_trigger_click', trigger: 'hover' });
const text = getParagraphText(target).trim();
if (!text) {
return;
@@ -10,6 +10,7 @@ import { useStableTextSelection } from './useStableTextSelection';
import { useAIChatController, useAIConfig } from '@/components/AI';
import { useIsMobile } from '@/components/hooks/useIsMobile';
import { useIsMounted } from '@/components/hooks/useIsMounted';
import { useTrackEvent } from '@/components/Insights';
import { Button } from '@/components/primitives';
import { isAIChatEnabled } from '@/components/utils/isAIChatEnabled';
import { t, useLanguage } from '@/intl/client';
@@ -27,6 +28,7 @@ export function AskAITextSelection() {
const config = useAIConfig();
const language = useLanguage();
const chatController = useAIChatController();
const trackEvent = useTrackEvent();
const isMobile = useIsMobile();
const isMounted = useIsMounted();
@@ -71,6 +73,7 @@ export function AskAITextSelection() {
}, [selection]);
const onClick = () => {
trackEvent({ type: 'ask_trigger_click', trigger: 'selection' });
if (!selection) {
return;
}
@@ -3,6 +3,7 @@
import { getCodeTextFromId } from './utils';
import { useAIChatController, useAIConfig } from '@/components/AI';
import { AIChatIcon } from '@/components/AIChat';
import { useTrackEvent } from '@/components/Insights';
import { Button } from '@/components/primitives';
import { isAIChatEnabled } from '@/components/utils/isAIChatEnabled';
import { t, useLanguage } from '@/intl/client';
@@ -19,12 +20,14 @@ export function AskAICodeButton(props: {
const language = useLanguage();
const config = useAIConfig();
const chatController = useAIChatController();
const trackEvent = useTrackEvent();
if (!isAIChatEnabled(config.aiMode)) {
return null;
}
const onClick = () => {
trackEvent({ type: 'ask_trigger_click', trigger: 'code' });
const codeText = getCodeTextFromId(codeId);
if (!codeText?.trim()) {
return;
@@ -37,7 +40,7 @@ export function AskAICodeButton(props: {
content: codeText,
syntax,
});
chatController.open();
chatController.open('code');
chatController.focus();
};
@@ -130,7 +130,7 @@ const TabPanel = memo(function TabPanel(props: {
aria-labelledby={getTabButtonId(tab.id)}
className="scroll-mt-[calc(var(--content-scroll-margin)+var(--spacing)*20)]"
>
<div className="px-8 py-6">{tab.body}</div>
<div className="p-4">{tab.body}</div>
</div>
);
});
@@ -317,7 +317,7 @@ function TabButton(
{...rest}
type="button"
className={tcls(
'relative inline-flex max-w-full items-center gap-1.5 px-4 py-2.5 font-medium text-sm transition-[color]',
'relative inline-flex max-w-full items-center gap-1.5 px-3.5 py-2 font-medium text-sm transition-[color]',
props.className
)}
/>
@@ -10,6 +10,7 @@ import { Icon, type IconName, IconStyle } from '@gitbook/icons';
import { useAIChatController, useAIChatState } from '@/components/AI';
import type { Assistant } from '@/components/AI';
import { useTrackEvent } from '@/components/Insights';
import { Button } from '@/components/primitives/Button';
import { DropdownMenuItem, useDropdownMenuClose } from '@/components/primitives/DropdownMenu';
import { getURLForLLM } from '@/components/utils';
@@ -39,6 +40,7 @@ export function ActionOpenAssistant(props: {
const { assistant, type, page } = props;
const chat = useAIChatState();
const chatController = useAIChatController();
const trackEvent = useTrackEvent();
const language = useLanguage();
return (
@@ -55,6 +57,7 @@ export function ActionOpenAssistant(props: {
)}
disabled={chat.responding}
onClick={() => {
trackEvent({ type: 'ask_trigger_click', trigger: 'page' });
// Stage a reference to the current page so the assistant is informed about
// the context the user is asking from. Only the sidebar GitBook Assistant
// uses the chat reference system.