Skip to main content

Event tracking and analytics

The Kapa SDK provides event tracking capabilities through callback functions. This allows you to monitor user interactions with the AI and integrate with your analytics systems.

Available events

The SDK emits events at key points in the user journey:

EventDescription
onQuerySubmitWhen a user submits a question
onAnswerGenerationCompletedWhen an answer is fully generated
onAnswerGenerationStopWhen generation is manually stopped by the user
onConversationResetWhen the conversation is reset
onFeedbackSubmitWhen a user provides feedback on an answer

Setting up callbacks

Configure event callbacks when setting up the KapaProvider:

import { KapaProvider } from "@kapaai/react-sdk";

function App() {
return (
<KapaProvider
integrationId="your-integration-id"
callbacks={{
askAI: {
onQuerySubmit: (data) => {
console.log("Question asked:", data.question);
// Send to your analytics service
},
onAnswerGenerationCompleted: (data) => {
console.log("Answer generated:", {
questionId: data.questionAnswerId,
question: data.question,
answer: data.answer,
});
},
onFeedbackSubmit: (data) => {
console.log("Feedback submitted:", {
questionId: data.questionAnswerId,
reaction: data.reaction,
comment: data.comment,
});
},
},
}}
>
<YourApplication />
</KapaProvider>
);
}

Callback payloads

Each event callback receives a data object with relevant information:

onQuerySubmit

interface QuerySubmitPayload {
// The question text
question: string;

// Current thread ID (null for first message)
threadId: string | null;

// Full conversation history
conversation: {
questionAnswerId: string;
question: string;
answer: string;
}[];
}

onAnswerGenerationCompleted

interface AnswerGenerationCompletedPayload {
// The question text
question: string;

// The generated answer
answer: string;

// ID of the QA pair
questionAnswerId: string;

// Current thread ID
threadId: string;

// Full conversation history
conversation: {
questionAnswerId: string;
question: string;
answer: string;
}[];
}

onAnswerGenerationStop

interface AnswerGenerationStopPayload {
// The question text
question: string;

// Current thread ID
threadId: string | null;

// Full conversation history
conversation: {
questionAnswerId: string;
question: string;
answer: string;
}[];
}

onConversationReset

interface ConversationResetPayload {
// Current thread ID
threadId: string | null;

// Full conversation history (before reset)
conversation: {
questionAnswerId: string;
question: string;
answer: string;
}[];
}

onFeedbackSubmit

interface FeedbackSubmitPayload {
// ID of the feedback
feedbackId: string;

// ID of the QA pair
questionAnswerId: string;

// User's reaction
reaction: "upvote" | "downvote";

// Optional user comment
comment?: {
incorrect?: boolean;
irrelevant?: boolean;
unaddressed?: boolean;
issue?: string;
};

// The question text
question: string;

// The answer text
answer: string;

// Current thread ID
threadId: string | null;

// Full conversation history
conversation: {
questionAnswerId: string;
question: string;
answer: string;
}[];
}

Integration examples

Google Analytics

import { KapaProvider } from "@kapaai/react-sdk";

function App() {
return (
<KapaProvider
integrationId="your-integration-id"
callbacks={{
askAI: {
onQuerySubmit: (data) => {
// Google Analytics 4 event
window.gtag("event", "ask_question", {
question: data.question,
thread_id: data.threadId,
});
},
onAnswerGenerationCompleted: (data) => {
window.gtag("event", "answer_generated", {
question_id: data.questionAnswerId,
answer_length: data.answer.length,
});
},
onFeedbackSubmit: (data) => {
window.gtag("event", "feedback_submitted", {
question_id: data.questionAnswerId,
reaction: data.reaction,
});
},
},
}}
>
<YourApplication />
</KapaProvider>
);
}

Segment

import { KapaProvider } from "@kapaai/react-sdk";

function App() {
return (
<KapaProvider
integrationId="your-integration-id"
callbacks={{
askAI: {
onQuerySubmit: (data) => {
window.analytics.track("AI Question Asked", {
question: data.question,
threadId: data.threadId,
});
},
onAnswerGenerationCompleted: (data) => {
window.analytics.track("AI Answer Generated", {
questionId: data.questionAnswerId,
question: data.question,
answerLength: data.answer.length,
});
},
onFeedbackSubmit: (data) => {
window.analytics.track("AI Feedback Submitted", {
questionId: data.questionAnswerId,
reaction: data.reaction,
hasComment: !!data.comment,
});
},
},
}}
>
<YourApplication />
</KapaProvider>
);
}

Custom backend

import { KapaProvider } from "@kapaai/react-sdk";

function App() {
const logEvent = async (eventName, eventData) => {
try {
await fetch("https://your-analytics-api.example.com/events", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
event: eventName,
timestamp: new Date().toISOString(),
userId: getCurrentUserId(), // Your user ID function
data: eventData,
}),
});
} catch (err) {
console.error("Failed to log event:", err);
}
};

return (
<KapaProvider
integrationId="your-integration-id"
callbacks={{
askAI: {
onQuerySubmit: (data) => {
logEvent("ai_question_asked", {
question: data.question,
threadId: data.threadId,
});
},
onAnswerGenerationCompleted: (data) => {
logEvent("ai_answer_generated", {
questionId: data.questionAnswerId,
question: data.question,
answer: data.answer,
});
},
},
}}
>
<YourApplication />
</KapaProvider>
);
}

User identification

For better analytics, you can provide user identification data by configuring the window.kapaSettings object:

// Set this before the KapaProvider is mounted
window.kapaSettings = {
user: {
email: "user@example.com",
uniqueClientId: "user-123",
metadata: {
companyName: "Acme Corp",
firstName: "Jane",
lastName: "Doe",
},
},
};

This information is sent along with queries to the Kapa backend and can be used for user-specific analytics.

Fingerprinting for anonymous analytics

For anonymous users, you can enable fingerprinting to generate consistent identifiers:

<KapaProvider
integrationId="your-integration-id"
fingerprintingEnabled={true}
callbacks={{...}}
>
<YourApplication />
</KapaProvider>

When enabled, the SDK generates a browser fingerprint and use it as an anonymous identifier.

Privacy considerations

When implementing analytics:

  1. Consent: Ensure you have user consent for tracking, especially in regions covered by GDPR, CCPA, etc.
  2. PII: Be careful with personally identifiable information in questions and answers.
  3. Fingerprinting: Make sure your privacy policy mentions fingerprinting if you enable this feature.
  4. Data Minimization: Only store what you need for your analytical purposes.

Debugging events

During development, you can log all events to the console:

<KapaProvider
integrationId="your-integration-id"
callbacks={{
askAI: {
onQuerySubmit: (data) => console.log("onQuerySubmit", data),
onAnswerGenerationCompleted: (data) =>
console.log("onAnswerGenerationCompleted", data),
onAnswerGenerationStop: (data) =>
console.log("onAnswerGenerationStop", data),
onConversationReset: (data) => console.log("onConversationReset", data),
onFeedbackSubmit: (data) => console.log("onFeedbackSubmit", data),
},
}}
>
<YourApplication />
</KapaProvider>

This helps verify that events are firing correctly and contain the expected data.