***
title: AI for Customers
icon: LuUsers
keywords: customer support AI, documentation search, content ingestion, UI components, chat integration, Slack integration, Discord integration, analytics dashboard, support tools, AI assistant, custom actions, API integration, self-serve support, technical documentation, knowledge base integration
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Use AI to help your users find what they need, get guidance on their scenarios, and have access to 24/7 troubleshooting help.
## Ingest your content
Ingest all of your customer-facing content with our out-of-box data connectors and scrapers.
**Supported Sources**
* Technical docs (Docusaurus, ReadMe, GitBook, Fumadocs, Mintlify, etc.)
* Help center and FAQs
* Website and blogs
* GitHub
* Community threads (Slack, Discord, and Discourse)
* Open API and GraphQL API specs
* Knowledge Bases (Notion, Confluence, Sharepoint, etc.)
* PDF, Markdown, CSV, and other files
* YouTube & other video sources
## Choose your UI
Pick the [UI components](/ui-components/overview) you'd like to add to your marketing site, docs, help center, or app.
Using the `@inkeep/cxkit-js` library.
Add a floating `Ask AI` chat button to any site or app.
Add to your docs or marketing site.
Use your own button or UI element to trigger the assistant UI.
Integrate an intelligent form to deflect new tickets.
Embed the chat directly in a dedicated standalone page.
Embed a search UI directly on a dedicated page.
Embed the chat in a sidebar on the left or right side of the page.
Using the `@inkeep/cxkit-react` library.
Add a floating `Ask AI` chat button to any site or app.
Add to your docs or marketing site.
Use your own button or UI element to trigger the assistant UI.
Integrate an intelligent form to deflect new tickets.
Embed the chat directly in a dedicated standalone page.
Embed a search UI directly on a dedicated page.
Embed the chat in a sidebar on the left or right side of the page.
## Add to your site
Follow a quickstart for your platform:
* [Docusaurus](/integrations/docusaurus/chat-button)
* [GitBook](/integrations/gitbook/chat-button)
* [ReadMe](/integrations/readme/chat-button)
* [Fumadocs](/integrations/fumadocs/chat-button)
* [Mintlify](/integrations/mintlify)
* [Next.js](/integrations/nextjs/chat-button)
* [Webflow](/integrations/webflow/chat-button)
* [Zendesk](/integrations/zendesk/help-center/chat-button)
* [HelpScout](/integrations/helpscout/chat-button)
* [Discourse](/integrations/discourse)
* [Framer](/integrations/framer/chat-button)
* [WordPress](/integrations/wordpress/chat-button)
* [Astro](/integrations/astro/chat-button)
* [Gatsby](/integrations/gatsby/chat-button)
* [Remix](/integrations/remix/chat-button)
* [Nextra](/integrations/nextra/chat-button)
* [VitePress](/integrations/vitepress/chat-button)
* [VuePress](/integrations/vuepress/chat-button)
* [Document360](/integrations/document360/chat-button)
* [Redocly](/integrations/redocly/api-docs/chat-button)
* [Sphinx](/integrations/sphinx/chat-button)
* [Hugo](/integrations/hugo/ananke)
* [Bettermode](/integrations/bettermode)
* [MkDocs](/integrations/mkdocs/chat-button)
* [Google Tag Manager](/integrations/google-tag-manager/chat-button)
* [Zudoku](/integrations/zudoku)
## Add to Slack or Discord
Add an `β¨ask-ai` channel or `@Ask AI` bot to:
A Slack workspace.
A Discord server.
## Monitor
Use our [dashboard](https://portal.inkeep.com) to monitor usage and close the feedback loop.
Get actionable reports on specific gaps in your documentation and monitor trending topics.
View all conversations and track thumbs up, down, and other stats.
## Tools and Actions
Add dynamic logic to your AI assistant.
Define custom functions available to the assistant.
Create support tickets, transfer to live chat, or book a sales call.
## AI APIs
Use our AI API to create custom experiences, including copilots or agents that can take product-specific actions ("tools") or be used in workflow automation tasks like form-filling. All powered with context about your product.
OpenAI-compatible Chat Completion API.
For Vercel AI SDK and OpenAI SDKs.
## Get started
Ready to use AI to improve your self-serve search and support experiences? [Try Inkeep on your content](https://inkeep.com/demo) or [Schedule a call](https://inkeep.com/schedule-demo).
***
title: AI for Support Teams
icon: PiHeadsetBold
keywords: support team AI, AI copilot, support automation, ticket deflection, auto-reply, Zendesk integration, Slack integration, support analytics, knowledge base management, AI assistant, support workflow, ticket routing, FAQ generation, support metrics, customer support tools, support team productivity, AI-powered support, support automation tools, support team efficiency
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
All the AI tools your support team needs to deliver fast, high-quality support.
## Tools for your team
### Support Copilot
Keep, our copilot for support teams, is a conversational AI sidekick that helps your team resolve tickets quickly.
Keep intelligently provides:
* Draft answers
* Relevant Sources
* Summaries
* To-dos
...and other relevant suggestions based on the context of a ticket.
Get started:
Install as a native app for Zendesk.
Use as a browser sidepane with any support platform.
### Slack Bot
Add the Inkeep Slack bot to your `#support-triage` or other internal channels where your team collaborates on customer questions.
Use Inkeep with:
Tag Inkeep to new or existing threads.
Have Inkeep automatically give suggestions on any new thread.
### Private Sources
Your internal-facing assistant can leverage private sources your customer-facing assistant can't.
This includes:
* Support tickets
* Slack conversations
* Internal KBs (Notion, Confluence, Google Drive, Sharepoint, etc.)
Use our out-of-box connectors to tap into any of these sources.
## Ticket Deflection
### AI Assistant
Use Inkeep's [customer-facing integrations](/overview/ai-for-customers) to embed an AI assistant anywhere users have questions: docs, help center, community, in-app and more.
### AI Support Forms
Inkeep AI knows when it can answer and when it needs to hand off to humans. Incorporate into your ticket creation process to deflect questions.
Provide an AI answer if confident and otherwise smartly categorize a new ticket.
Embed into the AI chat so a user can seamlessly escalate to human support.
### Auto-reply & Automations
Auto-reply to new support tickets, emails, GitHub issues, or forum posts only when confident using our APIs or integrations. Our APIs are OpenAI compatible, so can be easily integrated with any LLM frameworks.
Automatically respond to support tickets with AI-powered answers when confident.
{" "}
Have an AI agent handle livechats and handoff to your team when needed.
{" "}
Use and customize AI responses to auto-reply to any user question in any
channel.
Categorize tickets, pre-fill forms, and use custom tools to automate any support workflow.
## Close the Content Loop
Continuously improve your knowledge base and support content.
Get actionable reports on specific gaps in your documentation and monitor trending topics.
Automatically reformat closed tickets into private or public FAQs.
## Measure Impact
Track the effectiveness of your AI-powered support tools.
Monitor key metrics like deflection, documentation coverage, and π π.
Log chat events to your analytics tools and measure impact on your key metrics.
## Get started
Ready to use AI your support team and users can trust? [Schedule a call](https://inkeep.com/schedule-demo).
***
title: Developer Platform
sidebarTitle: Developer Platform
icon: LuCodeXml
keywords: developer platform, UI components, React components, JavaScript components, custom AI assistants, API integration, analytics API, RAG API, chat UI, search UI, form UI, CSS theming, custom instructions, tool calls, OpenAI compatibility, LLM framework, conversation logging, user feedback, developer tools
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Inkeep's developer-first primatives let you get started quickly while providing an extensible foundation for custom AI assistants and support automations.
## UI Component Library
Use `cxkit` React or JavaScript components to create custom search, chat, and form UIs.
### Components
Using the `@inkeep/cxkit-js` library.
Add a floating `Ask AI` chat button to any site or app.
Add to your docs or marketing site.
Use your own button or UI element to trigger the assistant UI.
Integrate an intelligent form to deflect new tickets.
Embed the chat directly in a dedicated standalone page.
Embed a search UI directly on a dedicated page.
Embed the chat in a sidebar on the left or right side of the page.
Using the `@inkeep/cxkit-react` library.
Add a floating `Ask AI` chat button to any site or app.
Add to your docs or marketing site.
Use your own button or UI element to trigger the assistant UI.
Integrate an intelligent form to deflect new tickets.
Embed the chat directly in a dedicated standalone page.
Embed a search UI directly on a dedicated page.
Embed the chat in a sidebar on the left or right side of the page.
### Customize
Customize the UI components to match your brand and embed in a way that feels native to your product or end-user experiences.
Customize theme tokens used and customize with semantic class names.
{" "}
Add user-specific information and custom guidance with dynamic prompts.
Trigger your own app logic and add dynamic interactions to the chat.
Create support tickets right from the chat.
## AI API
Build custom agents, auto-replies, and workflows with programmatic access to your knowledge base. All APIs follow the OpenAI Chat Completions format, so you can use the APIs with any LLM framework or observability tools.
Optimized for customer-facing support scenarios and auto-replies.
{" "}
Add dynamic functionality based on user requests.
{" "}
Use tools and structured outputs that leverage your knowledge base context.
Use Inkeep's RAG API or MCP server to get relevant content for any LLM app.
## Analytics API
When building your own AI assistant UI or user experience, use the analytics API to log and monitor all conversations, feedback, and usage events.
Log custom conversations or AI chats to the Inkeep analytics system.
Capture user feedback on responses.
Log custom events and user interactions.
Query and analyze all analytics data.
## Get started
Ready to build with Inkeep? [Schedule a call](https://inkeep.com/schedule-demo) with our team to get recommendations on your specific scenario.
***
title: Why Inkeep?
icon: LuStar
keywords: AI support, generative AI, RAG, retrieval augmented generation, conversational AI, customer support, knowledge base, content ingestion, neural search, hallucination prevention, enterprise support, self-serve support, semantic search, LLM, machine learning
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Quality
Our #1 goal is to help our customers ship AI support experiences to their users with confidence.
For us, quality means developing our AI solution to:
* Admit when it doesn't know and intelligently guide users to support channels
* Consistently find the right content and not hallucinate
* Provide rich citations that help users inspect answers
* Leverage many sources while prioritizing authoritative content
It also means providing the end-to-end tooling needed for the entire support lifecycle. Beyond customer-facing AI assistants, Inkeep provides a [copilot for support team members](https://inkeep.com/blog/copilot-for-support-teams) and [actionable reporting](/analytics/content-gaps) for content and product teams.
We built our product and [team](https://inkeep.com/team) to deliver best-in-class experiences for each of these steps.
That said - don't take our word for it! Use our [free trial](https://inkeep.com/demo-form) to test Inkeep with your toughest questions.
## Hands-on Support
Quality for us also means working closely with any team we work to accomplish their goals. Consider us a partner who will work with you every step of the way.
Reach us over email, Slack, Discord, or Teams.
Dedicated onboarding, support, and SLAs.
## Technical Deep Dive β¨
In our journey, we've talked to hundreds of companies who are eager to use generative AI to provide better self-serve experiences for their users. Many of them had experimented with creating their own LLM Q\&A apps or tried other services, but often didn't ship because they felt the quality and reliability weren't there.
### Ingesting content from many sources
Knowledge about technical products often lives in many places: documentation, GitHub, forums, Slack and Discord channels, blogs, StackOverflow, support systems, and elsewhere. Smartly ingesting all of this content, and keeping it up to date over time, quickly becomes the full-time task of a team of data engineers.
Inkeep addresses this by:
* Automatically ingesting content from common public and private content sources with out-of-the-box integrations (while prioritizing them appropriately)
* Frequently re-crawling your sources to find differences and keep your knowledge base up to date.
### Finding the most relevant content
[Retrieval augmented generation (RAG)](https://arxiv.org/abs/2005.11401) is the best way to use LLMs to answer questions regarding domain-specific content. At a high level, it involves taking a user question, finding the most relevant content, and feeding it to an LLM model.
RAG relies on finding the relevant documents and "chunks" within those documents needed to answer user questions. The problem is, popular ways of doing retrieval - like slicing up all content into `n`-character chunks - are often arbitrary and ineffective.
Retrieval becomes even more challenging as the number of documents and sources increase. More content can mean higher coverage of user questions, but often also means more noise and the need for a precise retrieval system.
Our retrieval and neural search engines address this by using:
* Accounting for **time**, **author**, **source type**, **and other metadata** that's important for prioritizing trustworthy content.
* **Custom embedding and chunking strategies** for each content source. The most effective embedding and chunking strategy for a Slack conversation is very different from one for a "How-to" article.
* **Neural search** that combines semantic and keyword search to balance vector similarity and keyword matching.
* **Tailoring of the embedding space** to your specific organization and content. Out-of-the-box embedding models don't account for what we call the "semantic space" of your company and your products. For example, "Retrieval system" is much closer in semantic meaning to "Feature" for Inkeep than for other companies.
* ...and more.
If you're curious about our technical approach, join [our newsletter](https://inkeep.typeform.com/to/IgrltCbO?utm_source=why_inkeep_article) where we share product updates and engineering deep-dives.
### Minimizing hallucinations
Conversational large language models are trained to provide satisfying answers to users. Unfortunately, this makes them prone to providing answers that are unsubstantiated, i.e. "hallucinating". Dealing with hallucinations is notoriously difficult and a common blocker for many companies.
Here are some of the key ways in which we minimize hallucinations with our grounded-answer system:
1. **Retrieving the right content** - When models are not given content that helps them answer a question, they are significantly more likely to hallucinate. That's in part why we focus so heavily on our search and retrieval engines.
2. **Providing citations** - Citations give end-users easy ways to learn more and introspect answers. We include rich citations in our UI to make it easy to compare reference content and use citations to automatically evaluate, alert, and fix drift from source material.
3. **Staying on topic** - We've implemented a variety of protections to keep model answers on topic. For example, the bot won't answer questions unrelated to your company and will guard against giving answers that create a poor perception of your product.
4. **Rapidly experimenting at scale** - We continuously test and evaluate our entire retrieval and LLM-stack against both historical and new user questions. This allows us to identify and adopt new techniques while monitoring for regressions.
### Incorporating feedback
Even with a best-in-class retrieval and grounded-answer system, feedback loops are the key to continuous improvement of model performance over time.
Our platform has built-in mechanisms for this, including:
* Thumbs up/down feedback from end-users
* "Edit answer" feature for administrators
* The ability to batch test a set of test questions
* Custom FAQs
We also provide usage, topical, and sentiment analysis on all user questions. Product and content teams often use these insights to prioritize content creation and product improvements that address root causes of user questions.
### Production-ready service
To launch something confidently to end-users, it's essential to have:
* High availability, geo-distributed, low latency search and chat services
* API and UX monitoring
* Continuous evaluation of search and chat results
Our platform already handles this at scale and answers hundreds of thousands of questions per month.
## The Team
Our [team](https://inkeep.com/team) is made up of engineers passionate about machine learning, data engineering, and user experiences. We're excited to solve the challenges in this space and help companies provide the best self-serve support and search experiences possible to their users.
We're fortunate to have the backing of reputable investors, including [Y Combinator](https://www.ycombinator.com/launches/IAP-inkeep-conversational-search-for-your-developer-product) and [Khosla Ventures](https://www.khoslaventures.com/).
***
title: Privacy
description: How Inkeep protects your data.
icon: LuLock
keywords: data privacy, SOC 2 compliance, data protection, LLM privacy, AI data security, data retention, HIPAA compliance, user privacy, data processing, security controls, enterprise security, data governance, privacy policy, data collection, user data protection, information security, privacy controls, data handling, security compliance
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
We know that privacy and security are critical for many organizations. Inkeep is committed to protecting your organization's and your users' data and privacy.
Inkeep is **SOC 2 Type II compliant**. We use industry-standard security practices, reputable subprocessors with SOC 2 Type II compliance, and offer controls to help organizations meet their own data protection and privacy requirements. We follow security best practices, including regular external security reviews and penetration tests.
## Use of LLMs
To provide our search and chat services, we use foundational large language models (LLMs) and artificial intelligence (AI) services from the following providers:
* [Anthropic](https://legal.anthropic.com)
* [Azure OpenAI](https://learn.microsoft.com/en-us/legal/cognitive-services/openai/data-privacy)
* [OpenAI](https://openai.com/policies/api-data-usage-policies)
Inkeep and our providers will never use your data to train AI or LLM models.
See the links above for details of each provider's policies.
## Custom Controls
For enterprise customers with strict data protection requirements, we offer:
* Custom retention period of conversations, including no-retention.
* Choice of which LLM or vector database provider is used.
* Data de-identification services (powered by Google Cloud's Sensitive Data Protection).
* Role-based access control to limit who can view your conversations logs.
* Restricting end-user access of AI functions to authenticated users only.
* A HIPAA Business Associate Agreement (BAA)
We will work with your legal and security teams to work with your requirements. We will review with them our service agreement, data processing agreement, security policies, and other relevant documents.
This article is provided solely for general informational purposes and does
not create or constitute contractual obligations, rights, or warranties
between you and Inkeep. Refer to your organization's Service Agreement, Data
Processing Agreement (if applicable), and our [Privacy
Policy](https://privacy.inkeep.com/privacy-policy) for details on your
relationship with Inkeep. For any questions, please contact
[privacy@inkeep.com](mailto:privacy@inkeep.com?subject=Inkeep%20Privacy%20Question).
## Categories of Individuals
We distinguish between:
* **Users:** Your end users or customers who interact with the platform.
* **Customer Agents:** Your employees or consultants authorized to access and manage the platform.
## Categories of Collected Data
### Knowledge Base Documents
**Knowledge Base Documents** are materials or data sources you provide to Inkeep for ingestion into the platform. They may include:
* Technical documentation
* Website content and blogs
* Sources with end-user generated content (e.g., StackOverflow, GitHub, Discourse, Slack, Discord)
* Support desk tickets and FAQs
* Internal documents
These documents are considered **Customer Data**, which you control and can view or delete at any time. This data is used to power the AI Functions for your (and only your) organization.
### Prompts and Responses
* **Prompts:** The text or input provided by Users or Customer Agents to the AI functions (e.g. search and chat services). Prompts are a form of **User Content**, which is a subset of Customer Data.
* **Responses:** The text or output generated by the platform's AI functions in reply to a Prompt. Responses are referred to as **Output**.
We retain Prompts (User Content) and Responses (Output) for:
1. **Usage Analytics:** Providing authorized Customer Agents with topical, sentiment, and other analytics.
2. **End User Functionality:** Enabling features like thumbs-up/down feedback, "Share chat," and conversation history.
3. **Abuse and Misuse Monitoring**
4. **Service Improvements:** Monitoring and improving the quality of our services, without using your data to train AI models.
Enterprise Customers can customize the below:
* Retention period of Prompts
* Enabling or disabling of Usage Analytics or End User Functionality
### User Metadata
**User Metadata** may include identifying information such as IP addresses, browser session details, or other user-related identifiers you or your Users choose to provide. This data is considered a subset of Customer Data. You can configure what User Metadata is collected and whether it is associated with Prompts and Responses.
You can customize and opt out of the collection of User Metadata. See
[here](/ui-components/common-settings/base) for instructions on configuring
Inkeep's web widgets.
### Usage Data
We collect **Usage Data**βsuch as technical logs, performance metrics, and other non-Customer Data related to platform usageβto help troubleshoot, measure, and improve the performance and availability of our services.
## Contacting Us
If you have a data request or questions about our use of data and processing, please reach out to [privacy@inkeep.com](mailto:privacy@inkeep.com?subject=Inkeep%20Privacy%20Question).
If you are aware of an information security incident, unauthorized access, policy violation, security weakness, or suspicious activity related to Inkeep, please send an email with any relevant details to [incidents@inkeep.com](mailto:incidents@inkeep.com).
***
title: Add Chat Button to Docusaurus
description: Integrate Inkeep's chat button into your Docusaurus documentation for real-time user assistance.
keywords: Docusaurus chat, React integration, documentation chat, Docusaurus customization, chat implementation, documentation enhancement, chat configuration, Docusaurus setup, React components, user assistance, MDX integration
sidebarTitle: Chat Button
-------------------------
## What is Docusaurus
[Docusaurus](https://docusaurus.io/) is an open-source documentation platform powered by MDX and React.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Install the Inkeep plugin
```bash
npm install @inkeep/cxkit-docusaurus
```
```bash
bun add @inkeep/cxkit-docusaurus
```
```bash
pnpm add @inkeep/cxkit-docusaurus
```
```bash
yarn add @inkeep/cxkit-docusaurus
```
## Define the widget
Add the chat button as a plugin in your `docusaurus.config.js` file:
```js title="docusaurus.config.js"
plugins: ["@inkeep/cxkit-docusaurus"],
```
### Configuration settings
You have two configuration options:
1. Configure the widget in the plugin `options`. Use this option if you are loading your apiKey from an environment variable, see [here](https://docusaurus.io/docs/deployment#using-environment-variables) for more information.
2. Configure the widget in standalone `config`. Use this option if you are using any callback functions (like `transformSource`, `onEvent`, or `getTools`) in your config.
These options can also be used together and the settings will be merged automatically.
#### Configure the widget in the plugin `options`
Docusaurus plugins can accept a tuple of `[pluginName, options]`.
In this case, the plugin name is `@inkeep/cxkit-docusaurus`.
Note that if you are using any callback functions (like `transformSource`, `onEvent`, or `getTools`) in your config, you will need to use the [standalone config](#configure-the-widget-in-standalone-config) to pass those settings.
So use like this:
You will need to replace `REPLACE_WITH_YOUR_INKEEP_API_KEY` with your actual
Inkeep API key in the code below.
```js title="docusaurus.config.js"
plugins: [
["@inkeep/cxkit-docusaurus", {
ChatButton: {
baseSettings: {
// see https://docusaurus.io/docs/deployment#using-environment-variables to use docusaurus environment variables
apiKey: "REPLACE_WITH_YOUR_INKEEP_API_KEY", // required - replace with your own API key
primaryBrandColor: "#26D6FF", // required -- your brand color, the widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
theme: {
// optional path to a custom stylesheet
styles: [
{
key: "main",
type: "link",
value: "/path/to/stylesheets",
},
],
syntaxHighlighter: {
lightTheme: lightCodeTheme, // optional -- pass in the Prism theme you're using
darkTheme: darkCodeTheme, // optional -- pass in the Prism theme you're using
},
}
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // optional -- use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
}
}],
],
```
#### Configure the widget in standalone `config`
In this case, the plugin name is `@inkeep/cxkit-docusaurus/chatButton`.
What this means is that you create a config file in your project. By default, you can create an `inkeep.config.js` or `inkeep.config.ts` file in the root of your project, and Inkeep will automatically pick it up.
```js title="inkeep.config.js"
window.inkeepConfig = {
ChatButton: {
// ...options
},
};
```
You can customize the path to the config file in the plugin options:
```js title="docusaurus.config.js"
plugins: [
["@inkeep/cxkit-docusaurus", { config: "./path/to/my-inkeep-config.js" }],
],
```
We also export a fully typed `defineConfig` function that you can use to create your config:
```js title="inkeep.config.js"
import { defineConfig } from "@inkeep/cxkit-docusaurus";
export default defineConfig({
ChatButton: {
// ...options
},
});
```
```js title="inkeep.config.js"
const { defineConfig } = require("@inkeep/cxkit-docusaurus");
module.exports = defineConfig({
ChatButton: {
// ...options
},
});
```
For a full list of customizations, check out the [Common Settings](/ui-components/common-settings).
### FAQ
We support docusaurus versions `2.0.1` and above.
Our plugin swizzles the `SearchBar` component. If you have a plugin that
also swizzles the `SearchBar` component, you need to ensure that plugin comes after our plugin in your `docusaurus.config.js` file.
This way, your custom `SearchBar` will override our default one.
To add custom styles to the Inkeep widget in your Docusaurus site, first create a CSS file in your `static` directory (e.g. `static/inkeep-overrides.css`). Then specify the URL of the stylesheet in the `styles` array within the `theme` object (inside of `baseSettings`).
For example, if you created a file at `static/inkeep-overrides.css`, you should set the `styles` array to:
```js
theme: {
styles: [
{
key: "main",
type: "link",
value: "/inkeep-overrides.css",
},
],
},
```
For additional details on how Docusaurus manages static assets, please refer to the [official documentation](https://docusaurus.io/docs/static-assets).
```js title="docusaurus.config.js"
//..
SearchBar: {
// ... rest of your settings
baseSettings: {
// ... rest of your baseSettings
theme: {
styles: [
{
key: "main",
type: "link",
value: "/inkeep-overrides.css",
},
],
},
},
},
```
If you need more control or customizations, you can use the React components directly. To do so, follow the react guides: [chat button](/ui-components/react/chat-button), [search bar](/ui-components/react/search-bar), [embedded chat](/ui-components/react/in-page/embedded-chat), [custom modal trigger](/ui-components/react/custom-modal-trigger).
A few things to keep in mind:
* If using Docusaurus 3.4.0 you will need to load the Inkeep widget component dynamically and wrap it in a `` [tag](https://docusaurus.io/docs/advanced/ssg#browseronly). For example:
```js
import React, { useEffect, useState } from "react";
import BrowserOnly from "@docusaurus/BrowserOnly";
export default function Widget() {
const [isOpen, setIsOpen] = useState(false);
const [ModalSearchAndChat, setModalSearchAndChat] = useState(null);
useEffect(() => {
(async () => {
const { InkeepModalSearchAndChat } = await import("@inkeep/cxkit-react");
setModalSearchAndChat(() => InkeepModalSearchAndChat);
})();
}, []);
const inkeepModalSearchAndChatProps = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // required -- your brand color, the widget color scheme is derived from this
organizationDisplayName: "Inkeep",
},
modalSettings: {
isOpen,
onOpenChange: handleOpenChange,
},
};
};
return (
<>
{
setIsOpen(true);
}}
>
Ask AI
}>
{() => {
return (
ModalSearchAndChat &&
);
}}
>
);
}
```
* If using the ChatButton component, you can create a `Footer.js` in the `themes` directory then import the original Footer component and add the Chat Button so that it will be present on each page. For example:
```js
import Footer from "@theme-original/Footer";
import React, { useEffect, useState } from "react";
import BrowserOnly from "@docusaurus/BrowserOnly";
export default function FooterWrapper(props) {
const [ChatButton, setChatButton] = useState(null);
useEffect(() => {
(async () => {
const { InkeepChatButton } = await import("@inkeep/cxkit-react");
setChatButton(() => InkeepChatButton);
})();
}, []);
const InkeepChatButtonProps = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // required -- your brand color, the widget color scheme is derived from this
organizationDisplayName: "Inkeep",
},
};
return (
<>
}>
{() => {
return ChatButton && ;
}}
>
);
}
```
***
title: Add Search Bar to Docusaurus
description: Integrate Inkeep's search bar into your Docusaurus documentation for powerful content discovery.
keywords: Docusaurus search, React search, documentation search, Docusaurus customization, search implementation, documentation enhancement, search configuration, Docusaurus setup, React components, content discovery, MDX integration
sidebarTitle: Search Bar
------------------------
## What is Docusaurus
[Docusaurus](https://docusaurus.io/) is an open-source documentation platform powered by MDX and React.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Install the Inkeep plugin
```bash
npm install @inkeep/cxkit-docusaurus
```
```bash
bun add @inkeep/cxkit-docusaurus
```
```bash
pnpm add @inkeep/cxkit-docusaurus
```
```bash
yarn add @inkeep/cxkit-docusaurus
```
## Define the widget
Add the search bar as a plugin in your `docusaurus.config.js` file:
```js title="docusaurus.config.js"
plugins: ["@inkeep/cxkit-docusaurus"],
```
If you are already using `Algolia DocSearch` provided by Docusaurus by
default, it will be replaced by our widget.
### Configuration settings
You have two configuration options:
1. Configure the widget in the plugin `options`. Use this option if you are loading your apiKey from an environment variable, see [here](https://docusaurus.io/docs/deployment#using-environment-variables) for more information.
2. Configure the widget in standalone `config`. Use this option if you are using any callback functions (like `transformSource`, `onEvent`, or `getTools`) in your config.
These options can also be used together and the settings will be merged automatically.
#### Configure the widget in the plugin `options`
Docusaurus plugins can accept a tuple of `[pluginName, options]`.
In this case, the plugin name is `@inkeep/cxkit-docusaurus`.
Note that if you are using any callback functions (like `transformSource`, `onEvent`, or `getTools`) in your config, you will need to use the [standalone config](#configure-the-widget-in-standalone-config) to pass those settings.
So use like this:
You will need to replace `REPLACE_WITH_YOUR_INKEEP_API_KEY` with your actual
Inkeep API key in the code below.
```js title="docusaurus.config.js"
plugins: [
["@inkeep/cxkit-docusaurus", {
SearchBar: {
baseSettings: {
// see https://docusaurus.io/docs/deployment#using-environment-variables to use docusaurus environment variables
apiKey: "REPLACE_WITH_YOUR_INKEEP_API_KEY", // required - replace with your own API key
primaryBrandColor: "#26D6FF", // required -- your brand color, the widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
theme: {
// optional path to a custom stylesheet
styles: [
{
key: "main",
type: "link",
value: "/path/to/stylesheets",
},
],
syntaxHighlighter: {
lightTheme: lightCodeTheme, // optional -- pass in the Prism theme you're using
darkTheme: darkCodeTheme, // optional -- pass in the Prism theme you're using
},
}
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // optional -- use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
}
}],
],
```
#### Configure the widget in standalone `config`
In this case, the plugin name is `@inkeep/cxkit-docusaurus`.
What this means is that you create a config file in your project. By default, you can create an `inkeep.config.js` or `inkeep.config.ts` file in the root of your project, and Inkeep will automatically pick it up.
```js title="inkeep.config.js"
window.inkeepConfig = {
SearchBar: {
// ...options
},
};
```
You can customize the path to the config file in the plugin options:
```js title="docusaurus.config.js"
plugins: [
["@inkeep/cxkit-docusaurus", { config: "./path/to/my-inkeep-config.js" }],
],
```
We also export a fully typed `defineConfig` function that you can use to create your config:
```js title="inkeep.config.js"
import { defineConfig } from "@inkeep/cxkit-docusaurus";
export default defineConfig({
SearchBar: {
// ...options
},
});
```
```js title="inkeep.config.js"
const { defineConfig } = require("@inkeep/cxkit-docusaurus");
module.exports = defineConfig({
SearchBar: {
// ...options
},
});
```
For a full list of customizations, check out the [Common Settings](/ui-components/common-settings).
If you have already created a custom `SearchBar` component (for example via
`swizzle eject`) this will need to be removed in order to use our Search Bar.
### FAQ
We support docusaurus versions `2.0.1` and above.
Our plugin swizzles the `SearchBar` component. If you have a plugin that
also swizzles the `SearchBar` component, you need to ensure that plugin comes after our plugin in your `docusaurus.config.js` file.
This way, your custom `SearchBar` will override our default one.
To add custom styles to the Inkeep widget in your Docusaurus site, first create a CSS file in your `static` directory (e.g. `static/inkeep-overrides.css`). Then specify the URL of the stylesheet in the `styles` array within the `theme` object (inside of `baseSettings`).
For example, if you created a file at `static/inkeep-overrides.css`, you should set the `styles` array to:
```js
theme: {
styles: [
{
key: "main",
type: "link",
value: "/inkeep-overrides.css",
},
],
},
```
For additional details on how Docusaurus manages static assets, please refer to the [official documentation](https://docusaurus.io/docs/static-assets).
```js title="docusaurus.config.js"
//..
SearchBar: {
// ... rest of your settings
baseSettings: {
// ... rest of your baseSettings
theme: {
styles: [
{
key: "main",
type: "link",
value: "/inkeep-overrides.css",
},
],
},
},
},
```
If you need more control or customizations, you can use the React components directly. To do so, follow the react guides: [chat button](/ui-components/react/chat-button), [search bar](/ui-components/react/search-bar), [embedded chat](/ui-components/react/in-page/embedded-chat), [custom modal trigger](/ui-components/react/custom-modal-trigger).
A few things to keep in mind:
* If using Docusaurus 3.4.0 you will need to load the Inkeep widget component dynamically and wrap it in a `` [tag](https://docusaurus.io/docs/advanced/ssg#browseronly). For example:
```js
import React, { useEffect, useState } from "react";
import BrowserOnly from "@docusaurus/BrowserOnly";
export default function Widget() {
const [isOpen, setIsOpen] = useState(false);
const [ModalSearchAndChat, setModalSearchAndChat] = useState(null);
useEffect(() => {
(async () => {
const { InkeepModalSearchAndChat } = await import("@inkeep/cxkit-react");
setModalSearchAndChat(() => InkeepModalSearchAndChat);
})();
}, []);
const inkeepModalSearchAndChatProps = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // required -- your brand color, the widget color scheme is derived from this
organizationDisplayName: "Inkeep",
},
modalSettings: {
isOpen,
onOpenChange: handleOpenChange,
},
};
};
return (
<>
{
setIsOpen(true);
}}
>
Ask AI
}>
{() => {
return (
ModalSearchAndChat &&
);
}}
>
);
}
```
* If using the ChatButton component, you can create a `Footer.js` in the `themes` directory then import the original Footer component and add the Chat Button so that it will be present on each page. For example:
```js
import Footer from "@theme-original/Footer";
import React, { useEffect, useState } from "react";
import BrowserOnly from "@docusaurus/BrowserOnly";
export default function FooterWrapper(props) {
const [ChatButton, setChatButton] = useState(null);
useEffect(() => {
(async () => {
const { InkeepChatButton } = await import("@inkeep/cxkit-react");
setChatButton(() => InkeepChatButton);
})();
}, []);
const InkeepChatButtonProps = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // required -- your brand color, the widget color scheme is derived from this
organizationDisplayName: "Inkeep",
},
};
return (
<>
}>
{() => {
return ChatButton && ;
}}
>
);
}
```
***
title: Add Chat and Search to Docusaurus
description: Integrate Inkeep's chat button and search bar into your Docusaurus documentation for enhanced user experience.
keywords: Docusaurus integration, chat and search, React integration, Docusaurus customization, combined integration, chat implementation, search implementation, documentation enhancement, React components, UI integration, MDX integration
sidebarTitle: Chat Button & Search Bar
--------------------------------------
## What is Docusaurus
[Docusaurus](https://docusaurus.io/) is an open-source documentation platform powered by MDX and React.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Install the Inkeep plugin
```bash
npm install @inkeep/cxkit-docusaurus
```
```bash
bun add @inkeep/cxkit-docusaurus
```
```bash
pnpm add @inkeep/cxkit-docusaurus
```
```bash
yarn add @inkeep/cxkit-docusaurus
```
If you are already using `Algolia DocSearch` provided by Docusaurus by
default, it will be replaced by our widget.
### Configuration settings
You have two configuration options:
1. Configure the widget in the plugin `options`. Use this option if you are loading your apiKey from an environment variable, see [here](https://docusaurus.io/docs/deployment#using-environment-variables) for more information.
2. Configure the widget in standalone `config`. Use this option if you are using any callback functions (like `transformSource`, `onEvent`, or `getTools`) in your config.
These options can also be used together and the settings will be merged automatically.
#### Configure the widget in the plugin `options`
Docusaurus plugins can accept a tuple of `[pluginName, options]`.
In this case, the plugin name is `@inkeep/cxkit-docusaurus`.
Note that if you are using any callback functions (like `transformSource`, `onEvent`, or `getTools`) in your config, you will need to use the [standalone config](#configure-the-widget-in-standalone-config) to pass those settings.
So use like this:
You will need to replace `REPLACE_WITH_YOUR_INKEEP_API_KEY` with your actual
Inkeep API key in the code below.
```js title="docusaurus.config.js"
const inkeepConfig = {
baseSettings: {
// see https://docusaurus.io/docs/deployment#using-environment-variables to use docusaurus environment variables
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // required -- your brand color, the widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
theme: {
// optional path to a custom stylesheet
styles: [
{
key: "main",
type: "link",
value: "/path/to/stylesheets",
},
],
syntaxHighlighter: {
lightTheme: lightCodeTheme, // optional -- pass in the Prism theme you're using
darkTheme: darkCodeTheme, // optional -- pass in the Prism theme you're using
},
}
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // optional -- use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
}
plugins: [
["@inkeep/cxkit-docusaurus", {
SearchBar: {
...inkeepConfig,
},
ChatButton: {
...inkeepConfig,
},
}],
],
```
#### Configure the widget in standalone `config`
In this case, the plugin name is `@inkeep/cxkit-docusaurus`.
What this means is that you create a config file in your project. By default, you can create an `inkeep.config.js` or `inkeep.config.ts` file in the root of your project, and Inkeep will automatically pick it up.
```js title="inkeep.config.js"
window.inkeepConfig = {
SearchBar: {
// ...options
},
ChatButton: {
// ...options
},
};
```
You can customize the path to the config file in the plugin options:
```js title="docusaurus.config.js"
plugins: [
["@inkeep/cxkit-docusaurus", { config: "./path/to/my-inkeep-config.js" }],
],
```
We also export a fully typed `defineConfig` function that you can use to create your config:
```js title="inkeep.config.js"
import { defineConfig } from "@inkeep/cxkit-docusaurus";
export default defineConfig({
SearchBar: {
// ...options
},
ChatButton: {
// ...options
},
});
```
```js title="inkeep.config.js"
const { defineConfig } = require("@inkeep/cxkit-docusaurus");
module.exports = defineConfig({
SearchBar: {
// ...options
},
ChatButton: {
// ...options
},
});
```
For a full list of customizations, check out the [Common Settings](/ui-components/common-settings).
If you have already created a custom `SearchBar` component (for example via
`swizzle eject`) this will need to be removed in order to use our Search Bar.
### FAQ
We support docusaurus versions `2.0.1` and above.
Our plugin swizzles the `SearchBar` component. If you have a plugin that
also swizzles the `SearchBar` component, you need to ensure that plugin comes after our plugin in your `docusaurus.config.js` file.
This way, your custom `SearchBar` will override our default one.
To add custom styles to the Inkeep widget in your Docusaurus site, first create a CSS file in your `static` directory (e.g. `static/inkeep-overrides.css`). Then specify the URL of the stylesheet in the `styles` array within the `theme` object (inside of `baseSettings`).
For example, if you created a file at `static/inkeep-overrides.css`, you should set the `styles` array to:
```js
theme: {
styles: [
{
key: "main",
type: "link",
value: "/inkeep-overrides.css",
},
],
},
```
For additional details on how Docusaurus manages static assets, please refer to the [official documentation](https://docusaurus.io/docs/static-assets).
```js title="docusaurus.config.js"
//..
SearchBar: {
// ... rest of your settings
baseSettings: {
// ... rest of your baseSettings
theme: {
styles: [
{
key: "main",
type: "link",
value: "/inkeep-overrides.css",
},
],
},
},
},
```
If you need more control or customizations, you can use the React components directly. To do so, follow the react guides: [chat button](/ui-components/react/chat-button), [search bar](/ui-components/react/search-bar), [embedded chat](/ui-components/react/in-page/embedded-chat), [custom modal trigger](/ui-components/react/custom-modal-trigger).
A few things to keep in mind:
* If using Docusaurus 3.4.0 you will need to load the Inkeep widget component dynamically and wrap it in a `` [tag](https://docusaurus.io/docs/advanced/ssg#browseronly). For example:
```js
import React, { useEffect, useState } from "react";
import BrowserOnly from "@docusaurus/BrowserOnly";
export default function Widget() {
const [isOpen, setIsOpen] = useState(false);
const [ModalSearchAndChat, setModalSearchAndChat] = useState(null);
useEffect(() => {
(async () => {
const { InkeepModalSearchAndChat } = await import("@inkeep/cxkit-react");
setModalSearchAndChat(() => InkeepModalSearchAndChat);
})();
}, []);
const inkeepModalSearchAndChatProps = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // required -- your brand color, the widget color scheme is derived from this
organizationDisplayName: "Inkeep",
},
modalSettings: {
isOpen,
onOpenChange: handleOpenChange,
},
};
};
return (
<>
{
setIsOpen(true);
}}
>
Ask AI
}>
{() => {
return (
ModalSearchAndChat &&
);
}}
>
);
}
```
* If using the ChatButton component, you can create a `Footer.js` in the `themes` directory then import the original Footer component and add the Chat Button so that it will be present on each page. For example:
```js
import Footer from "@theme-original/Footer";
import React, { useEffect, useState } from "react";
import BrowserOnly from "@docusaurus/BrowserOnly";
export default function FooterWrapper(props) {
const [ChatButton, setChatButton] = useState(null);
useEffect(() => {
(async () => {
const { InkeepChatButton } = await import("@inkeep/cxkit-react");
setChatButton(() => InkeepChatButton);
})();
}, []);
const InkeepChatButtonProps = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // required -- your brand color, the widget color scheme is derived from this
organizationDisplayName: "Inkeep",
},
};
return (
<>
}>
{() => {
return ChatButton && ;
}}
>
);
}
```
***
title: Add Chat Button to GitBook
description: Integrate Inkeep's chat button into your GitBook documentation for real-time user assistance.
keywords: GitBook integration, chat button, documentation chat, GitBook customization, chat implementation, documentation enhancement, chat configuration, GitBook setup, knowledge base chat, user assistance, documentation tools
sidebarTitle: Chat Button
-------------------------
## What is GitBook
[GitBook](https://www.gitbook.com/) is a static site generator for docs.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
### Find your organizationId and integrationId
#### To find your `organizationId`:
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Go to the **Settings** tab (under the **Organization** heading)
3. Copy the `ID` field
#### To find your `integrationId`:
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Select your project under **Projects**
3. Go to the **Assistants** tab
4. Select your assistant
5. Copy the `ID` field
## Installing widget for your website
1. Navigate to [GitBook](https://app.gitbook.com/integrations/inkeep)
2. Click **Install**
3. After installation, navigate to **Docs sites** tab and enable the widget for your desired site
## Initialize the widget
Navigate to the **Configuration** tab to customize your settings.
The **Base Widget Setting** is required for the widget to function.
Your configuration should resemble the example below:
```json title="baseSettings"
{
"apiKey": "INKEEP_API_KEY",
"integrationId": "INKEEP_INTEGRATION_ID",
"organizationId": "INKEEP_ORGANIZATION_ID",
"primaryBrandColor": "#26D6FF",
"organizationDisplayName": "Inkeep"
}
```
Once the configuration is applied, the widget will appear on the site you enabled the widget for. If the configuration is not applied, you may also need to edit the **Chat Button Type** field in order for Gitbook to recognize that configuration is complete (you can just remove the last letter and re-add it to trigger a refresh).
Gitbook caches this configuration so if you edit the configuration settings it may take some time for the new settings to take effect, you may try "re-saving" the configuration a couple of times to force a refresh.
For a full list of customizations, check out the [Chat Button](https://legacy-docs.inkeep.com/integrations/gitbook/chat-button) documentation.
Our Gitbook integration is currently using an older version of our widget, we are working on updating it to the latest version. Some of the configuration options found in these docs may not be available, but the relevant configuration options can be found [here](https://legacy-docs.inkeep.com/ui-components/common-settings/base).
***
title: Add Chat Button to ReadMe
description: Add Inkeep's chat button to your ReadMe documentation.
keywords: ReadMe integration, chat button, documentation chat, ReadMe customization, chat implementation, documentation enhancement, chat configuration, ReadMe setup, chat integration, docs improvement
sidebarTitle: Chat Button
-------------------------
## What is ReadMe
[ReadMe](https://readme.com/) is a platform for creating documentation.
This integration requires a ReadMe [Business plan](https://readme.com/pricing) or higher, as it relies on custom HTML.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Navigate to **Appearance** of the project settings
2. Open the **Custom Include Tags** tab
3. Add the below code to the **HEAD HTML** section
```html
```
## Initialize the widget
Next, in the **FOOTER HTML** section add the below code to add the chat button widget:
```html
```
Press **Save** to apply your changes.
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Search Bar to ReadMe
description: Add Inkeep's search bar to your ReadMe documentation.
keywords: ReadMe search, documentation search, search integration, ReadMe customization, search implementation, documentation enhancement, search configuration, ReadMe setup, search functionality, docs improvement
sidebarTitle: Search Bar
------------------------
## What is ReadMe
[ReadMe](https://readme.com/) is a platform for creating documentation.
This integration requires a ReadMe [Business plan](https://readme.com/pricing) or higher, as it relies on custom HTML.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Navigate to **Appearance** of the project settings
2. Open the **Custom Include Tags** tab
3. Add the below code to the **HEAD HTML** section
```html
```
## Initialize the widget
Next, in the **FOOTER HTML** section add the below code to hide the default search bar:
```html
```
Then add the search bar:
```html
```
Press **Save** to apply your changes.
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Chat and Search to ReadMe
description: Add Inkeep's chat button and search bar to your ReadMe documentation.
keywords: ReadMe integration, chat and search, documentation tools, ReadMe customization, combined integration, chat implementation, search implementation, ReadMe setup, documentation enhancement, UI integration
sidebarTitle: Chat Button & Search Bar
--------------------------------------
## What is ReadMe
[ReadMe](https://readme.com/) is a platform for creating documentation.
This integration requires a ReadMe [Business plan](https://readme.com/pricing) or higher, as it relies on custom HTML.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Navigate to **Appearance** of the project settings
2. Open the **Custom Include Tags** tab
3. Add the below code to the **HEAD HTML** section
```html
```
## Initialize the widgets
Next, in the **FOOTER HTML** section add the below code to hide the default search bar:
```html
```
Then add the chat button and search bar:
```html
```
Press **Save** to apply your changes.
For a full list of customizations, check out the [Common Settings](/ui-components/common-settings).
***
title: Add Chat Button to Fumadocs
description: Learn how to integrate Inkeep's chat button into your Fumadocs documentation for real-time user assistance and enhanced documentation interactivity.
keywords: Fumadocs chat integration, React chat button, documentation chat, Fumadocs customization, chat implementation, documentation enhancement, chat configuration, Fumadocs setup, Next.js integration, React components, client-side integration, color mode sync, TypeScript integration
sidebarTitle: Chat Button
-------------------------
## What is Fumadocs
[Fumadocs](https://fumadocs.vercel.app/) is an open source documentation framework, powered by Next.js App Router.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Initialize the widget
You will need to replace `REPLACE_WITH_YOUR_INKEEP_API_KEY` with your actual
Inkeep API key in the code below.
Create an `inkeep-script.tsx` client component in your Fumadocs project.
```jsx title="inkeep-script.tsx"
"use client";
import { useEffect, useState } from "react";
import { InkeepChatButton, type InkeepChatButtonProps } from "@inkeep/cxkit-react";
export function InkeepScript() {
// color mode sync target
const [syncTarget, setSyncTarget] = useState(null);
// We do this because document is not available in the server
useEffect(() => {
setSyncTarget(document.documentElement);
}, []);
const config: InkeepChatButtonProps = {
baseSettings: {
apiKey: "REPLACE_WITH_YOUR_INKEEP_API_KEY", // required - replace with your own API key
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
colorMode: {
sync: {
target: syncTarget,
attributes: ["class"],
isDarkMode: (attributes) => !!attributes.class?.includes("dark"),
},
},
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "https://mydomain.com/mylogo", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
};
return ;
}
```
Then import it in the ` ` of your root `layout.tsx` file.
```jsx title="layout.tsx"
import { InkeepScript } from "@/app/inkeep-script"; // [!code highlight]
import { SearchBar } from "@/app/SearchBar";
import { RootProvider } from "fumadocs-ui/provider";
import "fumadocs-ui/style.css";
import { Inter } from "next/font/google";
import Script from "next/script";
import type { ReactNode } from "react";
const inter = Inter({
subsets: ["latin"],
});
export default function Layout({ children }: { children: ReactNode }) {
return (
// [!code highlight]
{children}
);
}
```
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Search Bar to Fumadocs
description: Enhance your Fumadocs documentation with Inkeep's intelligent search bar for fast, accurate content discovery and improved user experience.
keywords: Fumadocs search integration, AI-powered search, documentation search, Fumadocs customization, search implementation, search configuration, Fumadocs setup, Next.js search, React search components, client-side search, search bar styling, TypeScript integration, search analytics
sidebarTitle: Search Bar
------------------------
## What is Fumadocs
[Fumadocs](https://fumadocs.vercel.app/) is an open source documentation framework, powered by Next.js App Router.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Option 1: Replace the built-in search dialog with Inkeep
This method allows you to replace the default Search Dialog with Inkeep, see [here](https://fumadocs.vercel.app/docs/ui/search#replace-search-dialog) for more information.
You will need to replace `REPLACE_WITH_YOUR_INKEEP_API_KEY` with your actual
Inkeep API key in the code below.
Create a `search.tsx` client component in your `components` directory.
```jsx title="components/search.tsx"
'use client';
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
import { InkeepModalSearchAndChat, type InkeepModalSearchAndChatProps } from "@inkeep/cxkit-react";
import { useEffect, useState } from "react";
export default function CustomDialog(props: SharedProps) {
const [syncTarget, setSyncTarget] = useState (null);
const { open, onOpenChange } = props;
// We do this because document is not available in the server
useEffect(() => {
setSyncTarget(document.documentElement);
}, []);
const config: InkeepModalSearchAndChatProps = {
baseSettings: {
apiKey: "REPLACE_WITH_YOUR_INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
colorMode: {
sync: {
target: syncTarget,
attributes: ["class"],
isDarkMode: (attributes) => !!attributes.class?.includes("dark"),
},
},
},
modalSettings: {
isOpen: open,
onOpenChange,
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "https://mydomain.com/mylogo", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
};
return ;
}
```
To pass it to the Root Provider, you need a wrapper with use client directive. Create a `provider.tsx` file.
```jsx title="provider.tsx"
'use client';
import { RootProvider } from 'fumadocs-ui/provider';
import dynamic from 'next/dynamic';
import type { ReactNode } from 'react';
const SearchDialog = dynamic(() => import('@/components/search')); // lazy load
export function Provider({ children }: { children: ReactNode }) {
return (
{children}
);
}
```
Use it instead of your previous Root Provider in your root `layout.tsx` file.
```jsx title="layout.tsx"
import { Provider } from './provider';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return (
{children}
);
}
```
## Option 2: Add the SearchBar to a custom nav or sidebar component
Use this option if you have created a custom nav or sidebar component.
You will need to replace `REPLACE_WITH_YOUR_INKEEP_API_KEY` with your actual
Inkeep API key in the code below.
Create a `searchbar.tsx` client component in your Fumadocs project.
```jsx title="searchbar.tsx"
"use client";
import { useEffect, useState } from "react";
import { InkeepSearchBar } from "@inkeep/cxkit-react";
export function SearchBar() {
// color mode sync target
const [syncTarget, setSyncTarget] = (useState < HTMLElement) | (null > null);
// We do this because document is not available in the server
useEffect(() => {
setSyncTarget(document.documentElement);
}, []);
const config = {
baseSettings: {
apiKey: "REPLACE_WITH_YOUR_INKEEP_API_KEY", // required - replace with your own API key
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
colorMode: {
sync: {
target: syncTarget,
attributes: ["class"],
isDarkMode: (attributes) => !!attributes.class?.includes("dark"),
},
},
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "https://mydomain.com/mylogo", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
};
return ;
}
```
Then import it into your navbar or sidebar component.
```jsx title="navbar.tsx"
import { SearchBar } from "./searchbar";
export const Navbar = () => {
return (
{/* ...rest of your navbar */}
);
};
```
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Chat Button to Nextra
description: Integrate Inkeep's chat button into your Nextra documentation for real-time user assistance.
keywords: Nextra integration, chat button, Next.js integration, Nextra chat, documentation chat, chat implementation, React components, chat configuration, Nextra setup, user interaction, MDX integration
sidebarTitle: Chat Button
-------------------------
## What is Nextra
[Nextra](https://nextra.site/) is a framework for creating content-focused websites using Next.js and markdown.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
NEXT_PUBLIC_INKEEP_API_KEY="INKEEP_API_KEY"
```
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
Next, create an `InkeepChatButton.tsx` file for the [`Chat Button`](https://docs.inkeep.com/ui-components/react/chat-button) component.
```jsx title=".jsx"
import React, { useEffect, useState } from "react";
export default function InkeepChatButton() {
const [ChatButton, setChatButton] = useState(null);
//...
// load the library asynchronously
useEffect(() => {
const loadChatButton = async () => {
try {
const { InkeepChatButton } = await import("@inkeep/cxkit-react");
setChatButton(() => InkeepChatButton);
} catch (error) {
console.error("Failed to load ChatButton:", error);
}
};
loadChatButton();
}, []);
const chatButtonProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ChatButton && ;
}
```
```tsx title=".tsx"
import React, { useEffect, useState } from "react";
import type { InkeepChatButtonProps } from "@inkeep/cxkit-react";
export default function InkeepChatButton() {
const [ChatButton, setChatButton] =
useState<(e: InkeepChatButtonProps) => JSX.Element>();
//...
// load the library asynchronously
useEffect(() => {
const loadChatButton = async () => {
try {
const { InkeepChatButton } = await import("@inkeep/cxkit-react");
setChatButton(() => InkeepChatButton);
} catch (error) {
console.error("Failed to load ChatButton:", error);
}
};
loadChatButton();
}, []);
const chatButtonProps: InkeepChatButtonProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ChatButton && ;
}
```
### Modify footer
To add a widget to the page, paste the code shown below into the `theme.config.tsx` file:
```tsx title="theme.config.tsx"
//...
footer: {
component: () => ;
}
```
For a full list of customizations, check out the [Chat Button](/ui-components/react/chat-button) documentation.
***
title: Add Search Bar to Nextra
description: Integrate Inkeep's search bar into your Nextra documentation for powerful content discovery.
keywords: Nextra search, Next.js search, search integration, Nextra components, search implementation, documentation search, search configuration, Nextra setup, content discovery, React components, MDX integration
sidebarTitle: Search Bar
------------------------
## What is Nextra
[Nextra](https://nextra.site/) is a framework for creating content-focused websites using Next.js and markdown.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
NEXT_PUBLIC_INKEEP_API_KEY="INKEEP_API_KEY"
```
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
Next, create an `InkeepSearchBar.tsx` file for the [`Search Bar`](https://docs.inkeep.com/ui-components/react/search-bar) component.
```jsx title=".jsx"
import React, { useEffect, useState } from "react";
export default function InkeepSearchBar() {
const [SearchBar, setSearchBar] = useState(null);
//...
// load the library asynchronously
useEffect(() => {
const loadSearchBar = async () => {
try {
const { InkeepSearchBar } = await import("@inkeep/cxkit-react");
setSearchBar(() => InkeepSearchBar);
} catch (error) {
console.error("Failed to load SearchBar:", error);
}
};
loadSearchBar();
}, []);
const searchBarProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return SearchBar && ;
}
```
```tsx title=".tsx"
import React, { useEffect, useState } from "react";
import type { InkeepSearchBarProps } from "@inkeep/cxkit-react";
export default function InkeepSearchBar() {
const [SearchBar, setSearchBar] =
useState<(e: InkeepSearchBarProps) => JSX.Element>();
//...
// load the library asynchronously
useEffect(() => {
const loadSearchBar = async () => {
try {
const { InkeepSearchBar } = await import("@inkeep/cxkit-react");
setSearchBar(() => InkeepSearchBar);
} catch (error) {
console.error("Failed to load SearchBar:", error);
}
};
loadSearchBar();
}, []);
const searchBarProps: InkeepSearchBarProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return SearchBar && ;
}
```
### Replace default search bar
To add a widget to the page, paste the code shown below into the `theme.config.tsx` file:
```tsx title="theme.config.tsx"
//...
search: {
component: () => ;
}
```
Search bar will be replaced by this widget by default
For a full list of customizations, check out the [Search Bar](/ui-components/react/search-bar) documentation.
***
title: Add Embedded Chat to Nextra
description: Integrate Inkeep's embedded chat into your Nextra documentation for seamless user interaction.
keywords: Nextra chat, embedded chat, Next.js integration, chat implementation, documentation enhancement, chat configuration, Nextra setup, user interaction, React components, chat UI, embedded interface, MDX integration
sidebarTitle: Embedded Chat
---------------------------
## What is Nextra
[Nextra](https://nextra.site/) is a framework for creating content-focused websites using Next.js and markdown.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
NEXT_PUBLIC_INKEEP_API_KEY="INKEEP_API_KEY"
```
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
Create an `InkeepEmbeddedChat.tsx` file for the [`Embedded Chat`](https://docs.inkeep.com/ui-components/react/in-page/embedded-chat) component.
```jsx title=".jsx"
import { useEffect, useState } from "react";
export default function InkeepEmbeddedChat() {
const [EmbeddedChat, setEmbeddedChat] = useState(null);
// load the library asynchronously
useEffect(() => {
const loadEmbeddedChat = async () => {
try {
const { InkeepEmbeddedChat } = await import("@inkeep/cxkit-react");
setEmbeddedChat(() => InkeepEmbeddedChat);
} catch (error) {
console.error("Failed to load EmbeddedChat:", error);
}
};
loadEmbeddedChat();
}, []);
const embeddedChatProps = {
baseSettings,
aiChatSettings,
};
return EmbeddedChat && ;
}
```
```tsx title=".tsx"
import { ReactNode, useEffect, useState } from "react";
import type { InkeepEmbeddedChatProps } from "@inkeep/cxkit-react";
export default function InkeepEmbeddedChat() {
const [EmbeddedChat, setEmbeddedChat] =
useState<(e: InkeepEmbeddedChatProps) => JSX.Element | ReactNode>();
// load the library asynchronously
useEffect(() => {
const loadEmbeddedChat = async () => {
try {
const { InkeepEmbeddedChat } = await import("@inkeep/cxkit-react");
setEmbeddedChat(() => InkeepEmbeddedChat);
} catch (error) {
console.error("Failed to load EmbeddedChat:", error);
}
};
loadEmbeddedChat();
}, []);
const embeddedChatProps: InkeepEmbeddedChatProps = {
baseSettings,
aiChatSettings,
};
return EmbeddedChat && ;
}
```
### Use the component
Now to add the `InkeepEmbeddedChat.tsx` component follow these steps:
1. Create a new page - **Ask AI β¨**
```bash
touch pages/ask-ai.mdx
```
2. Initialize the page in the `_meta.json` file:
```json title="_meta.json"
{
// ...
"ask-ai": "Ask AI β¨"
// ...
}
```
3. Add a widget to the page:
```jsx title="ask-ai.mdx"
# Ask AI β¨
import InkeepEmbeddedChat from "@/components/InkeepEmbeddedChat";
```
For a full list of customizations, check out the [Embedded Chat](/ui-components/react/in-page/embedded-chat) documentation.
***
title: Add Custom Modal Trigger to Nextra
description: Integrate Inkeep's custom modal trigger into your Nextra documentation for flexible user interactions.
keywords: Nextra integration, modal trigger, Next.js integration, custom trigger, Nextra components, trigger implementation, documentation customization, modal configuration, Nextra setup, UI integration, MDX integration
sidebarTitle: Custom Modal Trigger
----------------------------------
## What is Nextra
[Nextra](https://nextra.site/) is a framework for creating content-focused websites using Next.js and markdown.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
NEXT_PUBLIC_INKEEP_API_KEY="INKEEP_API_KEY"
```
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
We'll use the [`Modal Search and Chat`](/ui-components/react/custom-modal-trigger#modal-search-and-chat) component to create a custom trigger.
Create a `ModalSearchAndChat.tsx` file for our [`Custom Modal Trigger`](/ui-components/react/custom-modal-trigger) component. `` represents whatever UI element you'd like to use to trigger the Inkeep Modal.
```jsx title=".jsx"
import { useCallback, useEffect, useState } from "react";
export default function Widget() {
const [isOpen, setIsOpen] = useState(false);
const [ModalSearchAndChat, setModalSearchAndChat] = useState();
const handleOpenChange = useCallback((isOpen: boolean) => {
setIsOpen(isOpen);
}, []);
//...
// load the library asynchronously
useEffect(() => {
const loadModalSearchAndChat = async () => {
try {
const { InkeepModalSearchAndChat } = await import("@inkeep/cxkit-react");
setModalSearchAndChat(() => InkeepModalSearchAndChat);
} catch (error) {
console.error("Failed to load ModalSearchAndChat:", error);
}
};
loadModalSearchAndChat();
}, []);
const modalSearchAndChatProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings: {
...modalSettings,
onOpenChange: handleOpenChange,
isOpen,
},
};
return (
setIsOpen(!isOpen)}>Toggle Modal
{ModalSearchAndChat && }
);
}
```
```tsx title=".tsx"
import { useCallback, useEffect, useState } from "react";
import type { InkeepModalSearchAndChatProps } from "@inkeep/cxkit-react";
export default function Widget() {
const [isOpen, setIsOpen] = useState(false);
const [ModalSearchAndChat, setModalSearchAndChat] =
useState<(e: InkeepModalSearchAndChatProps) => JSX.Element>();
const handleOpenChange = useCallback((isOpen: boolean) => {
setIsOpen(isOpen);
}, []);
//...
// load the library asynchronously
useEffect(() => {
const loadModalSearchAndChat = async () => {
try {
const { InkeepModalSearchAndChat } = await import(
"@inkeep/cxkit-react"
);
setModalSearchAndChat(() => InkeepModalSearchAndChat);
} catch (error) {
console.error("Failed to load ModalSearchAndChat:", error);
}
};
loadModalSearchAndChat();
}, []);
const modalSearchAndChatProps: InkeepModalSearchAndChatProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings: {
...modalSettings,
onOpenChange: handleOpenChange,
isOpen,
},
};
return (
setIsOpen(!isOpen)}>Toggle Modal
{ModalSearchAndChat && (
)}
);
}
```
### Use the component
Add a widget component to the page:
```jsx
import InkeepModalSearchAndChat from "@/components/InkeepModalSearchAndChat";
export default function MyApp() {
return (
<>
>
);
}
```
For a full list of customizations, check out the [Custom Modal Trigger](/ui-components/react/custom-modal-trigger) documentation.
***
title: Add Chat and Search to Nextra
description: Integrate Inkeep's chat button and search bar into your Nextra documentation for enhanced user experience and content discovery.
keywords: Nextra integration, chat and search, Next.js integration, Nextra customization, combined integration, chat implementation, search implementation, documentation enhancement, React components, UI integration, MDX integration, theme configuration
sidebarTitle: Chat Button & Search Bar
--------------------------------------
## What is Nextra
[Nextra](https://nextra.site/) is a framework for creating content-focused websites using Next.js and markdown.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
NEXT_PUBLIC_INKEEP_API_KEY="INKEEP_API_KEY"
```
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the components
Next, create component files `InkeepChatButton.tsx` and `InkeepSearchBar.tsx`
#### ChatButton
```jsx title=".jsx"
import React, { useEffect, useState } from "react";
export default function InkeepChatButton() {
const [ChatButton, setChatButton] = useState(null);
//...
// load the library asynchronously
useEffect(() => {
const loadChatButton = async () => {
try {
const { InkeepChatButton } = await import("@inkeep/cxkit-react");
setChatButton(() => InkeepChatButton);
} catch (error) {
console.error("Failed to load ChatButton:", error);
}
};
loadChatButton();
}, []);
const chatButtonProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ChatButton && ;
}
```
```tsx title=".tsx"
import React, { useEffect, useState } from "react";
import type { InkeepChatButtonProps } from "@inkeep/cxkit-react";
export default function InkeepChatButton() {
const [ChatButton, setChatButton] =
useState<(e: InkeepChatButtonProps) => JSX.Element>();
//...
// load the library asynchronously
useEffect(() => {
const loadChatButton = async () => {
try {
const { InkeepChatButton } = await import("@inkeep/cxkit-react");
setChatButton(() => InkeepChatButton);
} catch (error) {
console.error("Failed to load ChatButton:", error);
}
};
loadChatButton();
}, []);
const chatButtonProps: InkeepChatButtonProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ChatButton && ;
}
```
#### SearchBar
```jsx title=".jsx"
import React, { useEffect, useState } from "react";
export default function InkeepSearchBar() {
const [SearchBar, setSearchBar] = useState(null);
//...
// load the library asynchronously
useEffect(() => {
const loadSearchBar = async () => {
try {
const { InkeepSearchBar } = await import("@inkeep/cxkit-react");
setSearchBar(() => InkeepSearchBar);
} catch (error) {
console.error("Failed to load SearchBar:", error);
}
};
loadSearchBar();
}, []);
const searchBarProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return SearchBar && ;
}
```
```tsx title=".tsx"
import React, { useEffect, useState } from "react";
import type { InkeepSearchBarProps } from "@inkeep/cxkit-react";
export default function InkeepSearchBar() {
const [SearchBar, setSearchBar] =
useState<(e: InkeepSearchBarProps) => JSX.Element>();
//...
// load the library asynchronously
useEffect(() => {
const loadSearchBar = async () => {
try {
const { InkeepSearchBar } = await import("@inkeep/cxkit-react");
setSearchBar(() => InkeepSearchBar);
} catch (error) {
console.error("Failed to load SearchBar:", error);
}
};
loadSearchBar();
}, []);
const searchBarProps: InkeepSearchBarProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return SearchBar && ;
}
```
### Modify theme config
To add widgets to the page, paste the code shown below into the `theme.config.tsx` file:
```tsx title="theme.config.tsx"
//...
footer: {
component: () =>
},
search: {
component: () =>
}
```
For a full list of customizations, check out the [Common Settings](/ui-components/common-settings).
***
title: Add Inkeep's UI components to your Mintlify docs
sidebarTitle: Mintlify
keywords: Mintlify integration, documentation platform, UI components, search bar integration, chat button, modern documentation, JavaScript integration, Mintlify docs, documentation search, AI chat integration, documentation tools, Mintlify configuration, documentation customization
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
[Mintlify](https://mintlify.com) is a managed documentation platform with a fresh, modern look.
To add Inkeep's search bar or "Ask AI" chat button to your Mintlify docs, you can use the `@inkeep/cxkit-mintlify` package.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Add a script to your repo
Create an `inkeep.js` file at the root of your documentation GitHub repo like the example below.
Customize `settings` with your API key and other [customizations](/ui-components/common-settings).
```js title="inkeep.js"
function loadScript(url, callback) {
const script = document.createElement("script");
script.src = url;
script.type = "text/javascript";
script.onload = callback;
document.head.appendChild(script);
}
loadScript(
"https://cdn.jsdelivr.net/npm/@inkeep/cxkit-mintlify@0.5/dist/index.js",
() => {
const settings = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // required -- your brand color, the color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
},
aiChatSettings: {
// ...optional settings
aiAssistantAvatar: "https://mydomain.com/mylogo.svg",
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
};
// Initialize the UI components
Inkeep.ModalSearchAndChat(settings); // Search Bar
Inkeep.ChatButton(settings); // 'Ask AI' button
}
);
```
***
title: Add Inkeep's UI components to your Fern docs
sidebarTitle: Fern
keywords: Fern integration, documentation integration, UI components, search bar integration, chat button, static site generator, developer documentation, API documentation, Fern docs, JavaScript integration, documentation search, AI chat integration, documentation tools, Fern configuration
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
[Fern](https://buildwithfern.com/) is a static site generator for developer-focused companies to build and host a beautiful, professional docs site.
To add Inkeep's search bar or "Ask AI" chat button to your Fern docs, you can use the `@inkeep/cxkit-fern` package.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Load the script files
1. Open the `docs.yml` file used to configure Fern.
2. Add the below scripts to the `docs.yml` file in `js` step:
```yml title="docs.yml"
js:
- path: ./inkeep.js
strategy: lazyOnload
```
This links to a local script where we'll setup **Inkeep** for your project.
It should be a relative path to wherever you'd like to setup the script. E.g. `./assets/inkeep.js`
## Create the inkeep.js script
Create the `./inkeep.js` file.
```bash
touch inkeep.js
```
## Add a script to your repo
Create an `inkeep.js` file at the root of your documentation GitHub repo like the example below.
Customize `settings` with your API key and other [customizations](/ui-components/common-settings).
```js title="inkeep.js"
function loadScript(url, callback) {
const script = document.createElement("script");
script.src = url;
script.type = "text/javascript";
script.onload = callback;
document.head.appendChild(script);
}
loadScript(
"https://cdn.jsdelivr.net/npm/@inkeep/cxkit-fern@0.5/dist/index.js",
() => {
const settings = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // required -- your brand color, the color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
},
aiChatSettings: {
// ...optional settings
aiAssistantAvatar: "https://mydomain.com/mylogo.svg",
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
};
// Initialize the UI components
Inkeep.ModalSearchAndChat(settings); // Search Bar
Inkeep.ChatButton(settings); // 'Ask AI' button
}
);
```
***
title: Add Inkeep Search to your Zudoku docs
sidebarTitle: Zudoku
keywords: Zudoku integration, documentation integration, UI components, search bar integration, developer documentation, API documentation, Fern docs, JavaScript integration, documentation search, AI chat integration, documentation tools, Fern configuration
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
[Zudoku](https://zudoku.dev/) is an open-source, OpenAPI powered, highly customizable API documentation framework for building quality developer experiences.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Configure Inkeep
To add Inkeep's search bar, you can configure the `search` option in Zudoku Configuration:
```js
{
// ...
search: {
type: "inkeep",
apiKey: "",
primaryBrandColor: "#26D6FF",
organizationDisplayName: "Your Organization Name",
}
// ...
}
```
***
title: Add Chat Button to VitePress
description: Integrate Inkeep's chat button into your VitePress documentation for real-time user assistance.
keywords: VitePress integration, chat button, Vue.js integration, VitePress chat, documentation chat, chat implementation, Vue components, chat configuration, VitePress setup, user interaction, theme customization
sidebarTitle: Chat Button
-------------------------
## What is VitePress
[VitePress](https://vitepress.dev/) is a lightweight static site generator based on Vue.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
VITE_INKEEP_API_KEY="INKEEP_API_KEY"
```
## Load the script files
Add the below scripts to the `config.ts` file:
```js title="config.ts"
export default {
head: [
[
"script",
{
src: "https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js",
type: "module",
defer: true,
},
],
["script", { src: "static/addInkeep.js", type: "module", defer: true }],
],
};
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `static` folder.
```bash
touch static/addInkeep.js
```
Now, configure the chat button component.
```js
const config = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
};
const inkeepWidget = Inkeep.ChatButton(config);
```
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Search Bar to VitePress
description: Integrate Inkeep's search bar into your VitePress documentation for powerful content discovery.
keywords: VitePress search, Vue.js search, search integration, VitePress components, search implementation, documentation search, search configuration, VitePress setup, content discovery, Vue components, theme customization
sidebarTitle: Search Bar
------------------------
## What is VitePress
[VitePress](https://vitepress.dev/) is a lightweight static site generator based on Vue.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
VITE_INKEEP_API_KEY="INKEEP_API_KEY"
```
## Load the script files
Add the below scripts to the `config.ts` file:
```js title="config.ts"
export default {
head: [
[
"script",
{
src: "https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js",
type: "module",
defer: true,
},
],
["script", { src: "static/addInkeep.js", type: "module", defer: true }],
],
};
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `static` folder.
```bash
touch static/addInkeep.js
```
Now, create a container and configure the search bar component.
### Configure the component
Next, initialize the widget using the `Inkeep.SearchBar()` function.
This will replace the default search bar used on the website.
```js title="addInkeep.js"
// Initialize the widget using the Inkeep.SearchBar() function.
const inkeepWidget = Inkeep.SearchBar(".search", {
baseSettings: {
apiKey: import.meta.env.VITE_INKEEP_API_KEY, // required
primaryBrandColor: "#26D6FF", // your brand color, the widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
colorMode: {
sync: {
target: document.documentElement,
attributes: ["class"],
isDarkMode: (attributes) => !!attributes.class?.includes("dark"),
},
},
theme: {
// optional path to a custom stylesheet
styles: [
{
key: "main",
type: "link",
value: "/path/to/stylesheets",
},
],
// ...optional settings
},
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
});
```
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Chat Button to VuePress
description: Integrate Inkeep's chat button into your VuePress documentation for real-time user assistance.
keywords: VuePress integration, chat button, Vue.js integration, VuePress chat, documentation chat, chat implementation, Vue components, chat configuration, VuePress setup, user interaction, theme customization
sidebarTitle: Chat Button
-------------------------
## What is VuePress
[VuePress](https://vuepress.vuejs.org/) a markdown-centered static site generator.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Load the script files
1. Navigate to the `.vuepress` directory
2. Add the below scripts to the `config.js` file:
```js title="config.js"
export default {
head: [
[
"script",
{
src: "https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js",
type: "module",
defer: true,
onLoad: "initializeInkeep()",
},
],
["script", { src: "js/addInkeep.js", type: "module", defer: true }],
],
};
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `public/js` folder.
```bash
touch public/js/addInkeep.js
```
Now, configure the chat button component.
```js title="addInkeep.js"
const initializeInkeep = () => {
const addInkeepWidget = () => {
const inkeepWidget = Inkeep.ChatButton({
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
colorMode: {
sync: {
target: document.documentElement,
attributes: ["data-color-mode"],
isDarkMode: (attributes) =>
!!attributes["data-color-mode"] === "dark",
},
},
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "https://mydomain.com/mylogo", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
});
};
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", addInkeepWidget);
return;
}
addInkeepWidget();
};
```
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Search Bar to VuePress
description: Integrate Inkeep's search bar into your VuePress documentation for powerful content discovery.
keywords: VuePress search, Vue.js search, search integration, VuePress components, search implementation, documentation search, search configuration, VuePress setup, content discovery, Vue components, theme customization
sidebarTitle: Search Bar
------------------------
## What is VuePress
[VuePress](https://vuepress.vuejs.org/) a markdown-centered static site generator.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Load the script files
1. Navigate to the `.vuepress` directory
2. Add the below scripts to the `config.js` file:
```js title="config.js"
export default {
head: [
[
"script",
{
src: "https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js",
type: "module",
defer: true,
onLoad: "initializeInkeep()",
},
],
["script", { src: "js/addInkeep.js", type: "module", defer: true }],
],
};
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `public/js` folder.
```bash
touch public/js/addInkeep.js
```
## Create container for search bar
To create a container for the search bar component, navigate to your desired page and add the following code:
```jsx
```
### Configure the component
Next, configure the Inkeep widget:
```js title="addInkeep.js"
const initializeInkeep = () => {
const addInkeepWidget = () => {
const searchContainer = document.querySelector("#inkeepSearchBar");
if (!searchContainer) return;
const inkeepWiddget = Inkeep.SearchBar("#inkeepSearchBar", {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF",
organizationDisplayName: "Inkeep",
colorMode: {
sync: {
target: document.documentElement,
attributes: ["data-md-color-scheme"],
isDarkMode: (attributes) =>
!!["dark", "dracula"].includes(
attributes["data-md-color-scheme"]
),
},
},
},
});
};
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", addInkeepWidget);
return;
}
addInkeepWidget();
};
```
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Embedded Chat to VuePress
description: Integrate Inkeep's embedded chat into your VuePress documentation for seamless user interaction.
keywords: VuePress chat, embedded chat, Vue.js integration, chat implementation, documentation enhancement, chat configuration, VuePress setup, user interaction, Vue components, chat UI, embedded interface
sidebarTitle: Embedded Chat
---------------------------
## What is VuePress
[VuePress](https://vuepress.vuejs.org/) a markdown-centered static site generator.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Load the script files
1. Navigate to the `.vuepress` directory
2. Add the below scripts to the `config.js` file:
```js title="config.js"
export default {
head: [
[
"script",
{
src: "https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js",
type: "module",
defer: true,
onLoad: "initializeInkeep()",
},
],
["script", { src: "js/addInkeep.js", type: "module", defer: true }],
],
};
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `public/js` folder.
```bash
touch public/js/addInkeep.js
```
## Create container for embedded chat
To create a container for the embedded chat component, navigate to your desired page and add the following code:
```jsx
```
### Configure the component
Next, configure the Inkeep widget:
```js title="addInkeep.js"
const initializeInkeep = () => {
const addInkeepWidget = () => {
const embeddedContainer = document.querySelector("#inkeepEmbeddedChat");
if (!embeddedContainer) return;
const inkeepWidget = Inkeep.EmbeddedChat("#inkeepEmbeddedChat", {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF",
organizationDisplayName: "Inkeep",
colorMode: {
sync: {
target: document.documentElement,
attributes: ["data-md-color-scheme"],
isDarkMode: (attributes) => {
const currentTheme = attributes["data-md-color-scheme"];
return currentTheme === "dracula" || currentTheme === "dark";
},
},
},
},
});
};
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", addInkeepWidget);
return;
}
addInkeepWidget();
};
```
For a full list of customizations, check out the [Embedded Chat](/ui-components/react/in-page/embedded-chat) documentation.
***
title: Add Chat Button to Document360
description: Integrate Inkeep's chat button into your Document360 documentation for real-time user assistance.
keywords: Document360 chat, chat integration, documentation chat, Document360 customization, chat implementation, documentation enhancement, chat configuration, Document360 setup, knowledge base chat, user assistance
sidebarTitle: Chat Button
-------------------------
## What is Document360
[Document360](https://document360.com/) an AI-powered knowledge base software to create internal and public knowledge bases.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Initialize the widget
To integrate the Inkeep chat button into your Document360 documentation, follow these steps:
1. Navigate to **Custom CSS / Javascript** settings.
2. Click on the **Javascript** tab.
3. Add the following script to load the chat button:
```js
document.addEventListener("DOMContentLoaded", () => {
// Load the Inkeep script
const inkeepScript = document.createElement("script");
inkeepScript.src =
"https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js";
inkeepScript.type = "module";
inkeepScript.defer = true;
document.head.appendChild(inkeepScript);
// Configure and initialize the widget
const addInkeepWidget = () => {
const inkeepWidget = Inkeep.ChatButton({
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
colorMode: {
sync: {
target: document.documentElement,
attributes: ["data-color-mode"],
isDarkMode: (attributes) =>
attributes["data-color-mode"] === "dark",
},
},
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "https://mydomain.com/mylogo", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
});
};
inkeepScript.addEventListener("load", () => {
addInkeepWidget();
});
});
```
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add AI Search to your Document360 docs
sidebarTitle: Search Bar
------------------------
## What is Document360
[Document360](https://document360.com/) an AI-powered knowledge base software to create internal and public knowledge bases.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Initialize the widget
To integrate the Inkeep search bar into your Document360 documentation, follow these steps:
1. On the **Home page** remove the default search bar from the **Hero** section
2. Go to the page where you want to display the widget and create a new **Custom code section** with the following html code:
```html
```
3. Navigate to **Custom CSS / Javascript** settings.
4. Click on the **Javascript** tab.
5. Add the following script to disable default search bar and load the Inkeep one:
```js
document.addEventListener("DOMContentLoaded", () => {
// Load the Inkeep script
const inkeepScript = document.createElement("script");
inkeepScript.src =
"https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js";
inkeepScript.type = "module";
inkeepScript.defer = true;
document.head.appendChild(inkeepScript);
// Function for customizing the widget configuration
const inkeepConfig = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
theme: {
// optional path to a custom stylesheet
styles: [
{
key: "main",
type: "link",
value: "/path/to/stylesheets",
},
],
// ...optional settings
},
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
};
// Configure and initialize the widget
const addInkeepWidget = () => {
Inkeep.SearchBar("#inkeepSearchBar", inkeepConfig);
const observer = new MutationObserver((mutationsList, observer) => {
const inkeepPortals = document.getElementsByTagName("inkeep-portal");
Array.from(inkeepPortals)?.forEach((inkeepPortal) => {
inkeepPortal.remove();
});
inkeepConfig("#inkeepSearchBar").targetElement = search;
Inkeep.SearchBar("#inkeepSearchBar", inkeepConfig);
});
observer.observe(document.head, { childList: true });
};
inkeepScript.addEventListener("load", () => {
addInkeepWidget();
});
});
```
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Chat and Search to Document360
description: Integrate Inkeep's chat button and search bar into your Document360 documentation for enhanced user experience.
keywords: Document360 integration, chat and search, documentation tools, Document360 customization, combined integration, chat implementation, search implementation, documentation enhancement, UI integration, knowledge base search, documentation chat
sidebarTitle: Chat Button & Search Bar
--------------------------------------
## What is Document360
[Document360](https://document360.com/) an AI-powered knowledge base software to create internal and public knowledge bases.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Initialize the widget
To integrate the Inkeep chat button and search bar into your Document360 documentation, follow these steps:
1. On the **Home page** remove the default search bar from the **Hero** section
2. Go to the page where you want to display the widget and create new **Custom code section** with the following html:
```html
```
3. Navigate to **Custom CSS / Javascript** settings.
4. Click on the **Javascript** tab.
5. Add the following script to load the Inkeep chat button and search bar:
```js
document.addEventListener("DOMContentLoaded", () => {
// Load the Inkeep script
const inkeepScript = document.createElement("script");
inkeepScript.src =
"https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js";
inkeepScript.type = "module";
inkeepScript.defer = true;
document.head.appendChild(inkeepScript);
// Function for customizing the widget configuration
const inkeepConfig = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
theme: {
// optional path to a custom stylesheet
styles: [
{
key: "main",
type: "link",
value: "/path/to/stylesheets",
},
],
// ...optional settings
},
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
};
// Configure and initialize the widgets
const addInkeepWidget = () => {
const targetElement = document.getElementById("inkeepSearchBar");
if (!targetElement) return;
Inkeep.ChatButton(inkeepConfig);
Inkeep.SearchBar("#inkeepSearchBar", inkeepConfig);
};
inkeepScript.addEventListener("load", () => {
addInkeepWidget();
});
});
```
For a full list of customizations, check out the [Common Settings](/ui-components/common-settings).
***
title: Add Chat Button to Sphinx
description: Integrate Inkeep's chat button into your Sphinx documentation for real-time user assistance.
keywords: Sphinx integration, chat button, Python documentation, Sphinx chat, documentation chat, chat implementation, Sphinx extension, chat configuration, Sphinx setup, user interaction, theme customization
sidebarTitle: Chat Button
-------------------------
## What is Sphinx
[Sphinx](https://www.sphinx-doc.org/) is a documentation platform often used for Python projects.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Load the script files
Add the below scripts to the `conf.py` file:
```py
# ...
html_js_files = [
('https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js', {'defer': 'defer', 'type': 'module'}),
('js/addInkeep.js', {'defer': 'defer', 'type': 'module'}),
]
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `_static` folder.
```bash
touch _static/js/addInkeep.js
```
Now, configure the chat button component.
```js title="addInkeep.js"
// Initialize the widget using the Inkeep.ChatButton() function.
const inkeepWidget = Inkeep.ChatButton({
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
});
```
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Search Bar to Sphinx
description: Integrate Inkeep's search bar into your Sphinx documentation for powerful content discovery.
keywords: Sphinx search, Python documentation, search integration, Sphinx components, search implementation, documentation search, search configuration, Sphinx setup, content discovery, Sphinx extension, theme customization
sidebarTitle: Search Bar
------------------------
## What is Sphinx
[Sphinx](https://www.sphinx-doc.org/) is a documentation platform often used for Python projects.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Load the script files
Add the below scripts to the `conf.py` file:
```py
# ...
html_js_files = [
('https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js', {'defer': 'defer', 'type': 'module'}),
('js/addInkeep.js', {'defer': 'defer', 'type': 'module'}),
]
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `_static` folder.
```bash
touch _static/js/addInkeep.js
```
Now, create a container and configure the search bar component.
### Configure the component
```js title="addInkeep.js"
// Embed the widget using the `Inkeep.SearchBar()` function.
const inkeepWidget = Inkeep.SearchBar("#inkeepSearchBar", {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
theme: {
// optional path to a custom stylesheet
styles: [
{
key: "main",
type: "link",
value: "/path/to/stylesheets",
},
],
// optional settings
},
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
});
```
## Container element
Create a `searchbox.html` file in `source/_templates` and paste in the below::
This Inkeep `SearchBar` widget will replace the default search bar used on the
website.
```html title="searchbox.html"
```
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Chat and Search to Hugo Ananke
description: Integrate Inkeep's chat button and search bar into your Hugo Ananke theme for enhanced user experience.
keywords: Hugo Ananke, theme integration, chat and search, Hugo customization, combined integration, chat implementation, search implementation, theme enhancement, static site integration, UI customization
sidebarTitle: Ananke (Base theme)
---------------------------------
## Overview
In this integration example, we will be integrating Inkeep widget into [Ananke](https://themes.gohugo.io/themes/gohugo-theme-ananke/) theme, which is the default theme used as an example with Hugo.
## What is Hugo
[Hugo](https://gohugo.io/) is a popular open-source static site generator often used for documentation.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Create the baseof.html file
Create an `baseof.html` file at the path `layouts/_default`
```bash
touch layouts/_default/baseof.html
```
Copy the contents of the `baseof.html` file:
```bash
cp themes/ananke/layouts/_default/baseof.html layouts/_default/baseof.html
```
Depending on your Hugo theme, this step may differ. The goal is to be able to insert custom scripts into your sites `` tag.
### Load the script files
In the `baseof.html` file, locate the **head** tag and paste the scripts below at the end:
```html title="baseof.html"
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `static/js` folder.
```bash
touch static/js/addInkeep.js
```
Now, configure the chat button component.
```js title="addInkeep.js"
const inkeepWidget = Inkeep.ChatButton({
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
});
```
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Chat Button to Hugo Docsy
description: Integrate Inkeep's chat button into your Hugo Docsy theme for real-time user assistance.
keywords: Hugo Docsy, chat button, theme integration, Docsy customization, chat implementation, documentation enhancement, chat configuration, Docsy setup, theme customization, user assistance, Hugo themes
sidebarTitle: Chat Button
-------------------------
## What is Docsy
[Docsy](https://www.docsy.dev/) is a theme for the Hugo static site generator thatβs specifically designed for technical documentation sets and has a lot of best practices built in.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Create the head-end.html file
Create an `head-end.html` file at the path `layouts/partials/hooks`
```bash
touch layouts/partials/hooks/head-end.html
```
### Load the script files
Add the below scripts to the `head-end.html` file:
```html title="head-end.html"
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `static/js` folder.
```bash
touch static/js/addInkeep.js
```
Now, configure the chat button component.
```js title="addInkeep.js"
// Initialize the widget using the Inkeep.ChatButton() function.
const inkeepWidget = Inkeep.ChatButton({
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
});
```
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Search Bar to Hugo Docsy
description: Integrate Inkeep's search bar into your Hugo Docsy theme for powerful content discovery.
keywords: Hugo Docsy search, theme integration, documentation search, Docsy customization, search implementation, theme enhancement, search configuration, Docsy setup, content discovery, Hugo themes, search functionality
sidebarTitle: Search Bar
------------------------
## What is Docsy
[Docsy](https://www.docsy.dev/) is a theme for the Hugo static site generator thatβs specifically designed for technical documentation sets and has a lot of best practices built in.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Create the head-end.html file
Create an `head-end.html` file at the path `layouts/partials/hooks`
```bash
touch layouts/partials/hooks/head-end.html
```
### Load the script files
Add the below scripts to the `head-end.html` file:
```html title="head-end.html"
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `static/js` folder.
```bash
touch static/js/addInkeep.js
```
Disable the default search in the `config.toml (or hugo.toml)` file, by
setting the `offlineSearch` parameter to **false**.
Now, create a container and configure the search bar component.
```js title="addInkeep.js"
// Create an HTML element that the Inkeep widget will be inserted into.
const nav = document.querySelector("nav");
const sidebar = document.getElementById("td-sidebar-menu");
const inkeepNavDiv = document.createElement("div");
inkeepNavDiv.id = "navSearchBar";
nav.appendChild(inkeepNavDiv);
const inkeepSidebarDiv = document.createElement("div");
inkeepSidebarDiv.id = "sideSearchBar";
sidebar && sidebar.prepend(inkeepSidebarDiv);
// Function for initializating the widget.
const addInkeepWidget = ({ targetElement, styles, shortcutKey }) => {
// Embed the widget using the `Inkeep.SearchBar()` function.
const inkeepWidget = Inkeep.SearchBar(targetElement, {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
theme: {
styles,
// ...optional settings
},
},
modalSettings: {
// optional settings
shortcutKey,
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
});
};
sidebar &&
addInkeepWidget({
targetElement: "#sideSearchBar",
styles: [
{
key: "main",
type: "link",
value: "/path/to/stylesheets",
},
],
// optional
shortcutKey: null,
});
addInkeepWidget({
targetElement: "#navSearchBar",
styles: [
{
key: "main",
type: "link",
value: "/path/to/stylesheets",
},
],
// optional
shortcutKey: "k",
});
```
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Chat Button to Redocly API Reference
description: Integrate Inkeep's chat button into your Redocly API Reference for real-time API documentation assistance.
keywords: Redocly integration, chat button, API reference, API documentation, chat implementation, documentation enhancement, chat configuration, Redocly setup, user interaction, API support, developer experience
sidebarTitle: Chat Button
-------------------------
## Overview
The Redocly [API registry](https://redocly.com/docs/api-registry/guides/api-registry-quickstart/) offers API reference docs generated from OpenAPI definitions.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Load the script files
Add the below scripts to the `index.html` file:
```html
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `docs` folder.
```bash
touch docs/addInkeep.js
```
Now, configure the chat button component.
```js title="addInkeep.js"
// Initialize the widget using the Inkeep.ChatButton() function.
const inkeepWidget = Inkeep.ChatButton({
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
});
```
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Search Bar to Redocly API Reference
description: Integrate Inkeep's search bar into your Redocly API Reference for powerful API documentation discovery.
keywords: Redocly search, API reference, search integration, API documentation, search implementation, documentation search, search configuration, Redocly setup, content discovery, API support, developer experience
sidebarTitle: Search Bar
------------------------
## Overview
The Redocly [API registry](https://redocly.com/docs/api-registry/guides/api-registry-quickstart/) offers API reference docs generated from OpenAPI definitions.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Load the script files
Add the below scripts to the `index.html` file:
```html
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `docs` folder.
```bash
touch docs/addInkeep.js
```
Now, create a container and configure the search bar component.
```js title="addInkeep.js"
// Create an HTML element that the Inkeep widget will be inserted into.
const searchBarParentNode = document.querySelector(".scrollbar-container");
const inkeepDiv = document.createElement("div");
inkeepDiv.id = "inkeep";
searchBarParentNode.prepend(inkeepDiv);
let inkeepWidget = null;
const config = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
theme: {
// optional path to a custom stylesheet
styles: [
{
key: "main",
type: "link",
value: "/path/to/stylesheets",
},
],
// ...optional settings
},
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
};
// Wait for container to render
if (!inkeepWidget && targetElement) {
// Initialize the widget using the Inkeep.SearchBar() function.
inkeepWidget = Inkeep.SearchBar("#inkeep", config);
}
```
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Chat Button to Redocly Developer Portal
description: Integrate Inkeep's chat button into your Redocly Developer Portal for real-time API documentation assistance.
keywords: Redocly integration, chat button, API documentation, developer portal, chat implementation, documentation enhancement, chat configuration, Redocly setup, user interaction, API support, developer experience
sidebarTitle: Chat Button
-------------------------
## Overview
Redocly [Developer Hubs](https://redocly.com/docs/api-registry/guides/api-registry-quickstart/) provide a way to build sites for your documentation from plain Markdown files.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Attach the script
Attach the `addInkeep.js` script in the `siteConfig.yaml` file:
```yaml title="siteConfig.yaml"
scripts:
- ./static/addInkeep.js
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `static` folder.
```bash
touch static/addInkeep.js
```
Now, configure the chat button component.
```js title="addInkeep.js"
// Function for adding a script to the page
const addScript = (src, type = "module", defer = true) => {
const script = document.createElement("script");
script.src = src;
script.type = type;
script.defer = defer;
document.body.appendChild(script);
return script;
};
// Function for customizing the widget configuration
const inkeepConfig = () => {
return {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
};
};
// Function for initializing the widget
const addInkeepWidget = () => {
const inkeepWidgetScript = document.createElement("script");
inkeepWidgetScript.defer = true;
// Initialize the widget using the `Inkeep.ChatButton()` function.
inkeepWidgetScript.innerHTML = `
const config = (${inkeepConfig.toString()})();
Inkeep.ChatButton(config);
`;
document.body.appendChild(inkeepWidgetScript);
};
// Adding the script and initializing the widget
const embedScript = addScript(
"https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js"
);
embedScript.addEventListener("load", () => {
addInkeepWidget();
});
```
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
```js
// Initialize the widget using the `Inkeep.ChatButton()` function.
const config = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
};
const inkeepWidget = Inkeep.ChatButton(config);
```
***
title: Add Search Bar to Redocly Developer Portal
description: Integrate Inkeep's search bar into your Redocly Developer Portal for powerful API documentation discovery.
keywords: Redocly search, API documentation, search integration, developer portal, search implementation, documentation search, search configuration, Redocly setup, content discovery, API reference, developer experience
sidebarTitle: Search Bar
------------------------
## Overview
Redocly [Developer Hubs](https://redocly.com/docs/api-registry/guides/api-registry-quickstart/) provide a way to build sites for your documentation from plain Markdown files.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Attach the script
Attach the `addInkeep.js` script in the `siteConfig.yaml` file:
```yaml title="siteConfig.yaml"
scripts:
- ./static/addInkeep.js
```
## Create the addInkeep.js script
Create an `addInkeep.js` file in your `static` folder.
```bash
touch static/addInkeep.js
```
Now, create a container and configure the search bar component.
```js title="addInkeep.js"
// Function for adding a script to the page
const addScript = (src, type = "module", defer = true) => {
const script = document.createElement("script");
script.src = src;
script.type = type;
script.defer = defer;
document.body.appendChild(script);
return script;
};
// Function for customizing the widget configuration
const inkeepConfig = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
};
// Function for initializating the widget
const addInkeepWidget = () => {
const search = document.getElementById("inkeepSearchBar");
if (search) {
Inkeep.SearchBar("#inkeepSearchBar", inkeepConfig);
}
};
// Adding the script and initializing the widget
const inkeepWidgetScript = document.createElement("script");
inkeepWidgetScript.defer = true;
inkeepWidgetScript.innerHTML = addInkeepWidget.toString();
document.body.appendChild(inkeepWidgetScript);
const embedScript = addScript(
"https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js"
);
embedScript.addEventListener("load", addInkeepWidget);
```
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Search Bar to MkDocs
description: Integrate Inkeep's search bar into your MkDocs documentation for powerful content discovery.
keywords: MkDocs search, documentation search, search integration, MkDocs customization, search implementation, documentation enhancement, search configuration, MkDocs setup, Python documentation, content discovery
sidebarTitle: Search Bar
------------------------
## What is MkDocs
[MkDocs](https://www.mkdocs.org/) is a platform for creating documentation with markdown.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Initialize the widget
In docs folder create a custom js file, for example `search-bar.js`. Add path to this file to the `mkdocs.yml` and disable default search bar with `plugins: []`:
```yml title="mkdocs.yml"
extra_javascript:
- search-bar.js
plugins: []
```
Then add the search bar:
```js title="search-bar.js"
document.addEventListener("DOMContentLoaded", () => {
// Create a new div for the Inkeep search bar
const inkeepDiv = document.createElement("div");
inkeepDiv.id = "inkeepSearchBar";
// Get the header element where you want to place the Inkeep search bar
const headerElement = document.querySelector(".navbar-nav");
if (headerElement) {
headerElement.parentNode.insertBefore(inkeepDiv, headerElement.nextSibling);
}
// Load the Inkeep script
const inkeepScript = document.createElement("script");
inkeepScript.src =
"https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js";
inkeepScript.type = "module";
inkeepScript.defer = true;
document.head.appendChild(inkeepScript);
// Initialize the Inkeep widget after the script loads
inkeepScript.addEventListener("load", () => {
Inkeep.SearchBar("#inkeepSearchBar", {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF",
organizationDisplayName: "Inkeep",
colorMode: {
sync: {
target: document.documentElement,
attributes: ["data-md-color-scheme"],
isDarkMode: (attributes) => {
const currentTheme = attributes["data-md-color-scheme"];
return currentTheme === "dracula" || currentTheme === "dark";
},
},
},
},
});
});
});
```
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Chat Button to MkDocs
description: Integrate Inkeep's chat button into your MkDocs documentation for real-time user assistance.
keywords: MkDocs integration, chat button, documentation chat, MkDocs customization, chat implementation, documentation enhancement, chat configuration, MkDocs setup, Python documentation, user assistance
sidebarTitle: Chat Button
-------------------------
## What is MkDocs
[MkDocs](https://www.mkdocs.org/) is a platform for creating documentation with markdown.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Initialize the widget
In docs folder create a custom js file, for example `inkeep-button.js`. Add path to this file to the `mkdocs.yml`:
```yml title="mkdocs.yml"
extra_javascript:
- inkeep-button.js
```
Then add the button:
You will need to replace `REPLACE_WITH_YOUR_INKEEP_API_KEY` with your actual
Inkeep API key in the code below.
```js title="inkeep-button.js"
document.addEventListener("DOMContentLoaded", () => {
// Load the Inkeep script
const inkeepScript = document.createElement("script");
inkeepScript.src =
"https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js";
inkeepScript.type = "module";
inkeepScript.defer = true;
document.head.appendChild(inkeepScript);
// Configure and initialize the widget
const addInkeepWidget = () => {
const inkeepWidget = Inkeep.ChatButton({
baseSettings: {
apiKey: "REPLACE_WITH_YOUR_INKEEP_API_KEY", // required - replace with your own API key
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
colorMode: {
sync: {
target: document.documentElement,
attributes: ["data-color-mode"],
isDarkMode: (attributes) =>
attributes["data-color-mode"] === "dark",
},
},
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "https://mydomain.com/mylogo", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
});
};
inkeepScript.addEventListener("load", () => {
addInkeepWidget(); // initialize the widget
});
});
```
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Chat and Search to MkDocs
description: Integrate Inkeep's chat button and search bar into your MkDocs documentation for enhanced user experience.
keywords: MkDocs integration, chat and search, documentation tools, MkDocs customization, combined integration, chat implementation, search implementation, documentation enhancement, Python documentation, UI integration
sidebarTitle: Chat Button & Search Bar
--------------------------------------
## What is MkDocs
[MkDocs](https://www.mkdocs.org/) is a platform for creating documentation with markdown.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Initialize the widget
In docs folder create a custom js file, for example `button-and-search-bar.js`. Add path to this file to the `mkdocs.yml` and disable default search bar with `plugins: []`:
```yml title="mkdocs.yml"
extra_javascript:
- button-and-search-bar.js
plugins: []
```
Then add the button and search bar:
```js title="button-and-search-bar.js"
document.addEventListener("DOMContentLoaded", () => {
// Load the Inkeep script
const inkeepScript = document.createElement("script");
inkeepScript.src =
"https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js";
inkeepScript.type = "module";
inkeepScript.defer = true;
document.head.appendChild(inkeepScript);
// Create a new div for the Inkeep search bar
const inkeepDiv = document.createElement("div");
inkeepDiv.id = "inkeepSearchBar";
// Get the header element where you want to place the Inkeep search bar
const headerElement = document.querySelector("#navbar-collapse");
if (headerElement) {
headerElement.appendChild(inkeepDiv);
}
const config = {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings,
colorMode: {
sync: {
target: document.documentElement,
attributes: ["data-color-mode-scheme"],
isDarkMode: (attributes) => {
const currentTheme = attributes["data-color-mode-scheme"];
return currentTheme === "dracula" || currentTheme === "dark";
},
},
},
theme: {
styles: [
{
key: "main",
type: "link",
value: "/path/to/stylesheets",
},
],
// ...optionalSettings,
},
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "https://mydomain.com/mylogo", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
};
inkeepScript.addEventListener("load", () => {
const widgetContainer = document.getElementById("inkeepSearchBar");
Inkeep.ChatButton(config);
widgetContainer && Inkeep.SearchBar("#inkeepSearchBar", config);
});
});
```
For a full list of customizations, check out the [Common Settings](/ui-components/common-settings).
***
title: Add Chat Button to Webflow
description: Add Inkeep's chat button to your Webflow site.
keywords: Webflow chat, chat button, chat integration, Webflow customization, chat implementation, site enhancement, chat configuration, Webflow setup, chat functionality, UI improvement
sidebarTitle: Chat Button
-------------------------
## What is Webflow
[Webflow](https://webflow.com/) is a visual web development platform that enables users to design, build, and launch websites without the need for coding.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Navigate to **Site settings** (not the designer)
2. Open the **Custom code** tab
3. Add the below to the **Head code** section
```html
```
## Initialize the widget
Click on the **Footer code** section and add the below script.
```html
```
Press **Save** to apply your settings.
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Search Bar to Webflow
description: Add Inkeep's search bar to your Webflow site.
keywords: Webflow search, site search, search integration, Webflow customization, search implementation, site enhancement, search configuration, Webflow setup, search functionality, UI improvement
sidebarTitle: Search Bar
------------------------
## What is Webflow
[Webflow](https://webflow.com/) is a visual web development platform that enables users to design, build, and launch websites without the need for coding.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Navigate to **Site settings** (not the designer)
2. Open the **Custom code** tab
3. Add the below to the **Head code** section
```html
```
## Creating the container
Next, you need to add a container for the widget. You can do this using the built-in Webflow **designer**.
### Add the placeholder
Add a container to your navigation bar where the search bar will be placed:
### Set the container ID
Set the ID of the container to `inkeepSearchBar`:
## Configure the widget
Go back to **Site settings** and navigate to **Custom code**. Add the below in the **Footer code** section.
```html
```
Press **Save** to apply your settings.
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Embedded Chat to Webflow
description: Add Inkeep's embedded chat to your Webflow site.
keywords: Webflow chat, embedded chat, chat integration, Webflow customization, chat implementation, site enhancement, chat configuration, Webflow setup, chat functionality, UI improvement
sidebarTitle: Embedded Chat
---------------------------
## What is Webflow
[Webflow](https://webflow.com/) is a visual web development platform that enables users to design, build, and launch websites without the need for coding.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Navigate to **Site settings** (not the designer)
2. Open the **Custom code** tab
3. Add the below to the **Head code** section
```html
```
## Create a new page
Next, you need to create a new page for the chat widget. You can do this using the built-in Webflow **designer**.
### Add a container to the page
Select **Container** from the list of elements and add it to the page:
### Set the container ID
Set the ID of the container to `inkeepEmbeddedChat`:
## Configure the widget
Go back to **Site settings** and navigate to **Custom code**. Add the below in the **Footer code** section.
```html
```
Press **Save** to apply your settings.
As a result, a chat widget will be added to the Ask AI page:
For a full list of customizations, check out the [Common Settings](/ui-components/common-settings).
***
title: Add Custom Modal Trigger to Webflow
description: Add Inkeep's custom modal trigger to your Webflow site.
keywords: Webflow integration, modal trigger, custom trigger, Webflow customization, modal implementation, site enhancement, trigger configuration, Webflow setup, UI integration, custom interaction
sidebarTitle: Custom Trigger
----------------------------
## What is Webflow
[Webflow](https://webflow.com/) is a visual web development platform that enables users to design, build, and launch websites without the need for coding.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Navigate to **Site settings** (not the designer)
2. Open the **Custom code** tab
3. Add the below to the **Head code** section
```html
```
## Create a trigger
You need to create a trigger in your application with ID - `inkeepButton`. This can be done using Webflow's built-in **designer**.
Example:
## Initialize the widget
Click on the **Footer code** section and add the below script.
```html
```
For a full list of customizations, check out the [Custom Modal Trigger](/ui-components/js-snippet/custom-modal-trigger) documentation.
***
title: Add Chat Button to Framer
description: Integrate Inkeep's chat button into your Framer site for real-time user assistance.
keywords: Framer integration, chat button, Framer chat, site integration, chat implementation, Framer components, chat configuration, Framer setup, user interaction, site enhancement, design integration, visual customization
sidebarTitle: Chat Button
-------------------------
## What is Framer
[Framer](https://www.framer.com/) is a tool for creating interactive websites.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Open **Site Settings** in the drop-down menu
2. Click on the **Open Settings** tab
3. Go to the **General** section
4. Add the below to the **Start of `` tag** section
```html
```
## Initialize the widget
Next, paste the script below into the **End of `` tag** section:
```html
```
## Save custom code
Click on the **Save** button. Navigate to your web application and reload the page, to make sure the widget is installed correctly.
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Search Bar to Framer
description: Integrate Inkeep's search bar into your Framer site for powerful content discovery.
keywords: Framer search, search integration, Framer components, search implementation, site search, design integration, search configuration, Framer setup, content discovery, search functionality, visual customization, search UI
sidebarTitle: Search Bar
------------------------
## What is Framer
[Framer](https://www.framer.com/) is a tool for creating interactive websites.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Open **Site Settings** in the drop-down menu
2. Click on the **Open Settings** tab
3. Go to the **General** section
4. Add the below to the **Start of `` tag** section
```html
```
## Creating the container
Add a widget container to the page using the built-in **Framer** functionality.
1. Select an area to add a container
2. Select the **Embed** item in the **Utility** section
3. Add an html element to the page
4. Specify the ID of the container to be `inkeepSearchBar`
## Initialize the widget
Next, paste the script below into the **End of `` tag** section:
```html
```
## Save custom code
Click on the **Save** button. Navigate to your web application and reload the page, to make sure the widget is installed correctly.
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Embedded Chat to Framer
description: Integrate Inkeep's embedded chat into your Framer site for seamless user interaction.
keywords: Framer chat, embedded chat, Framer integration, chat implementation, site enhancement, chat configuration, Framer setup, user interaction, design integration, visual customization, chat UI, embedded interface
sidebarTitle: Embedded Chat
---------------------------
## What is Framer
[Framer](https://www.framer.com/) is a tool for creating interactive websites.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Open **Site Settings** in the drop-down menu
2. Click on the **Open Settings** tab
3. Go to the **General** section
4. Add the below to the **Start of `` tag** section
```html
```
## Creating the container
Add a widget container to the page using the built-in **Framer** functionality.
1. Select an area to add a container
2. Select the **Embed** item in the **Utility** section
3. Add an html element to the page
4. Specify the ID of the container to be `inkeepEmbeddedChat`
## Initialize the widget
### For multi page sites
If your site is **not** a single page application (SPA), load the Inkeep script on the page with the Inkeep container element.
1. Open **Site Settings** in the drop-down menu
2. Click on the **Open Settings** tab
3. Select the page that has the Inkeep container element (under the **Page settings** section)
4. Next, paste the script below into the **End of `` tag** section:
```html
```
### For single page sites (SPAs)
If your site is a single page application, you will need to load the Inkeep script in the `` tag in the General section (that will be loaded on every page) and use the `MutationObserver` to track whether the `inkeepEmbeddedChat` element is in the DOM before initializing the widget (see example below).
1. Open **Site Settings** in the drop-down menu
2. Click on the **Open Settings** tab
3. Go to the General section
4. Next, paste the script below into the **End of `` tag** section:
```html
```
## Save custom code
Click on the **Save** button. Navigate to your web application and reload the page, to make sure the widget is installed correctly.
For a full list of customizations, check out the [Embedded Chat](/ui-components/js-snippet/in-page/embedded-chat) documentation.
***
title: Add Chat Button to WordPress
description: Learn how to integrate Inkeep's chat button into your WordPress site for real-time user assistance and enhanced customer support.
keywords: WordPress chat integration, WordPress plugin, chat button, website integration, customer support, real-time chat, WordPress customization, chat implementation, user assistance, WordPress enhancement
sidebarTitle: Chat Button
-------------------------
## What is WordPress
[WordPress](https://wordpress.com/) popular content management system (CMS) designed for creating and managing websites.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Install custom code plugin
This plugin is required to add custom code in order to create a widget.
1. Open WordPress admin panel
2. Select the **Plugins** tab
3. Open the **Add New Plugin** section
4. Install the **Head & Footer Code** plugin
## Initialize the widget
Next, under the **Tools** tab open **Head & Footer Code** option. Add the code below to the **HEAD Code** section:
```html
```
```html
```
## Save custom code
Click on the **Save Changes**. Navigate to your web application to make sure the widget is installed correctly.
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Search Bar to WordPress
description: Integrate Inkeep's search bar into your WordPress site for powerful content discovery.
keywords: WordPress search, site search, search integration, WordPress plugins, search implementation, site enhancement, search configuration, WordPress setup, content discovery, CMS integration, search functionality
sidebarTitle: Search Bar
------------------------
## What is WordPress
[WordPress](https://wordpress.com/) popular content management system (CMS) designed for creating and managing websites.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Install custom code plugin
This plugin is required to add custom code in order to create a widget.
1. Open WordPress admin panel
2. Select the **Plugins** tab
3. Open the **Add New Plugin** section
4. Install the **Head & Footer Code** plugin
## Creating the container
Add a container for the widget. You can do this using the built-in WordPress functionality.
1. Open the **Appearance** tab
2. Select **Editor** mode
3. Select the area to which you want to add the **SearchBar** widget
4. Add a **Custom HTML** block containing:
```html
```
**Example:**
## Initialize the widget
Next, under **Tools** go to the **Head & Footer Code** subsection. Add the code below to the **HEAD Code** section:
```html
```
```html
```
## Save custom code
Click on the **Save Changes**. Navigate to your web application to make sure the widget is installed correctly.
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Chat Button to Gatsby
description: Integrate Inkeep's chat button into your Gatsby site for real-time user assistance.
keywords: Gatsby integration, chat button, React integration, Gatsby chat, site integration, chat implementation, Gatsby components, chat configuration, Gatsby setup, user interaction, React components, static site chat
sidebarTitle: Chat Button
-------------------------
## What is Gatsby
[Gatsby](https://www.gatsbyjs.com/) is a React-based open source framework for creating websites.
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
Next, create an `InkeepChatButton.tsx` file for the [`Chat Button`](https://docs.inkeep.com/ui-components/react/chat-button) component.
```jsx title=".jsx"
import * as React from "react";
import { useEffect, useState } from "react";
export default function InkeepChatButton() {
const [ChatButton, setChatButton] = useState(null);
//...
// load the library asynchronously
useEffect(() => {
const loadChatButton = async () => {
try {
const { InkeepChatButton } = await import("@inkeep/cxkit-react");
setChatButton(() => InkeepChatButton);
} catch (error) {
console.error("Failed to load ChatButton:", error);
}
};
loadChatButton();
}, []);
const chatButtonProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ChatButton && ;
}
```
```tsx title=".tsx"
import * as React from "react";
import { useEffect, useState } from "react";
import type { InkeepChatButtonProps } from "@inkeep/cxkit-react";
export default function InkeepChatButton() {
const [ChatButton, setChatButton] =
useState<(e: InkeepChatButtonProps) => JSX.Element>();
//...
// load the library asynchronously
useEffect(() => {
const loadChatButton = async () => {
try {
const { InkeepChatButton } = await import("@inkeep/cxkit-react");
setChatButton(() => InkeepChatButton);
} catch (error) {
console.error("Failed to load ChatButton:", error);
}
};
loadChatButton();
}, []);
const chatButtonProps: InkeepChatButtonProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ChatButton && ;
}
```
For a full list of customizations, check out the [Chat Button](/ui-components/react/chat-button) documentation.
***
title: Add Search Bar to Gatsby
description: Integrate Inkeep's search bar into your Gatsby site for powerful content discovery.
keywords: Gatsby search, React search, search integration, Gatsby components, search implementation, site search, search configuration, Gatsby setup, content discovery, React components, static site search, search UI
sidebarTitle: Search Bar
------------------------
## What is Gatsby
[Gatsby](https://www.gatsbyjs.com/) is a React-based open source framework for creating websites.
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
Next, create an `InkeepSearchBar.tsx` file for the [`Search Bar`](https://docs.inkeep.com/ui-components/react/search-bar) component.
```jsx title=".jsx"
import * as React from "react";
import { useEffect, useState } from "react";
export default function InkeepSearchBar() {
const [SearchBar, setSearchBar] = useState(null);
//...
// load the library asynchronously
useEffect(() => {
const loadSearchBar = async () => {
try {
const { InkeepSearchBar } = await import("@inkeep/cxkit-react");
setSearchBar(() => InkeepSearchBar);
} catch (error) {
console.error("Failed to load SearchBar:", error);
}
};
loadSearchBar();
}, []);
const searchBarProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return SearchBar && ;
}
```
```tsx title=".tsx"
import * as React from "react";
import { useEffect, useState } from "react";
import type { InkeepSearchBarProps } from "@inkeep/cxkit-react";
export default function InkeepSearchBar() {
const [SearchBar, setSearchBar] =
useState<(e: InkeepSearchBarProps) => JSX.Element>();
//...
// load the library asynchronously
useEffect(() => {
const loadSearchBar = async () => {
try {
const { InkeepSearchBar } = await import("@inkeep/cxkit-react");
setSearchBar(() => InkeepSearchBar);
} catch (error) {
console.error("Failed to load SearchBar:", error);
}
};
loadSearchBar();
}, []);
const searchBarProps: InkeepSearchBarProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return SearchBar && ;
}
```
For a full list of customizations, check out the [Search Bar](/ui-components/react/search-bar) documentation.
***
title: Add Embedded Chat to Gatsby
description: Integrate Inkeep's embedded chat into your Gatsby site for seamless user interaction.
keywords: Gatsby chat, embedded chat, React integration, chat implementation, site enhancement, chat configuration, Gatsby setup, user interaction, React components, chat UI, embedded interface, static site chat
sidebarTitle: Embedded Chat
---------------------------
## What is Gatsby
[Gatsby](https://www.gatsbyjs.com/) is a React-based open source framework for creating websites.
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
Next, create an `InkeepEmbeddedChat.tsx` file for the [`Embedded Chat`](https://docs.inkeep.com/ui-components/react/in-page/embedded-chat) component.
```jsx title=".jsx"
import * as React from "react";
import { useEffect, useState } from "react";
export default function InkeepEmbeddedChat() {
const [EmbeddedChat, setEmbeddedChat] = useState(null);
// load the library asynchronously
useEffect(() => {
const loadEmbeddedChat = async () => {
try {
const { InkeepEmbeddedChat } = await import("@inkeep/cxkit-react");
setEmbeddedChat(() => InkeepEmbeddedChat);
} catch (error) {
console.error("Failed to load EmbeddedChat:", error);
}
};
loadEmbeddedChat();
}, []);
const embeddedChatProps = {
baseSettings,
aiChatSettings,
};
return EmbeddedChat && ;
}
```
```tsx title=".tsx"
import * as React from "react";
import { useEffect, useState } from "react";
import type { InkeepChatButtonProps } from "@inkeep/cxkit-react";
export default function InkeepEmbeddedChat() {
const [EmbeddedChat, setEmbeddedChat] = useState(null);
// load the library asynchronously
useEffect(() => {
const loadEmbeddedChat = async () => {
try {
const { InkeepEmbeddedChat } = await import("@inkeep/cxkit-react");
setEmbeddedChat(() => InkeepEmbeddedChat);
} catch (error) {
console.error("Failed to load EmbeddedChat:", error);
}
};
loadEmbeddedChat();
}, []);
const embeddedChatProps = {
baseSettings,
aiChatSettings,
};
return EmbeddedChat && ;
}
```
For a full list of customizations, check out the [Embedded Chat](/ui-components/react/in-page/embedded-chat) documentation.
***
title: Add Chat Button with Google Tag Manager
description: Learn how to integrate Inkeep's chat button using Google Tag Manager for seamless deployment without code changes.
keywords: Google Tag Manager integration, GTM chat button, tag management, GTM setup, chat implementation, tag configuration, GTM deployment, chat integration, analytics integration, no-code deployment, custom HTML tag, GTM workspace
sidebarTitle: Chat Button
-------------------------
## What is Google Tag Manager
Google Tag Manager (GTM) lets you manage and deploy custom JavaScript, without editing your website's code. This simplifies updates without needing developer involvement.
## How to integrate with Inkeep
To add the Inkeep Chat Button using Google Tag Manager (GTM), we'll use a modified version of the standard JavaScript snippet. This approach includes scoping, dynamic loading, and controlled initialization for GTM compatibility.
Here's the GTM-friendly version of the Chat Button snippet after grabbing your API information:
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Define the component in Google Tag Manager
1. Navigate to your [Google Tag Manager](https://tagmanager.google.com/) console
2. Select your workspace and navigate to the Tags section
3. Create a new Tag.
4. For Tag Configuration, choose **Custom HTML**. And upload the following for the Chat Button:
```html
```
5. Update this script with your API key and desired settings.
6. For Triggering, choose **All Pages**.
7. Click save to have the Chat Button appear on your GTM synced website
## Other Snippets
For the other integrations please refer to the JS Snippet examples in the UI Components Page section
* [Search Bar](/ui-components/js-snippet/search-bar)
* [Embedded Chat](/ui-components/js-snippet/in-page/embedded-chat)
* [Custom Trigger](/ui-components/js-snippet/custom-modal-trigger)
***
title: Add Chat Button to Zendesk Help Center
description: Add Inkeep's chat button to your Zendesk Help Center.
sidebarTitle: Chat Button
-------------------------
## What is Zendesk
[Zendesk](https://www.zendesk.com) is a customer service solution for handling support tickets.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Click the **Zendesk Products** in the top bar, then select **Guide**
2. Navigate to **Guide Admin**
3. Click **Customize** on the theme you want to edit
4. Click **Edit code**. Which will open theme code editor
In the **templates** section, find the `document_head.hbs` file and paste the code below:
```html
```
## Initialize the widget
Next, in the same file, paste the following code:
```html
```
## Save custom code
Click on the **Publish** button. Navigate to your web application to make sure the widget is installed correctly.
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Search Bar to Zendesk Help Center
description: Add Inkeep's search bar to your Zendesk Help Center.
keywords: Zendesk search, help center search, search integration, search bar implementation, Zendesk customization, search functionality, help center integration, search configuration, Zendesk setup, search enhancement
sidebarTitle: Search Bar
------------------------
## What is Zendesk
[Zendesk](https://www.zendesk.com) is a customer service solution for handling support tickets.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Click the **Zendesk Products** in the top bar, then select **Guide**
2. Navigate to **Guide Admin**
3. Click **Customize** on the theme you want to edit
4. Click **Edit code**. Which will open theme code editor
In the **templates** section, find the `document_head.hbs` file and paste the code below:
```html
```
## Creating the container
Add a container for the widget:
1. Open the `home_page.hbs` and `section_page.hbs` files
2. Add an element with the **ID** - `inkeepSearchBarNav` and `inkeepSearchBarHero`
3. Apply the below **before** -> **after** changes to `home_page.hbs`:
```html title="before"
{{ t 'search' }}
{{search submit=false instant=settings.instant_search class='search
search-full'}}
```
```html title="after"
```
4. Apply the below **before** -> **after** changes to `section_page.hbs`:
```html title="before"
{{breadcrumbs}}
{{search scoped=settings.scoped_kb_search submit=false}}
```
```html title="after"
```
5. Click **Publish**
## Custom CSS
Zendesk allows you to add a custom css file to the **assets** directory:
1. Create an `inkeep-styles.css` stylesheet and paste in the below::
```css title="inkeep-styles.css"
[data-theme="light"] .ikp-search-bar__button {
background: white;
border-radius: 6px;
width: 100%;
}
```
2. In the theme code editor, click **Add**
3. Click on **Asset**
4. Upload the created css file
## Initialize the widget
Next, go back to the `header.hbs` file and add the following code at the end of the file:
```html
```
## Different styles between hero and nav bar
You can conditionally apply different stylesheets to the navigation bar or hero search bar.
```js
// ...
const inkeepSearchBarNavStyles = "{{asset 'inkeep-styles.css'}}"; // <--- should match the uploaded file
const inkeepSearchBarHeroStyles = "{{asset 'inkeep-hero-styles.css'}}"; // <--- should match the uploaded file
const getStyles = (targetElementId) => {
return {
key: `style-${targetElementId}`,
type: "link",
value:
targetElementId === "inkeepSearchBarHero"
? inkeepSearchBarHeroStyles
: inkeepSearchBarNavStyles,
};
};
const inkeepWidget = Inkeep.SearchBar(targetElementId, {
baseSettings: {
apiKey: "INKEEP_API_KEY", // required
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
theme: {
styles: getStyles(targetElementId),
},
},
modalSettings: {
// optional settings
},
searchSettings: {
// optional settings
},
aiChatSettings: {
// optional settings
aiAssistantAvatar: "https://mydomain.com/mylogo", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
},
});
// ...
```
## Save custom code
Click on the **Publish** button. Navigate to your web application to make sure the widget is installed correctly.
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Chat and Search to Zendesk Help Center
description: Add Inkeep's chat button and search bar to your Zendesk Help Center.
keywords: Zendesk integration, chat and search, help center integration, Zendesk customization, combined integration, chat implementation, search implementation, help center setup, Zendesk configuration, UI enhancement
sidebarTitle: Chat Button & Search Bar
--------------------------------------
## What is Zendesk
[Zendesk](https://www.zendesk.com) is a customer service solution for handling support tickets.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Click the **Zendesk Products** in the top bar, then select **Guide**
2. Navigate to **Guide Admin**
3. Click **Customize** on the theme you want to edit
4. Click **Edit code**. Which will open theme code editor
In the **templates** section, find the `document_head.hbs` file and paste the code below:
```html
```
## Creating the container
Add a container for the widget:
1. Open the `home_page.hbs` and `section_page.hbs` files
2. Add an element with the **ID** - `inkeepSearchBarNav` and `inkeepSearchBarHero`
3. Apply the below **before** -> **after** changes to `home_page.hbs`:
```html title="before"
{{ t 'search' }}
{{search submit=false instant=settings.instant_search class='search
search-full'}}
```
```html title="after"
```
4. Apply the below **before** -> **after** changes to `section_page.hbs`:
```html title="before"
{{breadcrumbs}}
{{search scoped=settings.scoped_kb_search submit=false}}
```
```html title="after"
```
5. Click **Publish**
## Custom CSS
Zendesk allows you to add a custom css file to the **assets** directory:
1. Create an `inkeep-styles.css` stylesheet and paste in the below::
```css title="inkeep-styles.css"
[data-theme="light"] .ikp-search-bar__button {
background: white;
border-radius: 6px;
width: 100%;
}
```
2. In the theme code editor, click **Add**
3. Click on **Asset**
4. Upload the created css file
## Initialize the widgets
Next, go back to the `header.hbs` file and add the following code at the end of the file:
```html
```
## Different styles between hero and nav bar
You can conditionally apply different stylesheets to the navigation bar or hero search bar.
```js
// ...
const inkeepSearchBarNavStyles = "{{asset 'inkeep-styles.css'}}"; // <--- should match the uploaded file
const inkeepSearchBarHeroStyles = "{{asset 'inkeep-hero-styles.css'}}"; // <--- should match the uploaded file
const getStyles = (componentType, targetElementId) => {
if (componentType === "ChatButton") {
return [];
}
return targetElementId === "inkeepSearchBarHero"
? [{ key: "main", type: "link", value: inkeepSearchBarHeroStyles }]
: [{ key: "main", type: "link", value: inkeepSearchBarNavStyles }];
};
const config = {
// ...other settings,
baseSettings: {
// ...other baseSettings,
theme: {
styles: getStyles(componentType, targetElementId),
},
},
};
const inkeepWidget =
componentType === "ChatButton"
? Inkeep.ChatButton(config)
: Inkeep.SearchBar(targetElementId, config);
// ...
```
## Save custom code
Click on the **Publish** button. Navigate to your web application to make sure the widget is installed correctly.
For a full list of customizations, check out the [Common Settings](/ui-components/common-settings).
***
title: Add Embedded Chat to Zendesk Help Center
description: Add Inkeep's embedded chat to your Zendesk Help Center.
keywords: Zendesk chat, embedded chat, help center chat, chat integration, Zendesk customization, chat implementation, help center integration, chat configuration, Zendesk setup, chat enhancement
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## What is Zendesk
[Zendesk](https://www.zendesk.com) is a customer service solution for handling support tickets.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Click the **Zendesk Products** in the top bar, then select **Guide**
2. Navigate to **Guide Admin**
3. Click **Customize** on the theme you want to edit
4. Click **Edit code**. Which will open theme code editor
In the **templates** section, find the `document_head.hbs` file and paste the code below:
```html
```
## Creating a custom page
1. Click on **Add**
2. Click on **Custom page**
3. Specify a name for the custom page - `ask-ai`
4. Click on **Add custom page**
5. Add the code below to a new file (`ask_ai.hbs`):
```html title="ask_ai.hbs"
```
## Custom CSS (optional)
Zendesk allows you to add a custom css file to the **assets** directory:
1. Create an `inkeep-styles.css` stylesheet and paste in the below:
```css title="inkeep-styles.css"
[data-theme="light"] .ikp-search-bar__button {
background: white;
border-radius: 6px;
width: 100%;
}
```
2. In the theme code editor, click **Add**
3. Click on **Asset**
4. Upload the created css file
## Initialize the widget
Next, go back to the `header.hbs` file and add the following code at the end of the file:
```html
```
## Save custom code
Click on the **Publish** button. Navigate to your web application to make sure the widget is installed correctly.
For a full list of customizations, check out the [Embedded Chat](/ui-components/js-snippet/in-page/embedded-chat) documentation.
***
title: Add Intelligent Form to Zendesk Help Center
description: Add Inkeep's intelligent form to your Zendesk Help Center.
keywords: Zendesk form, intelligent form, help center form, form integration, Zendesk customization, form implementation, help center integration, form configuration, Zendesk setup, form enhancement
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## What is Zendesk
[Zendesk](https://www.zendesk.com) is a customer service solution for handling support tickets.
## Concepts
* Learn how to deploy an Inkeep AI Intelligent Form on your Zendesk Help Center
* Learn how to configure the Intelligent Form component to attempt to answer customer questions directly
* Learn how to create a new ticket with the Intelligent Form data including prefilled fields like name, email, subject, priority, and additional details
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Navigate to the theme code editor
1. Click the **Zendesk Products** in the top bar, then select **Guide**
2. Navigate to **Guide Admin**
3. Click **Customize** on the theme you want to edit
4. Click **Edit code**. Which will open theme code editor
## Create a custom page
1. Click on **Add**
2. Click on **Custom page**
3. Specify a name for the custom page - `support_form`
4. Click on **Add custom page**
5. Add the code below to a new file (`support_form.hbs`):
```html title="support_form.hbs"
```
## Initialize the component
Next add the following script tag at the end of the file to initialize the Intelligent Form component.
```html title="support_form.hbs"
```
## Save custom code
Click on the **Publish** button. Navigate to your new page to make sure the form renders correctly. You can find the url for the new page by clicking on the kebab menu next to the page name in the left sidebar and selecting `Custom Page URL`.
For a full list of customizations, check out the [Intelligent Form](/ui-components/js-snippet/intelligent-form) documentation.
## Handling form submissions to create Zendesk tickets
Please refer to the [Zendesk Ticket Creation](/integrations/zendesk/ticket-creation) guide for more information on how to handle form submissions to create Zendesk tickets.
***
title: Zendesk Ticket Creation
description: Configure ticket creation in Zendesk with Inkeep.
keywords: Zendesk integration, ticket creation, support automation, Zendesk workflow, ticket management, support configuration, Zendesk setup, automated support, ticket handling, support integration
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview:
* Configure and deploy an endpoint that will process the form data.
* Call the endpoint from the `onSubmit` function of your Inkeep widget. Example implementation can be found [here](https://github.com/inkeep/intelligent-support-form/blob/b0748084da4f5a0089a0fff1f723fe1740c805d6/app/form-components/IntelligentForm.tsx#L78-L139)
## Official Zendesk API Reference
For complete details on available endpoints and ticket parameters, see the [official Zendesk Tickets API reference](https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/).
## Basic Ticket Creation
This code must be executed in a secure server environment. Never expose your
Zendesk API tokens in client-side code as they contain sensitive permissions
that could be misused if compromised. Example endpoint for creating a new
ticket can be found
[here](https://github.com/inkeep/intelligent-support-form/blob/main/app/api/create-ticket/route.ts)
The following example demonstrates how to call the Zendesk Tickets API to create a new ticket. You can copy this code into your project and modify it to suit your needs:
```tsx
/**
* Zendesk Ticket Creation Example
*
* This example demonstrates how to create a ticket in Zendesk via their REST API.
*
* Required environment variables:
* - ZENDESK_SUBDOMAIN: Your Zendesk subdomain (e.g., 'mycompany' from 'mycompany.zendesk.com')
* - ZENDESK_EMAIL: Email address for authentication
* - ZENDESK_API_TOKEN: Zendesk API token
*/
// Interface for requester information
export interface RequesterInfo {
email: string;
name?: string;
phone?: string;
external_id?: string;
details?: string;
[key: string]: unknown;
}
// Interface for the ticket creation parameters
export interface TicketCreationParams {
subject: string;
comment: {
body: string;
html_body?: string;
public?: boolean;
};
priority?: "urgent" | "high" | "normal" | "low";
status?: "new" | "open" | "pending" | "hold" | "solved" | "closed";
type?: "problem" | "incident" | "question" | "task";
tags?: string[];
// User and organization information
requester_id?: number;
requester?: RequesterInfo;
submitter_id?: number;
assignee_id?: number;
organization_id?: number;
group_id?: number;
collaborator_ids?: number[];
collaborators?: Array; // Can be emails or objects with name/email
// Additional fields
custom_fields?: Array<{
id: number;
value: string | number | boolean | string[];
}>;
due_at?: string; // ISO 8601 format
via?: {
channel: string;
source?: {
to?: {
name?: string;
address?: string;
};
from?: {
name?: string;
address?: string;
};
rel?: string;
};
};
ticket_form_id?: number;
}
// Interface for Zendesk API response
export interface ZendeskTicketResponse {
ticket: {
id: number;
subject: string;
description: string;
status: string;
priority: string;
requester_id?: number;
organization_id?: number;
[key: string]: unknown;
};
[key: string]: unknown;
}
/**
* Create a ticket in Zendesk
*
* @param ticketData - Object containing the ticket information
* @returns A promise that resolves to the created ticket data
*/
export async function createTicket(
ticketData: TicketCreationParams
): Promise {
// Get environment variables
const subdomain = process.env.ZENDESK_SUBDOMAIN;
const email = process.env.ZENDESK_EMAIL;
const apiToken = process.env.ZENDESK_API_TOKEN;
// Validate environment variables
if (!subdomain || !email || !apiToken) {
throw new Error(
"Missing required environment variables. Please ensure ZENDESK_SUBDOMAIN, ZENDESK_EMAIL, and ZENDESK_API_TOKEN are set."
);
}
// Base URL for Zendesk API
const baseUrl = `https://${subdomain}.zendesk.com/api/v2`;
// Create the ticket payload
const ticketPayload = {
ticket: {
...ticketData,
},
};
try {
const response = await fetch(`${baseUrl}/tickets.json`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Basic ${btoa(`${email}/token:${apiToken}`)}`,
},
body: JSON.stringify(ticketPayload),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(`Failed to create ticket: ${JSON.stringify(errorData)}`);
}
return await response.json();
} catch (error) {
console.error("Error creating Zendesk ticket:", error);
throw error;
}
}
// Example usage
async function example() {
try {
// First, set your environment variables
// In a real application, these would be set in your environment
process.env.ZENDESK_SUBDOMAIN = "your-subdomain";
process.env.ZENDESK_EMAIL = "your-email@example.com";
process.env.ZENDESK_API_TOKEN = "your-api-token";
const ticketData: TicketCreationParams = {
subject: "Support needed with API integration",
comment: {
body: "I need help connecting your API with our system. Please assist.",
public: true,
},
// Associate ticket with an existing user by email
requester: {
email: "customer@example.com",
name: "John Customer",
},
// Associate with organization
organization_id: 123456,
priority: "normal",
type: "question",
tags: ["api", "integration", "support"],
custom_fields: [
{
id: 123456, // Replace with actual custom field ID
value: "Some custom value",
},
],
};
// Create a ticket
const result = await createTicket(ticketData);
console.log("Ticket created successfully:", result);
} catch (error) {
console.error("Error in example:", error);
}
}
```
## Prefill a Zendesk ticket form
Alternatively, you can use the callback function to prefill a Zendesk ticket form with the user's questions. See the [Zendesk documentation](https://support.zendesk.com/hc/en-us/articles/4408839114522-Creating-pre-filled-ticket-forms) for more details on how to create a pre-filled ticket form.
Example:
```tsx
const aiChatSettings: InkeepAIChatSettings = {
// ...
getHelpOptions: [
{
icon: { builtIn: 'IoHelpBuoyOutline' },
name: 'Create a support ticket',
action: {
type: 'invoke_callback',
callback: ({ conversation }) => {
try {
const { messages, userProperties } = conversation
// List the user's questions
const description = messages.length > 0 ?
"Here's what I need help with:\n\n" +
messages
.filter((message) => message.role === "user")
.map((message) => message.content)
.join("\n") : ''
const userEmail = String(userProperties?.['email'] || '')
const params = new URLSearchParams()
params.set('ticket_form_id', 'REPLACE_WITH_YOUR_FORM_ID') // if you have multiple forms pass the form id here, otherwise omit
params.set('tf_description', description) // prefill the description field with the user's questions
params.set('tf_subject', 'Support request') // prefill the subject field with a default subject
params.set('tf_REPLACE_WITH_YOUR_USER_EMAIL_FIELD_ID', userEmail) // if you know the user's email, you can pass it here
const url = `https://REPLACE_WITH_YOUR_SUBDOMAIN.zendesk.com/hc/en-us/requests/new?${params.toString()}`
window.open(url, '_blank')
} catch (error) {
console.error('Error opening support form', error)
}
},
},
},
],
};
```
***
title: Add Chat Button to Help Scout
description: Integrate Inkeep's chat button into your Help Scout knowledge base for real-time user assistance.
keywords: Help Scout integration, chat button, knowledge base chat, Help Scout customization, chat implementation, documentation enhancement, chat configuration, Help Scout setup, support tools, user assistance
sidebarTitle: Chat Button
-------------------------
## What is Help Scout
[Help Scout](https://www.helpscout.com/) is a customer service solution for handling support tickets.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Click the **Manage** dropdown in the top bar, then select **Docs**
2. Select the knowledge base you would like to add the widget to
3. Click **Custom Code** in the left sidebar
In the **Insert `` Code** section, copy and paste the code below:
```html
```
## Initialize the widget
Next, in the same section, paste the following code:
```html
```
## Save custom code
Click on the **Save** button. Navigate to your help center to make sure the widget is installed correctly.
For a full list of customizations, check out the [Chat Button](/ui-components/js-snippet/chat-button) documentation.
***
title: Add Search Bar to Help Scout
description: Integrate Inkeep's search bar into your Help Scout knowledge base for powerful content discovery.
keywords: Help Scout search, knowledge base search, search integration, Help Scout customization, search implementation, documentation enhancement, search configuration, Help Scout setup, support tools, content discovery
sidebarTitle: Search Bar
------------------------
## What is Help Scout
[Help Scout](https://www.helpscout.com/) is a customer service solution for handling support tickets.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Click the **Manage** dropdown in the top bar, then select **Docs**
2. Select the knowledge base you would like to add the widget to
3. Click **Custom Code** in the left sidebar
In the **Insert `` Code** section, copy and paste the code below:
```html
```
## Initialize the widget
Next, in the same section, paste the following code:
```html
```
## Save custom code Click on the **Save** button. Navigate to your help
center to make sure the widget is installed correctly.
For a full list of customizations, check out the [Search Bar](/ui-components/js-snippet/search-bar) documentation.
***
title: Add Chat and Search to Help Scout
description: Integrate Inkeep's chat button and search bar into your Help Scout knowledge base for enhanced user experience.
keywords: Help Scout integration, chat and search, knowledge base tools, Help Scout customization, combined integration, chat implementation, search implementation, documentation enhancement, support tools, UI integration
sidebarTitle: Chat Button & Search Bar
--------------------------------------
## What is Help Scout
[Help Scout](https://www.helpscout.com/) is a customer service solution for handling support tickets.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Connect the script
1. Click the **Manage** dropdown in the top bar, then select **Docs**
2. Select the knowledge base you would like to add the widget to
3. Click **Custom Code** in the left sidebar
In the **Insert `` Code** section, copy and paste the code below:
```html
```
## Initialize the widget
Next, in the same section, paste the following code:
```html
```
## Save custom code
Click on the **Save** button. Navigate to your help center to make sure the widget is installed correctly.
For a full list of customizations, check out the [Common Settings](/ui-components/common-settings).
***
title: Add an AI chatbot to your Discord server
sidebarTitle: Discord
keywords: Discord integration, Discord bot, AI chatbot, community support, server integration, Discord automation, custom bot responses, auto-reply bot, Discord server setup, team collaboration, community management, Discord channels, bot customization, Discord support, AI assistant integration
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
You can add Inkeep as a [Discord](https://discord.com/) app to your Discord community or team's internal support, solutions engineering, or other channels.
## Get Server ID
To configure the bot, you'll need your Discord Server ID:
1. Open Discord in your [browser](https://discord.com/app).
2. Select the target server in the left navigation bar
3. Copy the `{SERVER_ID}` from the browser's navigation bar. The URL will be in the format of `https://discord.com/channels/{SERVER_ID}/{CHANNEL_ID}`
4. Alternatively, you can find the ID in server settings.
## Create Assistant
To use the Inkeep Discord bot, we first need to register it as an assistant.
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Assistants** tab within the desired project
3. Click on **Create assistant**
4. From the dropdown menu, choose **Discord**
5. Fill in the required fields **Name** and **Server ID**.
6. (Optional) If you'd like the bot to *only* reply to tags in a specific channel, specify the channel ID in **Only reply in selected Channel IDs** under **Advanced Settings**. By default, the bot is able to be tagged in any public channel or private channels it is added to.
7. Click on **Create**
## Add to Server
To install the Inkeep Discord bot in your server:
1. Click [here](https://install.inkeep.com/ask-discord)
2. Select the desired server in the **ADD TO SERVER** dropdown
3. Review the permissions and click **Continue**
{" "}
The Discord bot can be added to any type of channel, including forums or
normal chat-style channels. For private channels, ensure that the bot is added
as a member of the channel.{" "}
To start using the bot, tag **@Ask Inkeep** in a message with your question. You or your users can do this in any channel.
## Create a dedicated channel (optional)
We recommend having a dedicated channel for team or community members to ask questions to the bot.
1. Create an `β¨ask-ai` or similar channel.
2. Ask an example question in the channel to demonstrate how to use the bot. Type **@Ask Inkeep** before your question and hit enter.
3. The Inkeep bot will automatically create a new thread (if [enabled](https://support.discord.com/hc/en-us/articles/4403205878423-Threads-FAQ#h_01FBM7FY3D1J3WC3TP71EC7JRF)) and reply to the user.
4. For follow-up questions, the user **must** tag the bot again.
Since Discord does not have the ability to pin a channel, consider:
* Making an announcement in your `#general` or other relevant channels linking users to it
* Adding guidance on how to use the bot in a pinned message on your main channel or incorporate as part of your onboarding experience.
## Customize the Display Name
Instead of using **@Ask Inkeep**, you can customize the bot name from Discord.
1. Have at least one message that tags **@Ask Inkeep**
2. In that message, *right* click on **@Ask Inkeep**
3. Select **Change Nickname**
4. Enter your desired name for the bot, e.g. `Ask CompanyAI`
The bot can now be tagged via **@Ask CompanyAI** and all existing instances of **@Ask Inkeep** will be updated.
Unfortunately, Discord does not currently support custom avatars or icons
for published bots.
## Customize the bot's default responses
You can configure the bot to send a default responses to users in different scenarios.
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Assistants** tab within the desired project
3. Select the Discord assistant
4. Expand **Advanced Settings**
5. Under **Custom Responses**, see the list of responses you can configure
6. Click **Update**
7. Your Discord bot will now use these responses.
## Tag a team member
Sometimes, you want users to be able to escalate to a human for help if the bot is not able to help.
To make this flow seamless, you can configure the Discord assistant to show **Mark as resolved β
** and **Ask for help π** buttons instead of the default π π.
When a user clicks on **Ask for help π**, the bot can tag users, roles, or other bots.
To set up:
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Assistants** tab within the desired project
3. Select the Discord assistant
4. Expand **Advanced Settings**
5. Under **When a user leaves negative feedback...**, click the dropdown menu
6. Select **Tag a team member**
7. Specify the **User IDs**, **Role IDs**, or **Bot IDs** you'd like to tag
You can get the ID of a Bot or User by right-clicking on a profile on Discord and clicking on **Copy User ID** or **Copy group ID**.
For a Role, you'll need to:
1. Navigate to the server
2. On the top left of the Discord app, click on your server name
3. Click on **Server Settings**
4. Navigate to **Roles** from the left side pane
5. Click on **...** next to the desired role and select **Copy Role ID**
## Auto-reply mode
Instead of requiring users to tag the bot with `@Ask Inkeep`, you can configure the Discord bot to automatically reply to all new threads in specific channels. This can be useful for dedicated support channels or community Q\&A forums.
To set up auto-reply mode:
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Assistants** tab within the desired project
3. Select the Discord assistant
4. Expand **Advanced Settings**
5. In the **Auto-reply Channel IDs** field, add the channel IDs where you want the bot to auto-reply to new threads
6. (Optional) Customize the bot's behavior with these settings:
* **Reply message**: Enter a custom initial message for the bot to use when it's tagged or auto-replies
* **Is AI Draft Mode enabled?**: Adjusts the bot's tone for generating draft responses for team review
* **Is human reviewing conversations?**: Informs users that team members are monitoring conversations
7. Click **Save** to apply the changes
We generally don't recommend enabling auto-reply for all channels, as it's
beneficial for users to get accustomed to tagging the bot, especially for
follow-up questions.
### Limiting bot responses to specific channels
If you want to restrict the bot to only respond in certain channels:
1. In the **Advanced Settings**, find the **Only reply in selected Channel IDs** field
2. Add the channel IDs where you want the bot to be active
3. The bot will now only respond when tagged in these specified channels
This can be useful for managing the bot's presence in large servers or for creating dedicated AI assistance channels.
We recommend creating a custom bot, e.g. `@Triaging Bot`, that contains the
logic you'd like to use for triggering custom down-stream workflows.
Need to make Discord SEO-friendly? Try [Answer
Overflow](https://www.answeroverflow.com?utm=inkeep) βοΈ (partner).
***
title: Add Inkeep to Slack Community
description: Integrate Inkeep's AI assistant into your Slack community for automated support and enhanced member engagement.
keywords: Slack assistant, community support, Slack bot, AI assistant, community management, automated support, Slack automation, member engagement, community tools, Slack app, community assistance
sidebarTitle: Community
-----------------------
## Overview
You can add Inkeep as a Slack bot to your Slack community to help scale support to your users.
## Get Workspace ID
To configure the bot, you'll need your Slack Workspace ID:
1. Open the Slack app in your [browser](https://app.slack.com/client).
2. Select the target workspace
3. Copy the `{WORKSPACE_ID}` from the browser's navigation bar. The URL will be in the format `https://app.slack.com/client/{WORKSPACE_ID}/{CHANNEL_ID}`. **Workspace ID typically starts with a `T` and is in the format of `TXXXXXXXXXX`.** Channel IDs are typically in the format of `CXXXXXXXXXX`.
4. Alternatively, you can find the ID in the workspace settings.
## Create Assistant
To use the Inkeep Slack bot, we first need to register it as an assistant.
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Assistants** tab within the desired project
3. Click on **Create assistant**
4. From the dropdown menu, choose **Slack**
5. Fill in the required fields **Name** and **Workspace ID**.
6. Click on **Create**
If you already have an existing Inkeep Slack assistant for a Slack workspace, then de-select **Is default for workspace** during the creation of a new assistant. Only one assistant can be the default for a workspace.
After creating the new assistant, click on **Advanced Settings** and specify the Channel IDs (format `CXXXXXXXXXX`) the bot is able to respond in under **Enabled for Channels**.
This is only required if you need Inkeep Slack bots that behave differently in different channels or map to different projects.
## Add to workspace
To install the Inkeep Slack bot in your workspace:
1. Click [here](https://install.inkeep.com/ask-slack)
2. Select the desired workspace
3. Confirm the installation.
### Create a channel (optional)
If you don't yet have a channel you'd like to add Inkeep to, you can create an `β¨ask-ai` or similarly named channel. Move or pin it to the appropriate sections in your workspace for visibility.
### Add to channels
Open the workspace you added the **Ask Inkeep** bot to.
Navigate to the channel you'd like to add Inkeep to.
Type `@Ask Inkeep` with an example question:
```
@Ask Inkeep How do I get started?
```
**Confirm** Slack's prompt to add the bot to the channel.
Repeat the steps for any other desired channels.
The "Ask Inkeep" bot **must** be added as a member of the channel.
### Send a direct message
Create a new message in Slack addressed to `@Ask Inkeep` or follow the steps below:
1. Find **Ask Inkeep** underneath the **Apps** section
2. Click on the **Messages** tab
3. Type a message and click **Send**
If you see a message saying, `Sending messages to this app has been turned off.`, please restart the Slack app to enable direct messages.
If you are not getting a response from the bot, please reinstall the Slack bot by using the `Install bot` button in your Slack Assistant Settings page.
Donβt uninstall the app, just reinstall it so it is kept in all your channels. This will also enable it for everyone else in your Slack workspace.
### Use as an auto-reply bot
Instead of requiring a user to tag the bot with `@Ask Inkeep`, you can configure the Slack bot to automatically reply to all new top-level messages in specified channels.
To configure:
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Assistants** tab within the desired project
3. Select the assistant
4. Expand **Advanced Settings**
5. Configure the following:
* **Auto-reply in the below channels**: Specify the channel IDs where you want the bot to auto-reply
* **Reply message (optional)**: Enter a custom initial message for the bot to use when it's tagged or auto-replies
6. (Optional) Click on **Human Reviewing Conversations** if you'd like to modify the tone of the bot to inform users that team members are actively reviewing and monitoring conversations.
7. Click **Save** to apply the changes
## Customize your bot
You can customize the name of the bot, the image used with it, and the default responses it sends.
### Upload an organization avatar (required)
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Settings** tab at root of your Inkeep organization (`https://portal.inkeep.com/{orgAlias}/settings`)
3. Under **Avatar**, select **Choose File** or if there's an existing file, hover over the existing avatar and click **Change**
4. Upload a PNG (preferred) or JPG file you'd like to use as your avatar. Recommended dimension: 512x512. Note that SVGs are not supported by Slack.
### Configure the bot name
1. In your Slack workspace, click on **Add apps** underneath the **Apps** section in your sidebar
2. Select **Ask Inkeep**
3. Click on **Configuration**
4. Scroll to **Bot User** section and click on **Edit**
5. Specify the desired name of the bot, e.g. `Ask CompanyAI`
Now, you and your users will be able to tag the bot using this name, e.g. `@Ask CompanyAI`.
When typing `@` and in a few other places, Slack will still display the default Inkeep icon. However, any posts made by the bot will show your actual avatar. Your custom name will always be displayed.
### Configure default responses
You can configure the bot to send a default responses to users in different scenarios.
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Assistants** tab within the desired project
3. Select the assistant
4. Expand **Advanced Settings**
5. Under **Custom Responses**, see the list of responses you can configure
6. Click **Update**
7. Your bot will now use these responses.
## Tag a team member
Sometimes, you want users to be able to escalate to a human for additional help.
To make this flow seamless, you can configure your bot to show **Mark as resolved β
** and **Ask for help π** buttons instead of the default π π buttons at the end of messages.
When a user clicks on **Ask for help π**, the bot can tag users, user groups, or other bots.
To set up:
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Assistants** tab within the desired project
3. Select the Slack assistant
4. Expand **Advanced Settings**
5. Under **When a user leaves negative feedback...**, click the dropdown menu
6. Select **Tag a team member**
7. Specify the **User IDs**, **Group IDs**, or **Bot IDs** you'd like to tag
You can get the IDs by left-clicking on a profile on Slack, selecting the more options button (often represented as three dots), and clicking on **Copy member ID** or **Copy group ID**. To create a group of users on Slack, see [this](https://slack.com/help/articles/212906697-Create-a-user-group) guide.
We recommend creating a custom bot, e.g. `@Triaging Bot`, that contains the logic you'd like to use for triggering custom down-stream workflows.
***
title: Add AI Chat to your Discourse community
sidebarTitle: Discourse
keywords: Discourse integration, community AI chat, Discourse widget, theme component, content security policy, CSP configuration, Discourse customization, community platform integration, AI assistant integration, Discourse theme, Material Design theme, widget customization, community support, Discourse plugin
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
You can add AI chat as a [Discourse](https://www.discourse.org/) widget to your Discourse community.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Create Theme-Component
To use the AI chat, first we need to create a theme-component on the Discourse platform.
1. Click the **Admin** section in the sidebar menu
2. Open the **Customize** tab
3. Open the **Themes** subsection
4. Now, select the **Components** tab
5. Click on **Install**
6. Open the **Create new** menu and specify a name for the component
7. Click on **Create**
Example:
## Customizing Theme-Component
Next, in the created theme component menu, click **Edit CSS/HTML** to customize the widget.
### Initialize the widget
Click on the **Head** section and paste the following scripts:
```html title="Base Theme"
```
```html title="Material Design Theme"
```
Optional: click **preview** to test out the widget.
Click on the **Save**.
## Apply to themes
In the **Include component on these themes** setting, specify the themes in which the widget will be used.
Alternatively, you can create and specify your own theme.
## Allow list from Content Security Policy (CSP)
If you are using a Discourse version earlier than `3.3.0.beta1` you may need to allow-list the Inkeep script by modifying the Content Security Policy (CSP). In version `3.3.0.beta1` or later external scripts should work without additional configuration, see [here](https://meta.discourse.org/t/mitigate-xss-attacks-with-content-security-policy/104243#csp-and-third-party-integrations-8) for more details:
1. Click the **Admin** section in the sidebar menu
2. Open the **Settings** tab
3. Open the **Security** section
4. Add `https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js` to the **content security policy script src** setting
5. Enable **content security policy strict dynamic** setting
Example:
Go back to the main community page and reload the page.
***
title: Add AI Chat to your Bettermode community
sidebarTitle: Bettermode
keywords: Bettermode integration, community AI chat, Bettermode widget, community platform, developer portal, custom code integration, widget customization, community support, AI assistant integration, Bettermode app, dark mode support, community tools, chat widget, Bettermode customization
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
You can add AI chat as a [Bettermode](https://bettermode.com/) widget to your Bettermode community.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
## Create App
To use the AI chat, first we need to create an application on the Bettermode platform.
1. Open the Bettermode [Developer Portal](https://developers.bettermode.com/portal)
2. Click on **Create a new app**
3. Specify a name for the integration, example: **Inkeep Widget**
4. Select your community from the drop-down menu below
5. Click on **Create app**
Result:
{" "}
## Customizing App
Next, you need to go to the app you created and customize the widget.
### Initialize the widget
Click on the **Custom code** section and add the following script to the `Custom code for ` area:
```html
```
```html
```
Click on the **Test and publish** section and click **Publish**.
## Install App
Open community settings, then open the **Apps** section. Select the app you created.
Go back to the main community page and reload the page.
***
title: Add Chat Button to Next.js
description: Integrate Inkeep's chat button into your Next.js application for real-time user assistance.
keywords: Next.js integration, chat button, React integration, Next.js chat, app integration, chat implementation, React components, chat configuration, Next.js setup, user interaction, server components
sidebarTitle: Chat Button
-------------------------
## What is Next.js
[Next.js](https://nextjs.org/) is a React full-stack app development framework. You can use Inkeep's React component library to Add AI Search & Chat functionality to apps or documentation and marketing sites built with Next.js.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
NEXT_PUBLIC_INKEEP_API_KEY="INKEEP_API_KEY"
```
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
Next, create an `InkeepChatButton.tsx` file for our [`Chat Button`](/ui-components/react/chat-button) component.
For Next.js apps that use **App Router**, use the `"use client"` directive at the top of the file to load the widget client side.
```jsx title=".jsx"
import dynamic from "next/dynamic";
const ChatButton = dynamic(
() => import("@inkeep/cxkit-react").then((mod) => mod.InkeepChatButton),
{
ssr: false,
}
);
function InkeepChatButton() {
//...
const chatButtonProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ;
}
export default InkeepChatButton;
```
```tsx title=".tsx"
import dynamic from "next/dynamic";
import { InkeepChatButtonProps } from "@inkeep/cxkit-react";
const ChatButton = dynamic(
() => import("@inkeep/cxkit-react").then((mod) => mod.InkeepChatButton),
{
ssr: false,
}
);
function InkeepChatButton() {
//...
const chatButtonProps: InkeepChatButtonProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ;
}
export default InkeepChatButton;
```
For a full list of customizations, check out the [Chat Button](/ui-components/react/chat-button) documentation.
***
title: Add Search Bar to Next.js
description: Integrate Inkeep's search bar into your Next.js application for powerful content discovery.
keywords: Next.js search, React search, search integration, Next.js components, search implementation, app search, search configuration, Next.js setup, content discovery, React components, server components
sidebarTitle: Search Bar
------------------------
## What is Next.js
[Next.js](https://nextjs.org/) is a React full-stack app development framework. You can use Inkeep's React component library to Add AI Search & Chat functionality to apps or documentation and marketing sites built with Next.js.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
NEXT_PUBLIC_INKEEP_API_KEY="INKEEP_API_KEY"
```
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
Next, create an `InkeepSearchBar.tsx` component file for our [`Search Bar`](/ui-components/react/search-bar) component.
For Next.js apps that use **App Router**, use the `"use client"` directive at the top of the file to load the widget client side.
```jsx title=".jsx"
import dynamic from "next/dynamic";
const SearchBar = dynamic(
() => import("@inkeep/cxkit-react").then((mod) => mod.InkeepSearchBar),
{
ssr: false,
}
);
function InkeepSearchBar() {
//...
const searchBarProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ;
}
export default InkeepSearchBar;
```
```tsx title=".tsx"
import dynamic from "next/dynamic";
import { InkeepSearchBarProps } from "@inkeep/cxkit-react";
const SearchBar = dynamic(
() => import("@inkeep/cxkit-react").then((mod) => mod.InkeepSearchBar),
{
ssr: false,
}
);
function InkeepSearchBar() {
//...
const searchBarProps: InkeepSearchBarProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ;
}
export default InkeepSearchBar;
```
For a full list of customizations, check out the [Search Bar](/ui-components/react/search-bar) documentation.
***
title: Add Embedded Chat to Next.js
description: Integrate Inkeep's embedded chat into your Next.js application for seamless user interaction.
keywords: Next.js chat, embedded chat, React integration, chat implementation, app enhancement, chat configuration, Next.js setup, user interaction, React components, chat UI, embedded interface, server components
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## What is Next.js
[Next.js](https://nextjs.org/) is a React full-stack app development framework. You can use Inkeep's React component library to Add AI Search & Chat functionality to apps or documentation and marketing sites built with Next.js.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
NEXT_PUBLIC_INKEEP_API_KEY="INKEEP_API_KEY"
```
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
Next, create an `InkeepEmbeddedChat.tsx` component file for our [`Embedded Chat`](/ui-components/react/in-page/embedded-chat) component.
For Next.js apps that use **App Router**, use the `"use client"` directive at the top of the file to load the widget client side.
```jsx title=".jsx"
import dynamic from "next/dynamic";
const EmbeddedChat = dynamic(
() => import("@inkeep/cxkit-react").then((mod) => mod.InkeepEmbeddedChat),
{
ssr: false,
// loading: () => loading...
, // optional: loading animation component
}
);
function InkeepEmbeddedChat() {
const embeddedChatProps = {
baseSettings,
aiChatSettings,
};
return ;
}
export default InkeepEmbeddedChat;
```
```tsx title=".tsx"
import dynamic from "next/dynamic";
import { InkeepEmbeddedChatProps } from "@inkeep/cxkit-react";
const EmbeddedChat = dynamic(
() => import("@inkeep/cxkit-react").then((mod) => mod.InkeepEmbeddedChat),
{
ssr: false,
// loading: () => loading...
, // optional: loading animation component
}
);
function InkeepEmbeddedChat() {
const embeddedChatProps: InkeepEmbeddedChatProps = {
baseSettings,
aiChatSettings,
};
return ;
}
export default InkeepEmbeddedChat;
```
For a full list of customizations, check out the [Embedded Chat](/ui-components/react/in-page/embedded-chat) documentation.
***
title: Add Custom Modal Trigger to Next.js
description: Integrate Inkeep's custom modal trigger into your Next.js application for flexible user interactions.
keywords: Next.js integration, modal trigger, React integration, custom trigger, Next.js components, trigger implementation, app customization, modal configuration, Next.js setup, UI integration, server components
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## What is Next.js
[Next.js](https://nextjs.org/) is a React full-stack app development framework. You can use Inkeep's React component library to Add AI Search & Chat functionality to apps or documentation and marketing sites built with Next.js.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
NEXT_PUBLIC_INKEEP_API_KEY="INKEEP_API_KEY"
```
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
We'll use the [`Modal Search and Chat`](/ui-components/react/custom-modal-trigger#modal-search-and-chat) component to create a custom trigger.
Create a `ModalSearchAndChat.tsx` file for our [`Custom Modal Trigger`](/ui-components/react/custom-modal-trigger) component. `` represents whatever UI element you'd like to use to trigger the Inkeep Modal.
For Next.js apps that use **App Router**, use the `"use client"` directive at the top of the file to load the widget client side.
```jsx title=".jsx"
import dynamic from "next/dynamic";
import { useCallback, useState } from "react";
const ModalSearchAndChat = dynamic(
() => import("@inkeep/cxkit-react").then((mod) => mod.InkeepModalSearchAndChat),
{
ssr: false,
}
);
function InkeepModalSearchAndChat() {
const [isOpen, setIsOpen] = useState(false);
//...
const handleOpenChange = useCallback((isOpen: boolean) => {
setIsOpen(isOpen);
}, []);
const customTriggerProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings: {
...modalSettings,
onOpenChange: handleOpenChange,
isOpen,
},
};
return (
setIsOpen(!isOpen)}>Toggle Modal
);
}
export default InkeepModalSearchAndChat;
```
```tsx title=".tsx"
import dynamic from "next/dynamic";
import { useCallback, useState } from "react";
import { InkeepModalSearchAndChatProps } from "@inkeep/cxkit-react";
const ModalSearchAndChat = dynamic(
() =>
import("@inkeep/cxkit-react").then((mod) => mod.InkeepModalSearchAndChat),
{
ssr: false,
}
);
function InkeepModalSearchAndChat() {
const [isOpen, setIsOpen] = useState(false);
//...
const handleOpenChange = useCallback((isOpen: boolean) => {
setIsOpen(isOpen);
}, []);
const customTriggerProps: InkeepModalSearchAndChatProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings: {
...modalSettings,
onOpenChange: handleOpenChange,
isOpen,
},
};
return (
setIsOpen(!isOpen)}>Toggle Modal
);
}
export default InkeepModalSearchAndChat;
```
For a full list of customizations, check out the [Custom Modal Trigger](/ui-components/react/custom-modal-trigger) documentation.
***
title: Add Chat Button to Remix
description: Integrate Inkeep's chat button into your Remix application for real-time user assistance.
keywords: Remix integration, chat button, React integration, Remix chat, app integration, chat implementation, React components, chat configuration, Remix setup, user interaction, server components
sidebarTitle: Chat Button
-------------------------
## What is Remix
[Remix](https://remix.run/) is a modern web framework for building web applications based on React.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
INKEEP_API_KEY="INKEEP_API_KEY"
```
### Get the environment variables
Use loader/action to access your environment variables:
```tsx title="root.tsx"
// ...
export const loader = async () => {
return json({
ENV: {
API_KEY: process.env.INKEEP_API_KEY!,
INTEGRATION_ID: process.env.INKEEP_INTEGRATION_ID!,
ORGANIZATION_ID: process.env.INKEEP_ORGANIZATION_ID!
}
});
};
```
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
Next, create an `InkeepChatButton.tsx` file for the [`Chat Button`](https://docs.inkeep.com/ui-components/react/chat-button) component.
```jsx title=".jsx"
import React, { useEffect, useState } from "react";
export default function InkeepChatButton() {
const [ChatButton, setChatButton] = useState(null);
//...
// load the library asynchronously
useEffect(() => {
const loadChatButton = async () => {
try {
const { InkeepChatButton } = await import("@inkeep/cxkit-react");
setChatButton(() => InkeepChatButton);
} catch (error) {
console.error("Failed to load ChatButton:", error);
}
};
loadChatButton();
}, []);
const chatButtonProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ChatButton && ;
}
```
```tsx title=".tsx"
import React, { useEffect, useState } from "react";
import type { InkeepChatButtonProps } from "@inkeep/cxkit-react";
export default function InkeepChatButton() {
const [ChatButton, setChatButton] =
useState<(e: InkeepChatButtonProps) => JSX.Element>();
//...
// load the library asynchronously
useEffect(() => {
const loadChatButton = async () => {
try {
const { InkeepChatButton } = await import("@inkeep/cxkit-react");
setChatButton(() => InkeepChatButton);
} catch (error) {
console.error("Failed to load ChatButton:", error);
}
};
loadChatButton();
}, []);
const chatButtonProps: InkeepChatButtonProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ChatButton && ;
}
```
For a full list of customizations, check out the [Chat Button](/ui-components/react/chat-button) documentation.
***
title: Add Search Bar to Remix
description: Integrate Inkeep's search bar into your Remix application for powerful content discovery.
keywords: Remix search, React search, search integration, Remix components, search implementation, app search, search configuration, Remix setup, content discovery, React components, server components
sidebarTitle: Search Bar
------------------------
## What is Remix
[Remix](https://remix.run/) is a modern web framework for building web applications based on React.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
INKEEP_API_KEY="INKEEP_API_KEY"
```
### Get the environment variables
Use loader/action to access your environment variables:
```tsx title="root.tsx"
// ...
export const loader = async () => {
return json({
ENV: {
API_KEY: process.env.INKEEP_API_KEY!,
INTEGRATION_ID: process.env.INKEEP_INTEGRATION_ID!,
ORGANIZATION_ID: process.env.INKEEP_ORGANIZATION_ID!
}
});
};
```
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
Next, create an `InkeepSearchBar.tsx` file for the [`Search Bar`](https://docs.inkeep.com/ui-components/react/search-bar) component.
```jsx title=".jsx"
import React, { useEffect, useState } from "react";
export default function InkeepSearchBar() {
const [SearchBar, setSearchBar] = useState(null);
//...
// load the library asynchronously
useEffect(() => {
const loadSearchBar = async () => {
try {
const { InkeepSearchBar } = await import("@inkeep/cxkit-react");
setSearchBar(() => InkeepSearchBar);
} catch (error) {
console.error("Failed to load SearchBar:", error);
}
};
loadSearchBar();
}, []);
const searchBarProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return SearchBar && ;
}
```
```tsx title=".tsx"
import React, { useEffect, useState } from "react";
import type { InkeepSearchBarProps } from "@inkeep/cxkit-react";
export default function InkeepSearchBar() {
const [SearchBar, setSearchBar] =
useState<(e: InkeepSearchBarProps) => JSX.Element>();
//...
// load the library asynchronously
useEffect(() => {
const loadSearchBar = async () => {
try {
const { InkeepSearchBar } = await import("@inkeep/cxkit-react");
setSearchBar(() => InkeepSearchBar);
} catch (error) {
console.error("Failed to load SearchBar:", error);
}
};
loadSearchBar();
}, []);
const searchBarProps: InkeepSearchBarProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return SearchBar && ;
}
```
For a full list of customizations, check out the [Search Bar](/ui-components/react/search-bar) documentation.
***
title: Add Chat Button to Astro
description: Integrate Inkeep's chat button into your Astro site for real-time user assistance.
keywords: Astro integration, chat button, Astro chat, site integration, chat implementation, Astro components, chat configuration, Astro setup, user interaction, site enhancement, Astro.js, static site chat
sidebarTitle: Chat Button
-------------------------
## What is Astro
[Astro](https://astro.build/) is an all-in-one web framework for content-driven websites. With Inkeep, you can Add AI Search & Chat to your landing page, app, blog, or documentation site powered by Astro.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
INKEEP_API_KEY="INKEEP_API_KEY"
```
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Define React components
Install the **@astrojs/react** package to use React components:
```bash
npx astro add react
```
```bash
bun astro add react
```
```bash
pnpm astro add react
```
```bash
yarn astro add react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
Next, create an `InkeepChatButton.tsx` file for the [`Chat Button`](https://docs.inkeep.com/ui-components/react/chat-button) component.
```jsx title=".jsx"
import React, { useEffect, useState } from "react";
export default function InkeepChatButton() {
const [ChatButton, setChatButton] = useState(null);
//...
// load the library asynchronously
useEffect(() => {
const loadChatButton = async () => {
try {
const { InkeepChatButton } = await import("@inkeep/cxkit-react");
setChatButton(() => InkeepChatButton);
} catch (error) {
console.error("Failed to load ChatButton:", error);
}
};
loadChatButton();
}, []);
const chatButtonProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ChatButton && ;
}
```
```tsx title=".tsx"
import React, { useEffect, useState } from "react";
import type { InkeepChatButtonProps } from "@inkeep/cxkit-react";
export default function InkeepChatButton() {
const [ChatButton, setChatButton] =
useState<(e: InkeepChatButtonProps) => JSX.Element>();
//...
// load the library asynchronously
useEffect(() => {
const loadChatButton = async () => {
try {
const { InkeepChatButton } = await import("@inkeep/cxkit-react");
setChatButton(() => InkeepChatButton);
} catch (error) {
console.error("Failed to load ChatButton:", error);
}
};
loadChatButton();
}, []);
const chatButtonProps: InkeepChatButtonProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return ChatButton && ;
}
```
### Use the component
Now use the `InkeepChatButton.tsx` component in your Astro based website.
```jsx
// ...
// ...
```
Use the `client:load` directive to load and hydrate the `InkeepChatButton.tsx`
component immediately on page load.
For a full list of customizations, check out the [Chat Button](/ui-components/react/chat-button) documentation.
***
title: Add Search Bar to Astro
description: Integrate Inkeep's search bar into your Astro site for powerful content discovery.
keywords: Astro search, search integration, Astro components, search implementation, site search, Astro.js integration, search configuration, Astro setup, content discovery, search functionality, static site search, search bar
sidebarTitle: Search Bar
------------------------
## What is Astro
[Astro](https://astro.build/) is an all-in-one web framework for content-driven websites. With Inkeep, you can Add AI Search & Chat to your landing page, app, blog, or documentation site powered by Astro.
## Get an API key
Follow [these steps](/projects/overview#create-a-web-assistant) to create an API key for your web assistant.
Copy and add the `apiKey` to your environment variables:
```shell title=".env"
INKEEP_API_KEY="INKEEP_API_KEY"
```
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Define React components
Install the **@astrojs/react** package to use React components:
```bash
npx astro add react
```
```bash
bun astro add react
```
```bash
pnpm astro add react
```
```bash
yarn astro add react
```
### Customize your settings
Define your Inkeep settings.
```jsx title=".js"
const apiKey = 'YOUR_API_KEY';
const baseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings = {
// optional settings
};
const searchSettings = {
// optional settings
};
const aiChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
```tsx title=".ts"
import type {
InkeepAIChatSettings,
InkeepSearchSettings,
InkeepBaseSettings,
InkeepModalSettings,
} from "@inkeep/cxkit-react";
const apiKey = 'YOUR_API_KEY';
const baseSettings: InkeepBaseSettings = {
apiKey,
primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
organizationDisplayName: "Inkeep",
// ...optional settings
};
const modalSettings: InkeepModalSettings = {
// optional settings
};
const searchSettings: InkeepSearchSettings = {
// optional settings
};
const aiChatSettings: InkeepAIChatSettings = {
// optional settings
aiAssistantAvatar: "/img/logo.svg", // use your own AI assistant avatar
exampleQuestions: [
"Example question 1?",
"Example question 2?",
"Example question 3?",
],
};
```
### Define the component
Next, create an `InkeepSearchBar.tsx` file for the [`Search Bar`](https://docs.inkeep.com/ui-components/react/search-bar) component.
```jsx title=".jsx"
import React, { useEffect, useState } from "react";
export default function InkeepSearchBar() {
const [SearchBar, setSearchBar] = useState(null);
//...
// load the library asynchronously
useEffect(() => {
const loadSearchBar = async () => {
try {
const { InkeepSearchBar } = await import("@inkeep/cxkit-react");
setSearchBar(() => InkeepSearchBar);
} catch (error) {
console.error("Failed to load SearchBar:", error);
}
};
loadSearchBar();
}, []);
const searchBarProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return SearchBar && ;
}
```
```tsx title=".tsx"
import React, { useEffect, useState } from "react";
import type { InkeepSearchBarProps } from "@inkeep/cxkit-react";
export default function InkeepSearchBar() {
const [SearchBar, setSearchBar] =
useState<(e: InkeepSearchBarProps) => JSX.Element>();
//...
// load the library asynchronously
useEffect(() => {
const loadSearchBar = async () => {
try {
const { InkeepSearchBar } = await import("@inkeep/cxkit-react");
setSearchBar(() => InkeepSearchBar);
} catch (error) {
console.error("Failed to load SearchBar:", error);
}
};
loadSearchBar();
}, []);
const searchBarProps: InkeepSearchBarProps = {
baseSettings,
aiChatSettings,
searchSettings,
modalSettings,
};
return SearchBar && ;
}
```
### Use the component
Now use the `InkeepSearchBar.tsx` component in your Astro based website.
```jsx
// ...
// ...
```
Use the `client:load` directive to load and hydrate the `InkeepSearchBar.tsx`
component immediately on page load.
For a full list of customizations, check out the [Search Bar](/ui-components/react/search-bar) documentation.
***
title: Add Inkeep to any site
sidebarTitle: Any site
icon: LuSparkle
keywords: website integration, React components, JavaScript snippets, UI customization, theme customization, user authentication, analytics integration, support form integration, chat sharing, user privacy, component library, website widgets, AI assistant integration, custom UI components, web integration
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
With Inkeep, you can easily embed your AI assistants anywhere your users have questions.
`@inkeep/cxkit-react` is our component library that are embeddable as both React components or JS snippets.
## Components
Using the `@inkeep/cxkit-js` library.
Add a floating `Ask AI` chat button to any site or app.
Add to your docs or marketing site.
Use your own button or UI element to trigger the assistant UI.
Integrate an intelligent form to deflect new tickets.
Embed the chat directly in a dedicated standalone page.
Embed a search UI directly on a dedicated page.
Embed the chat in a sidebar on the left or right side of the page.
Using the `@inkeep/cxkit-react` library.
Add a floating `Ask AI` chat button to any site or app.
Add to your docs or marketing site.
Use your own button or UI element to trigger the assistant UI.
Integrate an intelligent form to deflect new tickets.
Embed the chat directly in a dedicated standalone page.
Embed a search UI directly on a dedicated page.
Embed the chat in a sidebar on the left or right side of the page.
## Customization
Here are some common scenarios:
* **[Customize theme & CSS](/ui-components/customization-guides/style-components)** - Customize the look and feel of the UI components.
* **[Add guidance & context](/ui-components/customization-guides/custom-instructions)** - Provide user-specific information or provide custom instructions to the LLM.
* **[Manage user privacy preferences](/ui-components/customization-guides/use-your-own-analytics#configuration-options)** - Handle user privacy settings and analytics opt-outs.
* **[Authenticate users](/ui-components/customization-guides/authenticate-users)** - Limit chat or search usage to users authenticated with your app.
* **[Log events to your own analytics](/ui-components/customization-guides/use-your-own-analytics)** - Log events to your own custom analytics system.
* **[Embed a support form](/ui-components/common-settings/actions#open-form-action)** - Add a support form embedded within the chat experience to create support tickets.
* **[Make chats sharable](/ui-components/customization-guides/sharable-chats)** - Enable the 'Share' button to make chats sharable.
## Public clients
For an overview of local development and security for AI assistant's that are used on public sites, check out [this](/ui-components//public-api-keys) guide.
***
title: Zendesk
description: Integrate Inkeep Agent Copilot with Zendesk.
keywords: Zendesk integration, agent copilot, Zendesk support, integration setup, support automation, Zendesk workflow, agent assistance, support tools, Zendesk configuration, support enhancement
icon: SiZendesk
---------------
## How it Works
*"Prefer a visual walkthrough? Check out this video instead."*
Keep's **Smart Assist** mode analyzes the ticket you're currently looking at to generate intelligent suggestions to move the ticket forward.
Suggestions can include:
1. **Draft Answers**: Editable responses that are likely to resolve the ticket.
2. **Quick Links**: Relevant sources for the ticket, such as docs, previous support tickets, and Slack threads.
3. **Summaries & To-Do's**: Summaries of long conversations and actionable remaining to-dos.
4. **Other**: Quick replies, sentiment analysis, and other helpful insights.
Keep is **fully conversational** - you can ask for clarifications or even request modifications to suggested answers.
## Add Private Sources
The Support Copilot can leverage your private content, like Slack conversations in internal channels and historical support tickets, in addition to your public docs and help center content.
[Contact us](mailto:support@inkeep.com?subject=Private%20project%20for%20Support%20Copilot) to set up a separate project with those sources.
## Generate an API Key
First, lets get an Inkeep API key for the copilot:
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Select your project under **Projects**
3. Navigate to the **Assistants** tab
4. Click on **Create assistant**
5. Select **Support Copilot**
6. Give it a name like "Support Copilot"
7. Click on **Create**
8. Copy the generated **API key**, which we'll refer to as the **Copilot API key**
## Install the Zendesk App
1. **Access Zendesk**: Log in to your Zendesk account with administrator credentials.
2. **Install the Application**: Go to the [App Listing](https://www.zendesk.com/marketplace/apps/support/1065305/keep-ai-copilot-for-support/) or navigate to the Zendesk Marketplace and search for "Keep AI Copilot for Support". Click the **Install** button to begin the installation process.
3. **Authorize Installation**: Review and accept the requested permissions.
4. **Configure the App**: Follow the prompts to set up the app, including inputting your Inkeep Support Copilot API key that you generated in the previous step.
5. **Optimize Display**: Pin the app to the support sidebar for the best chat experience.
## Use with a ticket
To use Keep with a support ticket:
1. Open a support ticket in Zendesk
2. Open the Inkeep app on the right side bar
3. Click on **Smart Assist**
## Turn Tickets into FAQs
1. Open your resolved support ticket.
2. In the Keep interface, click **Ticket into FAQ**.
3. Review the generated FAQ:
* Check the auto-generated FAQ items
* Use the copilot chat to request any needed changes
* Click **Save to KB** when ready
4. Access your FAQs:
* Visit the [Inkeep Dashboard](https://portal.inkeep.com)
* Select your Copilot's Project
* Open the **Tuning FAQs** tab
* Manage your FAQs (edit, create, enable, or disable)
Generated FAQs should already be sanitized of sensitive information and could be used as customer-facing FAQs. However, you can choose to use the FAQ source from only your private project. By default the FAQs are used only by the project that the Support Copilot was created in.
To update the API key for your Support Copilot:
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Select your project under **Projects**
3. Navigate to the **Assistants** tab
4. Find the assistant named "Support Copilot" (or the name you gave it)
5. Copy the API key associated with this assistant
Now, update the API key in your Zendesk Support Copilot App configuration:
1. Go to your Zendesk Admin Center: `https://.zendesk.com/admin/apps-integrations/apps/support-apps`
2. Find the Inkeep Support Copilot App
3. Click on **Change Settings** in the app's context menu
4. In the settings form, locate the **API Key** field
5. Paste the new API key you copied from the Inkeep Dashboard
6. Save the changes
Your Support Copilot will now use the updated API key, which may give it access to different data sources or configurations based on your Inkeep project settings.
***
title: Salesforce
description: Integrate Inkeep Agent Copilot with Salesforce.
keywords: Salesforce integration, agent copilot, Salesforce support, integration setup, support automation, Salesforce workflow, agent assistance, support tools, Salesforce configuration, support enhancement
sidebarTitle: Salesforce
icon: FaSalesforce
------------------
## How it Works
*"Prefer a visual walkthrough? Check out this video instead."*
Keep's **Smart Assist** mode analyzes the ticket you're currently looking at to generate intelligent suggestions to move the ticket forward.
Suggestions can include:
1. **Draft Answers**: Editable responses that are likely to resolve the ticket.
2. **Quick Links**: Relevant sources for the ticket, such as docs, previous support tickets, and Slack threads.
3. **Summaries & To-Do's**: Summaries of long conversations and actionable remaining to-dos.
4. **Other**: Quick replies, sentiment analysis, and other helpful insights.
Keep is **fully conversational** - you can ask for clarifications or even request modifications to suggested answers.
## Add Private Sources
The Support Copilot can leverage your private content, like Slack conversations in internal channels and historical support tickets, in addition to your public docs and help center content.
[Contact us](mailto:support@inkeep.com?subject=Private%20project%20for%20Support%20Copilot) to set up a separate project with those sources.
## Create a Support Copilot Assistant
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Select your project under **Projects**
3. Navigate to the **Assistants** tab
4. Click on **Create assistant**
5. Select **Support Copilot**
6. Give it a name like `Support Copilot for Salesforce`
7. Click on **Create**
8. In the assistant settings, expand **Advanced Settings**.
9. Click on **Link Salesforce** to link your Salesforce workspace to the assistant via OAuth. You should see **Linked successfully** in the button
## Install the Chrome Extension
1. Open your Chrome or Chromium-based browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. Click on the Inkeep icon in your browser toolbar to launch the extension.
5. Log in with your Inkeep account.
6. Select the **Support Copilot** assistant you created in the previous step.
7. Visit a supported page and click on **Smart Assist** to start using Keep.
8. Pin the extension to the toolbar for easy access by right-clicking the extension (puzzle) icon and selecting **Pin**.
9. To close the copilot, click on the **X** in the top right.
## Install using Arc
1. Open your Arc browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. **Launch** the extension. Arc will open as a new tab in the background named "Inkeep Support Copilot". (Note: It may take a couple of seconds on first launch.)
5. While on your support ticket tab, **option-click** (`β₯-click`) on MacOS (or **Alt-click** on Windows) on the Inkeep Support Copilot tab to open it in a split view. See the screenshot below for how it's supposed to look.
6. Log in with your Inkeep account.
7. Select your **Support Copilot** assistant.
8. Click **Smart Assist** to start using Keep.
## Use with a Salesforce Case
1. Open a Case in your Salesforce workspace
2. Open the Inkeep Chrome Extension
3. Click on **Smart Assist**
## Turn Tickets into FAQs
1. Open your resolved support ticket.
2. In the Keep interface, click **Ticket into FAQ**.
3. Review the generated FAQ:
* Check the auto-generated FAQ items
* Use the copilot chat to request any needed changes
* Click **Save to KB** when ready
4. Access your FAQs:
* Visit the [Inkeep Dashboard](https://portal.inkeep.com)
* Select your Copilot's Project
* Open the **Tuning FAQs** tab
* Manage your FAQs (edit, create, enable, or disable)
Generated FAQs should already be sanitized of sensitive information and could be used as customer-facing FAQs. However, you can choose to use the FAQ source from only your private project. By default the FAQs are used only by the project that the Support Copilot was created in.
***
title: HubSpot
description: Integrate Inkeep Agent Copilot with HubSpot.
keywords: HubSpot integration, agent copilot, HubSpot support, integration setup, support automation, HubSpot workflow, agent assistance, support tools, HubSpot configuration, support enhancement
sidebarTitle: Hubspot
icon: FaHubspot
---------------
## How it Works
*"Prefer a visual walkthrough? Check out this video instead."*
Keep's **Smart Assist** mode analyzes the ticket you're currently looking at to generate intelligent suggestions to move the ticket forward.
Suggestions can include:
1. **Draft Answers**: Editable responses that are likely to resolve the ticket.
2. **Quick Links**: Relevant sources for the ticket, such as docs, previous support tickets, and Slack threads.
3. **Summaries & To-Do's**: Summaries of long conversations and actionable remaining to-dos.
4. **Other**: Quick replies, sentiment analysis, and other helpful insights.
Keep is **fully conversational** - you can ask for clarifications or even request modifications to suggested answers.
## Add Private Sources
The Support Copilot can leverage your private content, like Slack conversations in internal channels and historical support tickets, in addition to your public docs and help center content.
[Contact us](mailto:support@inkeep.com?subject=Private%20project%20for%20Support%20Copilot) to set up a separate project with those sources.
## Create a Support Copilot Assistant
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Select your project under **Projects**
3. Navigate to the **Assistants** tab
4. Click on **Create assistant**
5. Select **Support Copilot**
6. Give it a name like `Support Copilot for Hubspot`
7. Click on **Create**
8. In the assistant settings, expand **Advanced Settings**.
9. Click on **Link Hubspot** to link your Hubspot workspace to the assistant via OAuth. You should see **Linked successfully** in the button
## Install the Chrome Extension
1. Open your Chrome or Chromium-based browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. Click on the Inkeep icon in your browser toolbar to launch the extension.
5. Log in with your Inkeep account.
6. Select the **Support Copilot** assistant you created in the previous step.
7. Visit a supported page and click on **Smart Assist** to start using Keep.
8. Pin the extension to the toolbar for easy access by right-clicking the extension (puzzle) icon and selecting **Pin**.
9. To close the copilot, click on the **X** in the top right.
## Install using Arc
1. Open your Arc browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. **Launch** the extension. Arc will open as a new tab in the background named "Inkeep Support Copilot". (Note: It may take a couple of seconds on first launch.)
5. While on your support ticket tab, **option-click** (`β₯-click`) on MacOS (or **Alt-click** on Windows) on the Inkeep Support Copilot tab to open it in a split view. See the screenshot below for how it's supposed to look.
6. Log in with your Inkeep account.
7. Select your **Support Copilot** assistant.
8. Click **Smart Assist** to start using Keep.
## Use with a Hubspot conversation
1. Open a conversation in your Hubspot workspace
2. Open the Inkeep Chrome Extension
3. Click on **Smart Assist**
## Turn Tickets into FAQs
1. Open your resolved support ticket.
2. In the Keep interface, click **Ticket into FAQ**.
3. Review the generated FAQ:
* Check the auto-generated FAQ items
* Use the copilot chat to request any needed changes
* Click **Save to KB** when ready
4. Access your FAQs:
* Visit the [Inkeep Dashboard](https://portal.inkeep.com)
* Select your Copilot's Project
* Open the **Tuning FAQs** tab
* Manage your FAQs (edit, create, enable, or disable)
Generated FAQs should already be sanitized of sensitive information and could be used as customer-facing FAQs. However, you can choose to use the FAQ source from only your private project. By default the FAQs are used only by the project that the Support Copilot was created in.
***
title: Intercom
description: Integrate Inkeep Agent Copilot with Intercom.
keywords: Intercom integration, agent copilot, Intercom support, integration setup, support automation, Intercom workflow, agent assistance, support tools, Intercom configuration, support enhancement
sidebarTitle: Intercom
icon: SiIntercom
----------------
## How it Works
*"Prefer a visual walkthrough? Check out this video instead."*
Keep's **Smart Assist** mode analyzes the ticket you're currently looking at to generate intelligent suggestions to move the ticket forward.
Suggestions can include:
1. **Draft Answers**: Editable responses that are likely to resolve the ticket.
2. **Quick Links**: Relevant sources for the ticket, such as docs, previous support tickets, and Slack threads.
3. **Summaries & To-Do's**: Summaries of long conversations and actionable remaining to-dos.
4. **Other**: Quick replies, sentiment analysis, and other helpful insights.
Keep is **fully conversational** - you can ask for clarifications or even request modifications to suggested answers.
## Add Private Sources
The Support Copilot can leverage your private content, like Slack conversations in internal channels and historical support tickets, in addition to your public docs and help center content.
[Contact us](mailto:support@inkeep.com?subject=Private%20project%20for%20Support%20Copilot) to set up a separate project with those sources.
## Create a Support Copilot Assistant
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Select your project under **Projects**
3. Navigate to the **Assistants** tab
4. Click on **Create assistant**
5. Select **Support Copilot**
6. Give it a name like `Support Copilot for Intercom`
7. Click on **Create**
8. In the assistant settings, expand **Advanced Settings**.
9. Click on **Link Intercom** to link your Intercom workspace to the assistant via OAuth. You should see **Linked successfully** in the button
## Install the Chrome Extension
1. Open your Chrome or Chromium-based browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. Click on the Inkeep icon in your browser toolbar to launch the extension.
5. Log in with your Inkeep account.
6. Select the **Support Copilot** assistant you created in the previous step.
7. Visit a supported page and click on **Smart Assist** to start using Keep.
8. Pin the extension to the toolbar for easy access by right-clicking the extension (puzzle) icon and selecting **Pin**.
9. To close the copilot, click on the **X** in the top right.
## Install using Arc
1. Open your Arc browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. **Launch** the extension. Arc will open as a new tab in the background named "Inkeep Support Copilot". (Note: It may take a couple of seconds on first launch.)
5. While on your support ticket tab, **option-click** (`β₯-click`) on MacOS (or **Alt-click** on Windows) on the Inkeep Support Copilot tab to open it in a split view. See the screenshot below for how it's supposed to look.
6. Log in with your Inkeep account.
7. Select your **Support Copilot** assistant.
8. Click **Smart Assist** to start using Keep.
## Use with an Intercom conversation or ticket
1. Open a conversation or ticket in your Intercom workspace
2. Open the Inkeep Chrome Extension
3. Click on **Smart Assist**
## Turn Tickets into FAQs
1. Open your resolved support ticket.
2. In the Keep interface, click **Ticket into FAQ**.
3. Review the generated FAQ:
* Check the auto-generated FAQ items
* Use the copilot chat to request any needed changes
* Click **Save to KB** when ready
4. Access your FAQs:
* Visit the [Inkeep Dashboard](https://portal.inkeep.com)
* Select your Copilot's Project
* Open the **Tuning FAQs** tab
* Manage your FAQs (edit, create, enable, or disable)
Generated FAQs should already be sanitized of sensitive information and could be used as customer-facing FAQs. However, you can choose to use the FAQ source from only your private project. By default the FAQs are used only by the project that the Support Copilot was created in.
***
title: Help Scout
description: Integrate Inkeep Agent Copilot with Help Scout.
keywords: Help Scout integration, agent copilot, Help Scout support, integration setup, support automation, Help Scout workflow, agent assistance, support tools, Help Scout configuration, support enhancement
sidebarTitle: Help Scout
icon: SiHelpscout
-----------------
## How it Works
*"Prefer a visual walkthrough? Check out this video instead."*
Keep's **Smart Assist** mode analyzes the ticket you're currently looking at to generate intelligent suggestions to move the ticket forward.
Suggestions can include:
1. **Draft Answers**: Editable responses that are likely to resolve the ticket.
2. **Quick Links**: Relevant sources for the ticket, such as docs, previous support tickets, and Slack threads.
3. **Summaries & To-Do's**: Summaries of long conversations and actionable remaining to-dos.
4. **Other**: Quick replies, sentiment analysis, and other helpful insights.
Keep is **fully conversational** - you can ask for clarifications or even request modifications to suggested answers.
## Add Private Sources
The Support Copilot can leverage your private content, like Slack conversations in internal channels and historical support tickets, in addition to your public docs and help center content.
[Contact us](mailto:support@inkeep.com?subject=Private%20project%20for%20Support%20Copilot) to set up a separate project with those sources.
## Create a Support Copilot Assistant
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Select your project under **Projects**
3. Navigate to the **Assistants** tab
4. Click on **Create assistant**
5. Select **Support Copilot**
6. Give it a name like `Support Copilot for Help Scout`
7. Click on **Create**
8. In the assistant settings, expand **Advanced Settings**.
9. Click on **Link Help Scout** to link your Help Scout inbox to the assistant via OAuth. You should see **Linked successfully** in the button
## Install the Chrome Extension
1. Open your Chrome or Chromium-based browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. Click on the Inkeep icon in your browser toolbar to launch the extension.
5. Log in with your Inkeep account.
6. Select the **Support Copilot** assistant you created in the previous step.
7. Visit a supported page and click on **Smart Assist** to start using Keep.
8. Pin the extension to the toolbar for easy access by right-clicking the extension (puzzle) icon and selecting **Pin**.
9. To close the copilot, click on the **X** in the top right.
## Install using Arc
1. Open your Arc browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. **Launch** the extension. Arc will open as a new tab in the background named "Inkeep Support Copilot". (Note: It may take a couple of seconds on first launch.)
5. While on your support ticket tab, **option-click** (`β₯-click`) on MacOS (or **Alt-click** on Windows) on the Inkeep Support Copilot tab to open it in a split view. See the screenshot below for how it's supposed to look.
6. Log in with your Inkeep account.
7. Select your **Support Copilot** assistant.
8. Click **Smart Assist** to start using Keep.
## Use with a Help Scout conversation
1. Open a conversation in your Help Scout inbox
2. Open the Inkeep Chrome Extension
3. Click on **Smart Assist**
## Turn Tickets into FAQs
1. Open your resolved support ticket.
2. In the Keep interface, click **Ticket into FAQ**.
3. Review the generated FAQ:
* Check the auto-generated FAQ items
* Use the copilot chat to request any needed changes
* Click **Save to KB** when ready
4. Access your FAQs:
* Visit the [Inkeep Dashboard](https://portal.inkeep.com)
* Select your Copilot's Project
* Open the **Tuning FAQs** tab
* Manage your FAQs (edit, create, enable, or disable)
Generated FAQs should already be sanitized of sensitive information and could be used as customer-facing FAQs. However, you can choose to use the FAQ source from only your private project. By default the FAQs are used only by the project that the Support Copilot was created in.
***
title: Front
description: Integrate Inkeep Agent Copilot with Front.
icon: custom/FrontIcon
keywords: Front integration, agent copilot, Front support, integration setup, support automation, Front workflow, agent assistance, support tools, Front configuration, support enhancement
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## How it Works
*"Prefer a visual walkthrough? Check out this video instead."*
Keep's **Smart Assist** mode analyzes the ticket you're currently looking at to generate intelligent suggestions to move the ticket forward.
Suggestions can include:
1. **Draft Answers**: Editable responses that are likely to resolve the ticket.
2. **Quick Links**: Relevant sources for the ticket, such as docs, previous support tickets, and Slack threads.
3. **Summaries & To-Do's**: Summaries of long conversations and actionable remaining to-dos.
4. **Other**: Quick replies, sentiment analysis, and other helpful insights.
Keep is **fully conversational** - you can ask for clarifications or even request modifications to suggested answers.
## Add Private Sources
The Support Copilot can leverage your private content, like Slack conversations in internal channels and historical support tickets, in addition to your public docs and help center content.
[Contact us](mailto:support@inkeep.com?subject=Private%20project%20for%20Support%20Copilot) to set up a separate project with those sources.
## Create a Support Copilot Assistant
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Select your project under **Projects**
3. Navigate to the **Assistants** tab
4. Click on **Create assistant**
5. Select **Support Copilot**
6. Give it a name like `Support Copilot for Front`
7. Click on **Create**
8. In the assistant settings, expand **Advanced Settings**.
9. Click on **Link Front** to link your Front workspace to the assistant via OAuth. You should see **Linked successfully** in the button
## Install the Chrome Extension
1. Open your Chrome or Chromium-based browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. Click on the Inkeep icon in your browser toolbar to launch the extension.
5. Log in with your Inkeep account.
6. Select the **Support Copilot** assistant you created in the previous step.
7. Visit a supported page and click on **Smart Assist** to start using Keep.
8. Pin the extension to the toolbar for easy access by right-clicking the extension (puzzle) icon and selecting **Pin**.
9. To close the copilot, click on the **X** in the top right.
## Install using Arc
1. Open your Arc browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. **Launch** the extension. Arc will open as a new tab in the background named "Inkeep Support Copilot". (Note: It may take a couple of seconds on first launch.)
5. While on your support ticket tab, **option-click** (`β₯-click`) on MacOS (or **Alt-click** on Windows) on the Inkeep Support Copilot tab to open it in a split view. See the screenshot below for how it's supposed to look.
6. Log in with your Inkeep account.
7. Select your **Support Copilot** assistant.
8. Click **Smart Assist** to start using Keep.
## Use with a Front conversation
1. Open a conversation in your Front workspace
2. Open the Inkeep Chrome Extension
3. Click on **Smart Assist**
## Turn Tickets into FAQs
1. Open your resolved support ticket.
2. In the Keep interface, click **Ticket into FAQ**.
3. Review the generated FAQ:
* Check the auto-generated FAQ items
* Use the copilot chat to request any needed changes
* Click **Save to KB** when ready
4. Access your FAQs:
* Visit the [Inkeep Dashboard](https://portal.inkeep.com)
* Select your Copilot's Project
* Open the **Tuning FAQs** tab
* Manage your FAQs (edit, create, enable, or disable)
Generated FAQs should already be sanitized of sensitive information and could be used as customer-facing FAQs. However, you can choose to use the FAQ source from only your private project. By default the FAQs are used only by the project that the Support Copilot was created in.
***
title: Freshdesk
description: Integrate Inkeep Agent Copilot with Freshdesk.
keywords: Freshdesk integration, agent copilot, Freshdesk support, integration setup, support automation, Freshdesk workflow, agent assistance, support tools, Freshdesk configuration, support enhancement
sidebarTitle: Freshdesk
icon: custom/FreshdeskIcon
--------------------------
## How it Works
*"Prefer a visual walkthrough? Check out this video instead."*
Keep's **Smart Assist** mode analyzes the ticket you're currently looking at to generate intelligent suggestions to move the ticket forward.
Suggestions can include:
1. **Draft Answers**: Editable responses that are likely to resolve the ticket.
2. **Quick Links**: Relevant sources for the ticket, such as docs, previous support tickets, and Slack threads.
3. **Summaries & To-Do's**: Summaries of long conversations and actionable remaining to-dos.
4. **Other**: Quick replies, sentiment analysis, and other helpful insights.
Keep is **fully conversational** - you can ask for clarifications or even request modifications to suggested answers.
## Add Private Sources
The Support Copilot can leverage your private content, like Slack conversations in internal channels and historical support tickets, in addition to your public docs and help center content.
[Contact us](mailto:support@inkeep.com?subject=Private%20project%20for%20Support%20Copilot) to set up a separate project with those sources.
## Find your Freshdesk subdomain and API key
1. Follow Freshdesk's [guide](https://support.freshdesk.com/support/solutions/articles/215517) to find your API key.
2. Copy the API key and store it somewhere safe.
3. Your Freshdesk subdomain is the part before .freshdesk.com (e.g., "your-company" from your-company.freshdesk.com)
## Create a Support Copilot Assistant
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Select your project under **Projects**
3. Navigate to the **Assistants** tab
4. Click on **Create assistant**
5. Select **Support Copilot**
6. Give it a name like `Support Copilot for Freshdesk`
7. Click on **Create**
8. In the assistant settings, expand **Advanced Settings**.
9. Enter your Freshdesk subdomain and API key under the **Freshdesk** section.
10. Click on **Link Freshdesk** to link your Freshdesk account. You should see **Linked successfully** when the assistant is successfully linked.
## Install the Chrome Extension
1. Open your Chrome or Chromium-based browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. Click on the Inkeep icon in your browser toolbar to launch the extension.
5. Log in with your Inkeep account.
6. Select the **Support Copilot** assistant you created in the previous step.
7. Visit a supported page and click on **Smart Assist** to start using Keep.
8. Pin the extension to the toolbar for easy access by right-clicking the extension (puzzle) icon and selecting **Pin**.
9. To close the copilot, click on the **X** in the top right.
## Install using Arc
1. Open your Arc browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. **Launch** the extension. Arc will open as a new tab in the background named "Inkeep Support Copilot". (Note: It may take a couple of seconds on first launch.)
5. While on your support ticket tab, **option-click** (`β₯-click`) on MacOS (or **Alt-click** on Windows) on the Inkeep Support Copilot tab to open it in a split view. See the screenshot below for how it's supposed to look.
6. Log in with your Inkeep account.
7. Select your **Support Copilot** assistant.
8. Click **Smart Assist** to start using Keep.
## Use with a Freshdesk ticket
1. Open a ticket in Freshdesk
2. Open the Inkeep Chrome Extension
3. Click on **Smart Assist**
## Turn Tickets into FAQs
1. Open your resolved support ticket.
2. In the Keep interface, click **Ticket into FAQ**.
3. Review the generated FAQ:
* Check the auto-generated FAQ items
* Use the copilot chat to request any needed changes
* Click **Save to KB** when ready
4. Access your FAQs:
* Visit the [Inkeep Dashboard](https://portal.inkeep.com)
* Select your Copilot's Project
* Open the **Tuning FAQs** tab
* Manage your FAQs (edit, create, enable, or disable)
Generated FAQs should already be sanitized of sensitive information and could be used as customer-facing FAQs. However, you can choose to use the FAQ source from only your private project. By default the FAQs are used only by the project that the Support Copilot was created in.
***
title: Plain
description: Integrate Inkeep Agent Copilot with Plain.
icon: custom/PlainIcon
keywords: Plain integration, agent copilot, Plain support, integration setup, support automation, Plain workflow, agent assistance, support tools, Plain configuration, support enhancement
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## How it Works
*"Prefer a visual walkthrough? Check out this video instead."*
Keep's **Smart Assist** mode analyzes the ticket you're currently looking at to generate intelligent suggestions to move the ticket forward.
Suggestions can include:
1. **Draft Answers**: Editable responses that are likely to resolve the ticket.
2. **Quick Links**: Relevant sources for the ticket, such as docs, previous support tickets, and Slack threads.
3. **Summaries & To-Do's**: Summaries of long conversations and actionable remaining to-dos.
4. **Other**: Quick replies, sentiment analysis, and other helpful insights.
Keep is **fully conversational** - you can ask for clarifications or even request modifications to suggested answers.
## Add Private Sources
The Support Copilot can leverage your private content, like Slack conversations in internal channels and historical support tickets, in addition to your public docs and help center content.
[Contact us](mailto:support@inkeep.com?subject=Private%20project%20for%20Support%20Copilot) to set up a separate project with those sources.
## Generate a Plain API key
1. Follow Plain's [guide](https://www.plain.com/docs/api-reference/graphql/authentication) for creating an API key for Inkeep. To configure the correct permissions:
a. **Copy** the below permissions string.
```txt title="Needed"
attachment:download,company:read,customer:read,machineUser:read,thread:read,threadDiscussion:read,threadDiscussionMessage:read,threadField:read,threadFieldSchema:read,tier:read,timeline:read,user:read
```
b. In Plain's **Add API Key** page, click on the **From clipboard** button to paste the permissions.
c. Review the permissions and create the API key
2. Copy the API key and store it somewhere safe.
## Create a Support Copilot Assistant
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Select your project under **Projects**
3. Navigate to the **Assistants** tab
4. Click on **Create assistant**
5. Select **Support Copilot**
6. Give it a name like `Support Copilot for Plain`
7. Click on **Create**
8. In the assistant settings, expand **Advanced Settings**.
9. Enter your Plain API key in **Plain API key** field.
10. Click **Update**
## Install the Chrome Extension
1. Open your Chrome or Chromium-based browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. Click on the Inkeep icon in your browser toolbar to launch the extension.
5. Log in with your Inkeep account.
6. Select the **Support Copilot** assistant you created in the previous step.
7. Visit a supported page and click on **Smart Assist** to start using Keep.
8. Pin the extension to the toolbar for easy access by right-clicking the extension (puzzle) icon and selecting **Pin**.
9. To close the copilot, click on the **X** in the top right.
## Install using Arc
1. Open your Arc browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. **Launch** the extension. Arc will open as a new tab in the background named "Inkeep Support Copilot". (Note: It may take a couple of seconds on first launch.)
5. While on your support ticket tab, **option-click** (`β₯-click`) on MacOS (or **Alt-click** on Windows) on the Inkeep Support Copilot tab to open it in a split view. See the screenshot below for how it's supposed to look.
6. Log in with your Inkeep account.
7. Select your **Support Copilot** assistant.
8. Click **Smart Assist** to start using Keep.
## Use with a Plain thread
1. Open a thread in your Plain workspace
2. Open the Inkeep Chrome Extension
3. Click on **Smart Assist**
## Turn Tickets into FAQs
1. Open your resolved support ticket.
2. In the Keep interface, click **Ticket into FAQ**.
3. Review the generated FAQ:
* Check the auto-generated FAQ items
* Use the copilot chat to request any needed changes
* Click **Save to KB** when ready
4. Access your FAQs:
* Visit the [Inkeep Dashboard](https://portal.inkeep.com)
* Select your Copilot's Project
* Open the **Tuning FAQs** tab
* Manage your FAQs (edit, create, enable, or disable)
Generated FAQs should already be sanitized of sensitive information and could be used as customer-facing FAQs. However, you can choose to use the FAQ source from only your private project. By default the FAQs are used only by the project that the Support Copilot was created in.
***
title: Atlas Support
description: Integrate Inkeep Agent Copilot with Atlas.
keywords: Atlas integration, agent copilot, Atlas support, integration setup, support automation, Atlas workflow, agent assistance, support tools, Atlas configuration, support enhancement
icon: custom/AtlasIcon
----------------------
## How it Works
*"Prefer a visual walkthrough? Check out this video instead."*
Keep's **Smart Assist** mode analyzes the ticket you're currently looking at to generate intelligent suggestions to move the ticket forward.
Suggestions can include:
1. **Draft Answers**: Editable responses that are likely to resolve the ticket.
2. **Quick Links**: Relevant sources for the ticket, such as docs, previous support tickets, and Slack threads.
3. **Summaries & To-Do's**: Summaries of long conversations and actionable remaining to-dos.
4. **Other**: Quick replies, sentiment analysis, and other helpful insights.
Keep is **fully conversational** - you can ask for clarifications or even request modifications to suggested answers.
## Add Private Sources
The Support Copilot can leverage your private content, like Slack conversations in internal channels and historical support tickets, in addition to your public docs and help center content.
[Contact us](mailto:support@inkeep.com?subject=Private%20project%20for%20Support%20Copilot) to set up a separate project with those sources.
## Find your Atlas API key
1. Follow Atlas's [guide](https://developers.atlas.so/reference/getting-started-with-your-api) for finding your API key.
2. Copy the API key and store it somewhere safe.
## Create a Support Copilot Assistant
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Select your project under **Projects**
3. Navigate to the **Assistants** tab
4. Click on **Create assistant**
5. Select **Support Copilot**
6. Give it a name like `Support Copilot for Atlas`
7. Click on **Create**
8. In the assistant settings, expand **Advanced Settings**.
9. Enter your Atlas API key in **Atlas API key** field.
10. Click **Update**
## Install the Chrome Extension
1. Open your Chrome or Chromium-based browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. Click on the Inkeep icon in your browser toolbar to launch the extension.
5. Log in with your Inkeep account.
6. Select the **Support Copilot** assistant you created in the previous step.
7. Visit a supported page and click on **Smart Assist** to start using Keep.
8. Pin the extension to the toolbar for easy access by right-clicking the extension (puzzle) icon and selecting **Pin**.
9. To close the copilot, click on the **X** in the top right.
## Install using Arc
1. Open your Arc browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. **Launch** the extension. Arc will open as a new tab in the background named "Inkeep Support Copilot". (Note: It may take a couple of seconds on first launch.)
5. While on your support ticket tab, **option-click** (`β₯-click`) on MacOS (or **Alt-click** on Windows) on the Inkeep Support Copilot tab to open it in a split view. See the screenshot below for how it's supposed to look.
6. Log in with your Inkeep account.
7. Select your **Support Copilot** assistant.
8. Click **Smart Assist** to start using Keep.
## Use with a Atlas conversation
1. Open a conversation in your Atlas workspace
2. Open the Inkeep Chrome Extension
3. Click on **Smart Assist**
## Turn Tickets into FAQs
1. Open your resolved support ticket.
2. In the Keep interface, click **Ticket into FAQ**.
3. Review the generated FAQ:
* Check the auto-generated FAQ items
* Use the copilot chat to request any needed changes
* Click **Save to KB** when ready
4. Access your FAQs:
* Visit the [Inkeep Dashboard](https://portal.inkeep.com)
* Select your Copilot's Project
* Open the **Tuning FAQs** tab
* Manage your FAQs (edit, create, enable, or disable)
Generated FAQs should already be sanitized of sensitive information and could be used as customer-facing FAQs. However, you can choose to use the FAQ source from only your private project. By default the FAQs are used only by the project that the Support Copilot was created in.
***
title: Missive
description: Integrate Inkeep Agent Copilot with Missive.
icon: custom/MissiveIcon
keywords: Missive integration, agent copilot, Missive support, integration setup, support automation, Missive workflow, agent assistance, support tools, Missive configuration, support enhancement
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## How it Works
*"Prefer a visual walkthrough? Check out this video instead."*
Keep's **Smart Assist** mode analyzes the ticket you're currently looking at to generate intelligent suggestions to move the ticket forward.
Suggestions can include:
1. **Draft Answers**: Editable responses that are likely to resolve the ticket.
2. **Quick Links**: Relevant sources for the ticket, such as docs, previous support tickets, and Slack threads.
3. **Summaries & To-Do's**: Summaries of long conversations and actionable remaining to-dos.
4. **Other**: Quick replies, sentiment analysis, and other helpful insights.
Keep is **fully conversational** - you can ask for clarifications or even request modifications to suggested answers.
## Add Private Sources
The Support Copilot can leverage your private content, like Slack conversations in internal channels and historical support tickets, in addition to your public docs and help center content.
[Contact us](mailto:support@inkeep.com?subject=Private%20project%20for%20Support%20Copilot) to set up a separate project with those sources.
## Generate a Missive API key
1. Follow Missive's [guide](https://learn.missiveapp.com/api-documentation/getting-started) (in the Authentication section) and create a new API key.
2. Copy the API key and store it somewhere safe.
## Create a Support Copilot Assistant
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Select your project under **Projects**
3. Navigate to the **Assistants** tab
4. Click on **Create assistant**
5. Select **Support Copilot**
6. Give it a name like `Support Copilot for Missive`
7. Click on **Create**
8. In the assistant settings, expand **Advanced Settings**.
9. Enter your Missive API key in **Missive API key** field.
10. Click **Update**
## Install the Chrome Extension
1. Open your Chrome or Chromium-based browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. Click on the Inkeep icon in your browser toolbar to launch the extension.
5. Log in with your Inkeep account.
6. Select the **Support Copilot** assistant you created in the previous step.
7. Visit a supported page and click on **Smart Assist** to start using Keep.
8. Pin the extension to the toolbar for easy access by right-clicking the extension (puzzle) icon and selecting **Pin**.
9. To close the copilot, click on the **X** in the top right.
## Install using Arc
1. Open your Arc browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. **Launch** the extension. Arc will open as a new tab in the background named "Inkeep Support Copilot". (Note: It may take a couple of seconds on first launch.)
5. While on your support ticket tab, **option-click** (`β₯-click`) on MacOS (or **Alt-click** on Windows) on the Inkeep Support Copilot tab to open it in a split view. See the screenshot below for how it's supposed to look.
6. Log in with your Inkeep account.
7. Select your **Support Copilot** assistant.
8. Click **Smart Assist** to start using Keep.
## Use with a Missive conversation
1. Open a conversation in your Missive inbox. Make sure you are viewing a conversation in an expanded view, which is available through Inbox, All, Archive, and Searches tabs. There is a collapsed view available if you open a conversation through the Tasks tab, which is not supported.
2. Open the Inkeep Chrome Extension
3. Click on **Smart Assist**
## Turn Tickets into FAQs
1. Open your resolved support ticket.
2. In the Keep interface, click **Ticket into FAQ**.
3. Review the generated FAQ:
* Check the auto-generated FAQ items
* Use the copilot chat to request any needed changes
* Click **Save to KB** when ready
4. Access your FAQs:
* Visit the [Inkeep Dashboard](https://portal.inkeep.com)
* Select your Copilot's Project
* Open the **Tuning FAQs** tab
* Manage your FAQs (edit, create, enable, or disable)
Generated FAQs should already be sanitized of sensitive information and could be used as customer-facing FAQs. However, you can choose to use the FAQ source from only your private project. By default the FAQs are used only by the project that the Support Copilot was created in.
***
title: Chrome Extension
description: Install and use the Inkeep Agent Copilot Chrome extension.
keywords: Chrome extension, agent copilot, browser extension, support tools, extension setup, Chrome integration, agent assistance, browser support, extension configuration, support enhancement
icon: LuChrome
--------------
## How it Works
*"Prefer a visual walkthrough? Check out this video instead."*
Keep's **Smart Assist** mode analyzes the ticket you're currently looking at to generate intelligent suggestions to move the ticket forward.
Suggestions can include:
1. **Draft Answers**: Editable responses that are likely to resolve the ticket.
2. **Quick Links**: Relevant sources for the ticket, such as docs, previous support tickets, and Slack threads.
3. **Summaries & To-Do's**: Summaries of long conversations and actionable remaining to-dos.
4. **Other**: Quick replies, sentiment analysis, and other helpful insights.
Keep is **fully conversational** - you can ask for clarifications or even request modifications to suggested answers.
## Add Private Sources
The Support Copilot can leverage your private content, like Slack conversations in internal channels and historical support tickets, in addition to your public docs and help center content.
[Contact us](mailto:support@inkeep.com?subject=Private%20project%20for%20Support%20Copilot) to set up a separate project with those sources.
## Create a Support Copilot Assistant
First, lets get create a Support Copilot assistant:
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com/)
2. Select your project under **Projects**
3. Navigate to the **Assistants** tab
4. Click on **Create assistant**
5. Select **Support Copilot**
6. Give it a name like "Support Copilot"
7. Click on **Create**
8. In the assistant settings, expand **Advanced Settings**.
9. Link the assistant to your support platform using the options provided.
10. Click **Update**
## Install the Chrome Extension
1. Open your Chrome or Chromium-based browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. Click on the Inkeep icon in your browser toolbar to launch the extension.
5. Log in with your Inkeep account.
6. Select the **Support Copilot** assistant you created in the previous step.
7. Visit a supported page and click on **Smart Assist** to start using Keep.
8. Pin the extension to the toolbar for easy access by right-clicking the extension (puzzle) icon and selecting **Pin**.
9. To close the copilot, click on the **X** in the top right.
## Install using Arc
1. Open your Arc browser.
2. Go to the [Chrome Web Store Listing](https://chromewebstore.google.com/detail/keep-ai-copilot-for-suppo/pkhhiabkpgkjabdlakafhdmapkgdafkh).
3. Click **Add to Chrome**, then **Add extension**.
4. **Launch** the extension. Arc will open as a new tab in the background named "Inkeep Support Copilot". (Note: It may take a couple of seconds on first launch.)
5. While on your support ticket tab, **option-click** (`β₯-click`) on MacOS (or **Alt-click** on Windows) on the Inkeep Support Copilot tab to open it in a split view. See the screenshot below for how it's supposed to look.
6. Log in with your Inkeep account.
7. Select your **Support Copilot** assistant.
8. Click **Smart Assist** to start using Keep.
## Compatibility
Currently, the Chrome Extension works on:
* Salesforce
* Hubspot
* Intercom
* Help Scout
* Front
* Freshdesk
* GitHub Issues
* Plain
* Atlas Support
* Missive
To request support for additional platforms, just ask [sales@inkeep.com](mailto:support@inkeep.com?subject=Add%20compatibility%20to%20Chrome%20Extension%20copilot). We can add support within 1 week.
## Example Usage
To use Keep with a GitHub issue:
1. Open a GitHub issue in a given tab.
2. Launch the extension.
3. Click on **Smart Assist**.
## Turn Tickets into FAQs
1. Open your resolved support ticket.
2. In the Keep interface, click **Ticket into FAQ**.
3. Review the generated FAQ:
* Check the auto-generated FAQ items
* Use the copilot chat to request any needed changes
* Click **Save to KB** when ready
4. Access your FAQs:
* Visit the [Inkeep Dashboard](https://portal.inkeep.com)
* Select your Copilot's Project
* Open the **Tuning FAQs** tab
* Manage your FAQs (edit, create, enable, or disable)
Generated FAQs should already be sanitized of sensitive information and could be used as customer-facing FAQs. However, you can choose to use the FAQ source from only your private project. By default the FAQs are used only by the project that the Support Copilot was created in.
***
title: Draft FAQ Responses
description: Use Agent Copilot to draft FAQ responses for your knowledge base.
keywords: FAQ drafting, knowledge base, response templates, content creation, FAQ management, support documentation, answer drafting, content automation, knowledge management, FAQ automation, content generation
sidebarTitle: Turn tickets into FAQs
icon: arrows-spin
-----------------
## Overview
The Inkeep Support Copilot allows you to close the loop and improve future AI responses by using the AI to draft FAQs from resolved support tickets. This guide will walk you through the process of using the Support Copilot and managing the generated FAQs.
## Prerequisites
Before you begin, ensure you have:
1. Created a Support Copilot assistant
2. Configured your Zendesk app with the necessary API credentials
## Using the Support Copilot
### Open the AI Copilot
1. Navigate to a resolved support ticket in your system (or a ticket with sufficient information to build an FAQ)
2. Open the Inkeep AI Copilot for support from either the Zendesk App or the Chrome Extension
### Generate an FAQ
1. In the AI Copilot interface, click on **Draft FAQ**
2. Wait for the AI to draft the FAQ based on the support ticket
### Review and Save the FAQ
1. Read over the generated FAQ items carefully
2. You may chat with the copilot to request modifications to revise the draft FAQ.
3. If you're satisfied with the question and answer, click **Save to my knowledge base**
4. You should see a checkmark indicating that the FAQ has been successfully saved
## Managing FAQs
### Access the FAQ Management Page
1. Return to the Inkeep Dashboard
2. Click on the **Tuning FAQs** button
### View and Edit FAQs
On the FAQ management page, you can:
1. View all generated FAQs
2. Enable or disable individual FAQs
3. Edit any fields of the FAQ
4. See the sources used to draft the FAQ, including the original ticket source
## Using Support Copilot with Internal Projects
You can use the Support Copilot process with internal projects to maintain privacy for sensitive information:
1. Create FAQs from internal support tickets
2. Use these FAQs to improve AI-drafted responses for your support agents
3. Keep sensitive information private while enhancing your AI performance
## Benefits of Using Support Copilot
* Continuously refine your AI's understanding of common issues and solutions
* Improve the accuracy and relevance of AI-generated responses over time
* Streamline the process of creating and managing FAQs from support interactions
* Enhance the knowledge base available to both AI and human support agents
By regularly using the Support Copilot to generate FAQs from resolved tickets, you can create a feedback loop that consistently improves your AI's performance in handling support queries.
***
title: Prehook Integration
description: Integrate Inkeep Agent Copilot with Prehook.
keywords: Prehook integration, agent copilot, support integration, Prehook setup, integration configuration, support tools, agent assistance, Prehook automation, workflow integration, support platform, integration setup
sidebarTitle: Custom context
icon: HiLightBulb
-----------------
## Overview
Sometimes you may want to provide information from external systems to the Inkeep support copilot. This can include:
* Payment information from your billing system
* Account information from your CRM
* Activity or product-specific data from your database
* Uptime information from your application monitoring software
To accomplish this, you can use a `prehook` for the copilot. When a `prehook` is enabled, the following happens:
1. When a support agent clicks on `Smart Assist`, Inkeep will make a request to an API route of your choosing.
2. Your API route fetches information from any arbitrary backend service\[s].
3. Your API route returns that information and any custom instructions in the API route's response.
4. That information is added as custom context for the AI copilot to consider.
5. That context is persisted across the entire conversation with the copilot.
Think of the `prehook` as a way to inject dynamic, custom data or instructions into the Copilot's decision-making process.
## 1. Deploy your API route
You'll need to deploy an API endpoint that the Copilot can call.
### Option 1: Deploy with Vercel (Recommended)
A quick way to deploy is to use the below Vercel template:
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Finkeep%2Fcopilot-prehook-template\&project-name=copilot-prehook-template\&repository-name=copilot-prehook-template\&env=INKEEP_SUPPORT_COPILOT_API_KEY\&envDescription=API%20Key%20needed%20to%20authorize%20request)
1. Click the "Deploy with Vercel" button above
2. Connect your GitHub account when prompted
3. Generate a random API key using this command:
```bash
openssl rand -base64 30 | cut -c1-40
```
4. Enter this API key as the `INKEEP_SUPPORT_COPILOT_API_KEY` environment variable
5. Click Deploy
### Option 2: Deploy anywhere
As long as your API route follows the API contract, you can deploy and develop the API route in any cloud provider or API framework. A reference TypeScript template repository is provided [here](https://github.com/inkeep/copilot-prehook-template).
## 2. Write your custom logic
Below are the schemas that are used by the prehook. If you're using the reference template, you can customize your business logic in [this](https://github.com/inkeep/copilot-prehook-template/blob/main/api/index.ts) file.
### Request
The request to your API endpoint will include information the Copilot has in relation to the current ticket. You can use this information, like a user email or ID, to fetch information from downstream services.
#### Request examples
```js
// POST /your-route
Headers: {
host: 'your-endpoint-url',
'content-type': 'application/json',
authorization: 'Bearer INKEEP_SUPPORT_COPILOT_API_KEY',
}
Body: {
ticketId: '120',
ticketAttributes: {
// Standard ticket fields
ticketingPlatformType: 'zendesk',
ticketId: '120',
tags: [ 'tag1', 'tag2', 'tag3' ],
priority: 'normal',
type: 'task',
// Custom ticket fields, where the key is custom_field_{field_id}. See the field ID in your zendesk ticket fields setup to use the correct key.
'custom_field_33823202294419': 'Text value',
'custom_field_37074111502483': 'Text value line 1\nText value line 2',
'custom_field_37074153082259': true,
'custom_field_37074157971731': '1234',
'custom_field_37074158858643': '2025-01-01', // date field
'custom_field_37074163782803': '117', // dropdown field, this is the ID of the ticket/organization/user selected
'custom_field_37076344188179': [ 'q1', 'q4' ] // multiselect field values are an array of strings
},
userAttributes: {
// Standard user fields
id: 11122233344455,
url: 'https://.zendesk.com/api/v2/users/11122233344455.json',
name: 'User Name',
email: 'user@example.com',
created_at: '2024-11-07T08:02:58Z',
updated_at: '2025-01-06T19:35:33Z',
time_zone: 'Pacific Time (US & Canada)',
iana_time_zone: 'America/Los_Angeles',
locale_id: 1,
locale: 'en-US',
organization_id: 13457869872341,
role: 'end-user',
tags: [ 'user-tag1', 'user-tag2', 'user-tag3' ],
active: true,
ticket_restriction: 'requested',
restricted_agent: true,
// Custom user fields, where the key is the field key from your zendesk user fields setup
custom_user_dropdown_field: 'dropdown value',
custom_lookup_rel_field_to_org: '13457869872341', // this is the ID of the organization selected in the dropdown field
custom_user_number_field: 4321,
custom_user_text_field: 'text value'
},
organizationAttributes: {
// Standard organization fields
id: 13457869872341,
name: 'Test Org',
tags: [ 'org_tag' ],
// Custom organization fields, where the key is the field key from your zendesk organization fields setup
custom_organization_date_field: '2025-01-01T00:00:00+00:00',
custom_organization_text_field: 'text field'
},
messages: [
{
id: '120',
createdAt: '2024-11-07T08:02:59.000Z',
content: 'How do I add Inkeep to a Slack workspace?',
authorId: '11122233344455',
authorType: 'user',
authorName: 'User Name',
files: []
},
{
id: '35171330444691',
createdAt: '2024-11-07T08:03:59.000Z',
content: 'I want to add Inkeep as an autoreply bot.',
authorId: '11122233344455',
authorType: 'user',
authorName: 'User Name',
files: [],
isInternalComment: false
},
{
id: '35171348277779',
createdAt: '2024-11-07T08:04:59.000Z',
content: 'Inkeep offers auto-reply functionality for both Slack and Discord:\n' +
'Slack Auto-Reply\n' +
'- Configure the bot to automatically reply to all root-level messages in specific channels(1)\n' +
'...',
authorId: '35089669796243',
authorType: 'member',
authorName: 'AI Agent',
files: [],
isInternalComment: false
}
],
ticketingPlatformType: 'zendesk'
}
```
#### Request parameters
| Parameter | Type | Description |
| ---------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| ticketId | `string` | Unique identifier for the ticket for your support platform. |
| ticketingPlatformType | `string` | The support platform type ("zendesk", "github", "plain", or "other"). |
| ticketAttributes | `object` | Information about the ticket provided by the support platform. |
| userAttributes | `object` | Information about the user provided by the support platform. |
| organizationAttributes | `object` | Information about the organization the user is a member of as provided by the support platform (for business-to-business type scenarios). |
| messages | `MessageObject[]` | List of message objects containing conversation history. |
The exact ticket, user and organization attributes provided are dependent on
the support ticketing platform. If you'd like to fetch more information from
the support platform, you can use the `ticketId` to query relevant
information.
**MessageObject**
| Parameter | Type | Description |
| ----------------- | -------------------- | ------------------------------------------------------- |
| id | `string` | Unique identifier for the message. |
| createdAt | `date` (optional) | Timestamp when the message was created. |
| content | `string` | The message text content. |
| authorId | `string` | Unique identifier for the message author. |
| authorType | `string` | Type of author ("user" or "member"). |
| authorName | `string` (optional) | Name of the message author. |
| files | `array` | List of attached files, each containing `id` and `url`. |
| isInternalComment | `boolean` (optional) | Whether the message is an internal note. |
### Response
The response from your API endpoint should include any additional context you want to provide to the Copilot. You can also include specific instructions to guide how the Copilot should respond. All of the below are **Optional**.
Here's an example response:
```json
{
"userAttributes": [
{
"label": "payment_status",
"value": "overdue",
"description": "Customer has an overdue payment",
"useWhen": "when user asks about billing issues"
}
],
"organizationAttributes": [
{
"label": "support_tier",
"value": "enterprise",
"description": "Organization has enterprise support",
"audience": "member"
}
],
"prompt": "This is an enterprise customer, ensure you use a warm, expedient tone that reflects that we are urgently considering their request. There is currently an outage on the dashboard, so if they mention that, let them know this the team is aware and actively investigating."
}
```
#### Response format
| Parameter | Type | Description |
| ---------------------- | ------------------- | --------------------------------------------------------------------------------- |
| userAttributes | `AttributeObject[]` | **Optional**. List of attribute objects providing context about the user. |
| organizationAttributes | `AttributeObject[]` | **Optional**. List of attribute objects providing context about the organization. |
| ticketAttributes | `AttributeObject[]` | **Optional**. List of attribute objects providing context about the ticket. |
| prompt | `string` | **Optional**. Additional instructions to guide the Copilot's response. |
The `prompt` field is best used for high-level instructions or context that doesn't fit naturally into the attributes. For example, prompt can include:
* Real-time information on a wide-application situation: "There is currently an outage affecting our dashboard. If the user references an outage, link them to the tracker page [here](https://tracking.com)."
* Tone/style guidance: "This is a VIP customer, use an expedited tone..."
* Complex business rules: "If the user mentions feature X, first verify their subscription tier..."
Think of this as dynamic instructions or context for the bot beyond what can be described with attributes.
**AttributeObject**
| Field | Type | Description |
| ----------- | ----------------------------- | ---------------------------------------------------------------------------------------------- |
| label | `string` | Semantic, short identifier for the attribute (e.g., 'subscription\_plan'). |
| value | `string` | The attribute's value (e.g., 'premium'). |
| description | `string` | Optional explanation of the attribute's meaning or implications of the value. |
| useWhen | `string` | Optional condition for when the copilot should consider or use this attribute. |
| audience | `"user" \| "member" \| "any"` | Optional field to specify which type of participant can see this attribute. Defaults to `any`. |
`useWhen` and `description` should contain the core details of when this attribute may or may not be relevant and how it should be used.
For more complex scenarios, use `xml` or `markdown` format to specify behavior. Check out our [prompting guide](/projects/rules-and-prompts) for ideas.
```typescript title="inkeepSupportCopilotSchemas.ts"
import { z } from "zod";
import { MessageSchema } from "./MessagesSerializer";
// NOTE: These schemas are also in the docs, and copilot-prehook-template repos.
// Any changes here should be reflected in those repos as well.
/* Request Schema */
/* Aim to be optimistic, the request may include more information in the future. */
const isNonEmpty = (val: unknown): boolean => {
if (val === "") return false;
if (Array.isArray(val) && val.length === 0) return false;
if (val && typeof val === "object" && Object.keys(val).length === 0)
return false;
return val !== undefined && val !== null;
};
const MessageSchema = z.object({
id: z.string(),
createdAt: z.preprocess(
(arg) => (arg ? new Date(arg as string) : undefined),
z.date().optional()
),
content: z.string(),
authorId: z.string(),
authorType: z.enum(["user", "member"]),
authorName: z.string().optional(),
files: z.array(
z.object({
id: z.string(),
url: z.string(),
})
),
isInternalComment: z.boolean().optional(),
});
export type MessageType = z.infer;
export const RequestAttributesSchema = z.record(
z.string(),
z.unknown().refine(isNonEmpty, {
message: "Value must not be empty or null/undefined",
})
);
export const CopilotSmartAssistContextHookRequestSchema = z
.object({
ticketId: z.string(),
ticketAttributes: RequestAttributesSchema,
userAttributes: RequestAttributesSchema,
organizationAttributes: RequestAttributesSchema,
messages: z.array(MessageSchema),
ticketingPlatformType: z.enum(["zendesk", "github", "plain", "other"]),
})
.passthrough();
const ReturnAttributeSchema = z
.object({
label: z
.string()
.describe(
"A short identifier or name for the attribute (e.g. 'Subscription Plan')."
),
value: z
.string()
.describe(
"The attribute's value, often a string that can be displayed or processed (e.g. 'premium')."
),
description: z
.string()
.nullish()
.describe(
"An optional explanation or context about how the AI should interpret or use this attribute or particular value of the attribute."
),
useWhen: z
.string()
.nullish()
.describe(
"An optional description of when this attribute should be considered (e.g. 'when user asks about billing')."
),
audience: z
.enum([...MessageSchema.shape.authorType.options, "any"])
.nullish()
.default("any")
.describe(
'The intended audience for this attribute. For example, use "member" for "internal" information that should not be directly referenced in messages to the user.'
),
})
.describe(
"A structured piece of contextual data (attribute) that may be relevant to the copilot depending on the support ticket."
);
export const CopilotSmartAssistContextHookResponseSchema = z
.object({
userAttributes: z
.array(ReturnAttributeSchema)
.nullish()
.describe(
"A list of user-specific attributes providing additional context about the end-user."
),
organizationAttributes: z
.array(ReturnAttributeSchema)
.nullish()
.describe(
"A list of organization-specific attributes providing additional context about the user's organization or account."
),
ticketAttributes: z
.array(ReturnAttributeSchema)
.nullish()
.describe(
"A list of ticket-specific attributes providing additional context about the ticket."
),
prompt: z
.string()
.nullish()
.describe(
"Optional custom instructions or guidance to influence the copilot's response (e.g. special handling instructions, tone guidelines)."
),
})
.describe(
"The schema returned by the customer-owned endpoint, providing structured context and an optional prompt to guide the copilot's responses."
);
export type CopilotSmartAssistContextHookResponse = z.infer<
typeof CopilotSmartAssistContextHookResponseSchema
>;
```
## 3. Configure the prehook in the Inkeep Dashboard
Once your endpoint is deployed, configure it from the Inkeep Dashboard. Creating a separate copilot integration is recommended if you want to test the prehook without affecting your main copilot. More on this in the Testing section below.
1. Create a new Support Copilot integration in the Inkeep Dashboard. Follow the steps [here](/support-tools/agent-copilot/zendesk#generate-an-api-key) and give it a name like "Support Copilot with Prehook".
2. Expand **Advanced Settings**.
3. Under **Prehook URL**, enter the full URL of your API endpoint. Example: `https://your-app-deployment-url.vercel.app/api`.
4. Under **Headers (JSON)**, enter the headers you want to include in the prehook request. See below.
5. Click **Save**.
Once this is saved, this new Copilot will use your prehook to get additional context and instructions when it runs.
#### Custom headers
In the **Headers (JSON)** field, you can configure custom headers to be included in the prehook request. While `Content-Type: application/json` is always included, you can use this to add additional headers, like for authentication. The value should be a valid JSON object with double quotes.
**Example**: To secure the API request, you can configure the headers to include an API key. For example:
```json
{ "Authorization": "Bearer your-api-key" }
```
The template implementation includes a validation for this, so `your-api-key` should match the value of the `INKEEP_SUPPORT_COPILOT_API_KEY` environment variable.
If using your own implementation, ensure you implement your own validation of relevant headers.
The **Headers (JSON)** field is encrypted at storage, so it's safe to include
sensitive information like API keys.
## 4. Testing your prehook
Once you've configured your prehook in the Inkeep Dashboard, you can test it by updating your setup in your support platform and clicking on `Smart Assist`.
### Developing locally with ngrok
To test your prehook locally before deploying to production, you can use ngrok to create a public URL for your local development server:
1. Start your local development server:
```bash
# If using the reference template:
vercel dev # Runs on http://localhost:3000/api
# If using your own implementation:
# Start your server using your preferred method
```
2. Install and set up ngrok:
* Install from [ngrok.com/download](https://ngrok.com/download) and follow the setup instructions
3. Create a secure tunnel to your local server:
```bash
# Replace 3000 with your local server's port number
ngrok http 3000
```
4. In the ngrok output, copy the HTTPS URL (e.g., `https://1234-your-tunnel.ngrok.app/api`)
5. Use this URL as your prehook URL in the Inkeep Dashboard
**Important**: The ngrok URL is temporary and changes each time you restart
ngrok.
### Testing in your support platform
1. Install another Zendesk app to be used for testing following the steps [here](/support-tools/agent-copilot/zendesk#install-the-zendesk-app), making sure to use the API key from the new "Support Copilot with Prehook" integration from the previous step.
2. Open your test Zendesk app and click on `Smart Assist`. The Copilot should now use your prehook.
3. Once you're done testing, you can [update your API key](/support-tools/agent-copilot/zendesk#updating-your-api-key) in your original Zendesk App configuration with the API key from the new "Support Copilot with Prehook" integration.
4. Disable or delete your test Zendesk app.
***
title: Auto-reply to support tickets with Inkeep AI
sidebarTitle: Tickets
icon: LuTicket
keywords: ticket automation, support tickets, auto-reply, ticket management, automated responses, support automation, ticket workflow, response handling, ticket processing, support efficiency, automated support
***
## Overview
This guide provides instructions for how to setup an AI auto-reply with Zendesk. The [template repo](https://github.com/inkeep/zendesk-inkeep-autoreply-template) can be adapted to work with any support platform.
By default, the auto-responder implementation:
* Provides an AI generated answer if it is `very_confident`
* Leaves an internal note if it is not confident
* Supports customizing behavior based on ticket tags and attributes
The [webhook](https://github.com/inkeep/zendesk-inkeep-autoreply-template/blob/main/src/app/api/webhook/route.ts) logic can be customized to your requirements. For example, you can:
* Customize when to bypass the AI autoresponse based on ticket tags, user attributes, or other criteria
* Add your own disclaimer language
* Control the auto-reply flow and response behavior
* Implement different handling for different types of tickets
## Prerequisites
Ensure you have:
1. A Zendesk account with admin access
2. Get an [Inkeep API key](/ai-api/chat-completions-api#get-an-api-key)
3. Access to deploy an API route (e.g., using Vercel Serverless Functions)
## 1. Deploy the webhook
The fastest way to get started is to deploy the serverless API route to Vercel:
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Finkeep%2Fzendesk-inkeep-autoreply-template\&env=ZENDESK_SUBDOMAIN,ZENDESK_API_TOKEN,ZENDESK_API_USER,AUTO_RESPONDER_INKEEP_API_KEY,ZENDESK_WEBHOOK_SECRET)
Simply configure these environment variables:
| Variable | Description |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ZENDESK_SUBDOMAIN` | Your Zendesk subdomain (e.g., if your Zendesk URL is mycompany.zendesk.com, enter 'mycompany') |
| `ZENDESK_API_TOKEN` | Your Zendesk API token ([generate from Zendesk Admin settings](https://support.zendesk.com/hc/en-us/articles/4408889192858-Managing-access-to-the-Zendesk-API#topic_bsw_lfg_mmb)) |
| `ZENDESK_API_USER` | Email address of the Zendesk user that generated the API token |
| `AUTO_RESPONDER_INKEEP_API_KEY` | Your Inkeep API key |
| `ZENDESK_WEBHOOK_SECRET` | A secret key for the Zendesk webhook |
Optional:
| Variable | Description |
| ------------------------- | --------------------------------------------------------------------------------------------- |
| `AI_AGENT_USER_ID` | The User ID you'd like the AI bot to have if leaving internal comments |
| `ENABLE_PUBLIC_RESPONSES` | Set to `true` to make AI responses visible to customers (defaults to internal responses only) |
## 2. Configure your local environment variables
Copy the `.env.sample` file to `.env` and configure the missing variables with the values you used in the previous step.
These variables are used by the scripts you will run in the next step.
## 3. Configure Zendesk
Now, let's configure Zendesk to send a webhook to your API route when new tickets are created.
### Option A: Automated (Recommended)
1. Navigate to the [webhook\_setup folder](https://github.com/inkeep/zendesk-inkeep-autoreply-template/tree/main/webhook_setup) in your local terminal (`cd webhook_setup`).
2. Enable execution of the setup script by running `chmod +x setup.sh`.
3. Execute it with `./setup.sh`. This will create the webhook and trigger for you.
The script will write the created webhook and trigger IDs to a file named `.webhook_resources`. You can use these IDs later to clean up the resources by running the cleanup script: `chmod +x cleanup.sh` and `./cleanup.sh`.
1. In Zendesk Admin Center, go to **Apps** and **Integrations** >
**Webhooks** 2. Create a new webhook with the following settings: - Name:
`Inkeep Smart Replies` - Endpoint URL: Your deployed Vercel URL +
`/api/webhook` (e.g., `https://your-app.vercel.app/api/webhook`) - Request
method: `POST` - Request format: `JSON` - Basic authentication: `No` -
Active: `Yes` 3. Create a trigger to invoke the webhook: - Go to **Admin
Center** > **Objects and rules** > **Business rules** > **Triggers** - Click
**Add trigger** - Name it `Inkeep Smart Reply Trigger` - Set conditions: -
**Ticket**: Is Created - Set actions: - **Notify webhook**: Select the
webhook you created
## 4. Test the Setup
To verify everything is working correctly:
1. Create a ticket:
* Go to your Zendesk workspace
* Create and submit a ticket with a test message
2. Verify answer:
* Check that an AI-generated response was added as a reply or internal note
* The note should be from the user specified in your `AI_AGENT_USER_ID`
## Debug Mode
By default, the AI Autoresponder runs in debug mode (internal notes only). In this mode, responses will only be visible to your support team as internal notes and not to the end-users.
To enable customer-facing responses:
1. Set the environment variable: `ENABLE_PUBLIC_RESPONSES=true`
2. Redeploy the application
When `ENABLE_PUBLIC_RESPONSES` is not set or is set to any value other than "true", the AI Auto Responder will only create internal notes (not visible to end-users) when responding to tickets.
**Review the Zendesk webhook activity:**
* In Zendesk Admin Center, go to **Apps** and **Integrations** > **Webhooks**
* Click on your **Inkeep Smart Replies** webhook
* Check the **Activity** tab to confirm the webhook fired for your test ticket
* Verify the webhook shows a successful (200) response
**Check the Vercel logs:**
* Go to your Vercel dashboard
* Select your deployed application
* Navigate to **Deployments** > **Latest Deployment** > **View Functions Logs**
* Look for logs showing the webhook request was received and processed
**Check that your Zendesk Workspace is configured to send emails on public replies to tickets:**
* Look at the Zendesk email tigger guide [here.](https://support.zendesk.com/hc/en-us/articles/4408823742618-My-customers-don-t-receive-emails)
**If your auto-responder is timing out:**
* The default maxDuration on Vercel free plan is 60 seconds. This is the maximum time the AI can take to generate a response. You can increase this by setting the `maxDuration` parameter on the route.ts file and upgrading to a paid Vercel plan.
**Double-check the environment variables are configured correctly**
**Webhook/Trigger Issues:**
If you experience problems with the webhook or trigger:
1. Manually deactivate them in Zendesk:
* Visit `https://YOUR-SUBDOMAIN.zendesk.com/admin/objects-rules/rules/triggers`
* Replace YOUR-SUBDOMAIN with your Zendesk subdomain
2. Or run the cleanup script to remove the trigger/webhook pair:
```
chmod +x ./cleanup.sh
./cleanup.sh
```
You can customize the auto-reply behavior based on Zendesk ticket tags. The webhook receives the full ticket data, including tags, which you can use to control the flow:
1. First, ensure your Zendesk trigger adds the appropriate tags before the webhook is called
2. In the webhook code, you can access ticket tags from the API response:
```typescript
const ticket = await client.tickets.show(ticketId);
const tags = ticket.tags;
```
3. Implement your custom logic based on tags:
```typescript
if (tags.includes('no-auto-reply')) {
return; // Skip auto-reply
}
if (tags.includes('priority-support')) {
// Custom handling for priority tickets
}
```
Common use cases include:
* Bypassing auto-reply for specific ticket types
* Different response templates based on ticket category
* Varying confidence thresholds for different types of inquiries
***
title: Auto-reply to live chat with Inkeep AI
sidebarTitle: Live chat
icon: LuMessagesSquare
keywords: live chat, auto-reply, chat automation, customer support, chat responses, automated messaging, chat integration, support automation, chat configuration, response automation, chat management
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
Inkeep's Live Chat AI Agent integrates with Zendesk Messaging to provide intelligent, real-time responses to customer inquiries. The AI agent can handle common questions, provide product information, and escalate complex issues to human agents when needed.
## Demo
Try out our live demo to see the AI agent in action:
[Launch Demo](https://zendesk-copilot.inkeep.com/demo/inkeep)
## Key Features
* **Real-time AI Responses**: Instantly responds to customer inquiries using your knowledge base
* **Seamless Human Handoff**: Automatically transfers complex conversations to human agents
* **Knowledge Base Integration**: Leverages your existing documentation to provide accurate answers
* **Conversation History**: Maintains context throughout the chat for natural interactions
* **Custom Branding**: Matches your brand's look and feel
* **Analytics & Insights**: Track performance metrics and conversation quality
## Benefits
* **24/7 Availability**: Provide instant support around the clock
* **Reduced Wait Times**: Handle multiple conversations simultaneously
* **Consistent Responses**: Ensure accurate and standardized information
* **Agent Efficiency**: Free up human agents for complex issues
* **Cost Effective**: Scale support operations without proportionally increasing costs
## Getting Started
To implement the Live Chat AI Agent:
1. Contact our [support team](mailto:support@inkeep.com?subject=Live%20Chat%20AI%20Agent%20-%20Getting%20Started) to get started
2. Provide your Zendesk credentials and configure integration settings
3. Customize the AI agent's responses and behavior
4. Test the integration in a sandbox environment
5. Deploy to production
For detailed implementation guidance or questions, reach out to our [support team](mailto:support@inkeep.com).
***
title: Route, classify and label your support tickets
sidebarTitle: Smart Routing
icon: LuGitBranch
keywords: ticket routing, support automation, routing API, ticket management, automated routing, support workflow, ticket assignment, routing configuration, support efficiency, workflow automation, ticket handling
***
## Overview
This guide demonstrates how to use the [Inkeep AI Context API](/ai-api/chat-completions-api) to programmatically triage and route tickets.
With `inkeep-context` you can:
* **Categorize** the ticket (e.g. between "feature\_request", "account\_billing", or "production\_issue").
* **Extract static fields** - for example, detect if a user has mentioned an invoice ID.
* **Label** the ticket with a `Subject` or other fields you'd typically ask a user to fill out manually.
* **Summarize** the ticket and leave the summary as an internal note for your team.
For example, you may:
* Route production issues directly to an engineering-led queue.
* Choose topics you'd like Inkeep [auto-reply AI](../auto-reply/tickets) to respond to vs ones you'd like to route directly to your team.
* Populate custom, structured fields in your support ticket system from the user's request.
The `inkeep-context` API automatically uses your Inkeep knowledge base as context while generating a response.
While this example leverages the [Vercel AI SDK](https://sdk.vercel.ai/docs/introduction) and assumes a JavaScript backend, the same principle pattern can be used with any backend language and with any OpenAI compatible SDK.
Since the API follows the OpenAI chat completions format, you can define any custom fields or tool calls relevant for your scenario.
## Get started
1. **Inkeep API Key**: If you haven't created one yet, get an [Inkeep API Key](/ai-api/chat-completions-api#get-an-api-key).
2. **Install dependencies**: Install the `ai`, `@ai-sdk/openai` and `zod` packages.
```bash
npm install @ai-sdk/openai ai zod
```
```bash
bun add @ai-sdk/openai ai zod
```
```bash
pnpm add @ai-sdk/openai ai zod
```
```bash
yarn add @ai-sdk/openai ai zod
```
## Example
In the following scenario, we demonstrate how a single call to the [`inkeep-context` API](/ai-api/chat-completions-api) can be used to output all the relevant fields we'd like for our workflow.
### 1. Define a schema
You can use `zod` to define a schema of any structured information we'd like from the AI.
```ts schema.ts
import { z } from "zod";
export const TicketSchema = z.object({
subject: z
.string()
.describe(
"A concise (max 80 chars) subject line summarizing the main topic or request of the ticket."
),
summary: z
.string()
.describe(
"A clear, direct internal note capturing the key context and summary of key aks of the ticket. Will be left as an internal note to the support team."
),
category: z
.union([
z
.literal("production_issue")
.describe("Issues affecting production systems or service disruptions"),
z
.literal("account_billing")
.describe(
"Billing requests related to an existing account, including refunds, cancellations, etc."
),
z
.literal("feature_request")
.describe("Requests for new features or enhancements"),
z
.literal("other")
.describe(
"Any other category that does not fit well with the above categories"
),
])
.describe(
"The primary category of the ticket. Choose only from the valid options."
),
invoiceId: z
.string()
.nullish()
.describe(
"(Optional) The invoice ID, if mentioned in the text. Should be undefined or null if no invoice ID is mentioned"
),
});
```
We use the `describe()` function to prompt the AI on how it should "think" about each field. See our [prompting guide](/projects/rules-and-prompts) for more advanced scenarios.
### 1. Initiate the AI client
First, lets create the Inkeep AI client.
```ts model.ts
import { createOpenAI } from "@ai-sdk/openai";
export const inkeepClient = createOpenAI({
apiKey: process.env.INKEEP_API_KEY,
baseURL: "https://api.inkeep.com/v1",
});
export const model = inkeepClient("inkeep-context-expert");
```
Alternatively, you can use any AI provider for this task. For example:
```ts title="Anthropic" {2,4}
import { anthropic } from "@ai-sdk/anthropic";
export const contextModel = anthropic("claude-sonnet-4-20250514");
```
```ts title="OpenAI" {2,4}
import { openai } from "@ai-sdk/openai";
export const contextModel = openai("gpt-4o");
```
This may be beneficial for low-latency scenarios where the AI model doesn't need extensive context about your product.
### 3. Add business logic
Here, we'll use the [`generateObject`](https://sdk.vercel.ai/docs/reference/ai-sdk-core/generate-object) function to request data in this structure from the `inkeep-context` API.
```ts
import { generateObject, type CoreUserMessage } from "ai";
import { TicketSchema } from "./schema.ts";
import { contextModel } from "./model.ts";
export async function triageTicket(
serializedTicket: CoreUserMessage["content"]
) {
const { object: ticketInfo } = await generateObject({
model: contextModel,
schema: TicketSchema,
maxRetries: 2,
messages: [
{
role: "system",
content:
"You are a system that classifies and extracts data from a user's support request.",
},
{
role: "user",
content: serializedTicket,
},
],
});
const { category, invoiceId, subject, summary } = ticketInfo;
/* BUSINESS LOGIC */
if (ticketInfo.category === "production_issue") {
console.log("Routing to engineering queue...");
} else if (ticketInfo.category === "account_billing") {
console.log("Escalating to finance team...");
} else if (ticketInfo.category === "feature_request") {
console.log("Routing to product backlog...");
} else {
console.log("Routing to general support...");
// ...etc.
}
return ticketInfo;
}
```
In the `BUSINESS LOGIC` section, you can handle creating or updating a ticket in your support platform, calling the `inkeep-qa` API to get an [automated reply](/support-tools/auto-reply/tickets), add internal comments, etc.
For more advanced workflows or AI agents, you can use [tool calling](https://sdk.vercel.ai/docs/ai-sdk-core/tools-and-tool-calling) as well.
***
title: Add Inkeep to Internal Slack
description: Integrate Inkeep's AI assistant into your internal Slack workspace for team support and knowledge sharing.
keywords: Slack integration, internal teams, Slack bot, AI assistant, team support, knowledge sharing, Slack automation, team collaboration, workplace tools, Slack app, internal communication
sidebarTitle: AI Assistant for Slack
icon: slack
-----------
## Overview
You can add the Inkeep Slack bot to your workspace for your:
* 1:1 channels shared with your customers
* Collaboration channels between internal teams, like support and engineering
* Dedicated `#ask-ai` channel for your team
## Get Workspace ID
To configure the bot, you'll need your Slack Workspace ID:
1. Open the Slack app in your [browser](https://app.slack.com/client).
2. Select the target workspace
3. Copy the `{WORKSPACE_ID}` from the browser's navigation bar. The URL will be in the format `https://app.slack.com/client/{WORKSPACE_ID}/{CHANNEL_ID}`. **Workspace ID typically starts with a `T` and is in the format of `TXXXXXXXXXX`.** Channel IDs are typically in the format of `CXXXXXXXXXX`.
4. Alternatively, you can find the ID in the workspace settings.
## Create Assistant
To use the Inkeep Slack bot, we first need to register it as an assistant.
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Assistants** tab within the desired project
3. Click on **Create assistant**
4. From the dropdown menu, choose **Slack**
5. Fill in the required fields **Name** and **Workspace ID**.
6. Click on **Create**
If you already have an existing Inkeep Slack assistant for a Slack workspace, then de-select **Is default for workspace** during the creation of a new assistant. Only one assistant can be the default for a workspace.
After creating the new assistant, click on **Advanced Settings** and specify the Channel IDs (format `CXXXXXXXXXX`) the bot is able to respond in under **Enabled for Channels**.
This is only required if you need Inkeep Slack bots that behave differently in different channels or map to different projects.
## Add to workspace
To install the Inkeep Slack bot in your workspace:
1. Click [here](https://install.inkeep.com/ask-slack)
2. Select the desired workspace
3. Confirm the installation.
### Create a channel (optional)
If you don't yet have a channel you'd like to add Inkeep to, you can create an `β¨ask-ai` or similarly named channel. Move or pin it to the appropriate sections in your workspace for visibility.
### Add to channels
Open the workspace you added the **Ask Inkeep** bot to.
Navigate to the channel you'd like to add Inkeep to.
Type `@Ask Inkeep` with an example question:
```
@Ask Inkeep How do I get started?
```
**Confirm** Slack's prompt to add the bot to the channel.
Repeat the steps for any other desired channels.
The "Ask Inkeep" bot **must** be added as a member of the channel.
### Send a direct message
Create a new message in Slack addressed to `@Ask Inkeep` or follow the steps below:
1. Find **Ask Inkeep** underneath the **Apps** section
2. Click on the **Messages** tab
3. Type a message and click **Send**
If you see a message saying, `Sending messages to this app has been turned off.`, please restart the Slack app to enable direct messages.
If you are not getting a response from the bot, please reinstall the Slack bot by using the `Install bot` button in your Slack Assistant Settings page.
Donβt uninstall the app, just reinstall it so it is kept in all your channels. This will also enable it for everyone else in your Slack workspace.
### Loop-in mode
Instead of having the bot automatically reply to every message, you can use Loop-in mode to tag `@Ask Inkeep` only when you need AI assistance. The bot can be tagged at the top level of a channel or within any existing thread, and it will provide context-aware suggestions based on the conversation so far.
This mode is ideal for:
* Support triage channels where you want AI assistance on demand
* Collaboration channels where you want to selectively get AI input
* Any channel where you prefer manual control over when the bot responds
### Use as an auto-reply bot
Instead of requiring a user to tag the bot with `@Ask Inkeep`, you can configure the Slack bot to automatically reply to all new top-level messages in specified channels.
To configure:
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Assistants** tab within the desired project
3. Select the assistant
4. Expand **Advanced Settings**
5. Configure the following:
* **Auto-reply in the below channels**: Specify the channel IDs where you want the bot to auto-reply
* **Reply message (optional)**: Enter a custom initial message for the bot to use when it's tagged or auto-replies
6. (Optional) Adjust the tone of the bot by enabling either of these two options:
* **AI Draft Mode**: Designed for when the bot is used as a way to create draft messages for support team members
* **Human Reviewing Conversations**: Designed for when team members are actively reviewing and monitoring conversations. It gives the user a heads up that a team member will step in quickly if needed
7. Click **Save** to apply the changes
## Customize your bot
You can customize the name of the bot, the image used with it, and the default responses it sends.
### Upload an organization avatar (required)
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Settings** tab at root of your Inkeep organization (`https://portal.inkeep.com/{orgAlias}/settings`)
3. Under **Avatar**, select **Choose File** or if there's an existing file, hover over the existing avatar and click **Change**
4. Upload a PNG (preferred) or JPG file you'd like to use as your avatar. Recommended dimension: 512x512. Note that SVGs are not supported by Slack.
### Configure the bot name
1. In your Slack workspace, click on **Add apps** underneath the **Apps** section in your sidebar
2. Select **Ask Inkeep**
3. Click on **Configuration**
4. Scroll to **Bot User** section and click on **Edit**
5. Specify the desired name of the bot, e.g. `Ask CompanyAI`
Now, you and your users will be able to tag the bot using this name, e.g. `@Ask CompanyAI`.
When typing `@` and in a few other places, Slack will still display the default Inkeep icon. However, any posts made by the bot will show your actual avatar. Your custom name will always be displayed.
### Configure default responses
You can configure the bot to send a default responses to users in different scenarios.
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Assistants** tab within the desired project
3. Select the assistant
4. Expand **Advanced Settings**
5. Under **Custom Responses**, see the list of responses you can configure
6. Click **Update**
7. Your bot will now use these responses.
## Tag a team member
Sometimes, you want users to be able to escalate to a human for additional help.
To make this flow seamless, you can configure your bot to show **Mark as resolved β
** and **Ask for help π** buttons instead of the default π π buttons at the end of messages.
When a user clicks on **Ask for help π**, the bot can tag users, user groups, or other bots.
To set up:
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Assistants** tab within the desired project
3. Select the Slack assistant
4. Expand **Advanced Settings**
5. Under **When a user leaves negative feedback...**, click the dropdown menu
6. Select **Tag a team member**
7. Specify the **User IDs**, **Group IDs**, or **Bot IDs** you'd like to tag
You can get the IDs by left-clicking on a profile on Slack, selecting the more options button (often represented as three dots), and clicking on **Copy member ID** or **Copy group ID**. To create a group of users on Slack, see [this](https://slack.com/help/articles/212906697-Create-a-user-group) guide.
We recommend creating a custom bot, e.g. `@Triaging Bot`, that contains the logic you'd like to use for triggering custom down-stream workflows.
***
title: Add Inkeep AI Assistant to GitHub
description: Our Inkeep AI Assistant bot works by automating initial responses to GitHub issues.
sidebarTitle: AI Assistant for GitHub
icon: github
keywords: AI assistant, community support, GitHub bot, issue resolver, community management, automated support, GitHub automation, member engagement, community tools, GitHub app, community assistance
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
You can add Inkeep AI Assistant as a GitHub bot to help scale support to your users. Before you go live, you can preview all replies in the Inkeep Portal. The Inkeep AI Assistant will not reply to any GitHub issues until you explicitly enable public responses.
## Create Assistant
To use the Inkeep GitHub bot, we first need to register it as an assistant.
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Assistants** tab within the desired project
3. Click on **Create Assistant**
4. From the dropdown menu, choose **GitHub Issues Autoresponder**
5. Fill in the required field **Name**.
6. Click on **Create**.
7. Click onto the organization where you want to install Inkeep-AI-Assistant
8. Select which repositories you want to install the GitHub bot on. Installation requires **Admin** permissions on the repository. If you lack Admin access, your request will be routed to an Admin for approval.
## Debug Mode
By default, the GitHub bot is configured to have public responses set to **False**.
To enable the autoresponder, open the assistantβs settings and toggle **Enable public responses** on.
## When does the Bot reply
Whenever you **open a new issue or reopen a closed one** the Inkeep AI Assistant evaluates its confidence via a builtβin Inkeep meter and generates a draft reply thatβs always sent to your analytics portal. If its confidence score meets the threshold for a confident response **and** you have **Enable public responses** turned on, it will also post that reply as a GitHub comment; otherwise it stays hidden in the portal for review.
Additionally, tagging the bot will generate a response regardless of confidence level. To tag the bot simply respond to an issue with a comment that includes **@inkeep** or **@inkeep-ai-assistant**.
1. Navigate to [GitHub](https://github.com)
2. Click on profile and navigate down to Settings
3. Click on Applications and hit configure on the GitHub bot
4. Under Repository access, choose which repositories the bot should have access to
5. Click Save to apply changes
***
title: Content & Feature Gaps
sidebarTitle: Content Gaps
icon: bullseye
description: Identify documentation gaps and feature requests through AI-powered insights
keywords: content gaps, feature requests, documentation analysis, AI insights, content prioritization, product gaps, user feedback analysis, documentation improvements, content strategy, feature analysis, user needs, content optimization, documentation quality
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
*"Prefer a visual walkthrough? Check out this video instead."*
## Overview
**AI Reports** pinpoint and summarize specific documentation or product gaps based on user conversations.
Reports are used by:
* Content teams to have a data-driven way to prioritize documentation updates.
* Product teams to identify top features or functionality users are asking for.
* Marketing teams to identify blog and other content marketing opportunities.
### Create a report
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Select your project
3. Click on **Insights** in the sidebar
4. Choose the report of your desired time frame (available weekly and monthly)
A report looks like:
And is segmented into two sections:
### 1. Features and Functionality
This section of the report synthesizes gaps core to your product. At the top of each topic card there is an AI generated summary with specific details on what the gaps were related to that topic. Related user conversations that generated the insight are also listed.
### 2. Third-Party Integrations
This section is similar to the above, but focused on gaps related to third party tools and services that a user may mention in relation to your product. For example, "slack" and "Zendesk" may appear in our reports. This section helps reveal common integration requests and what tools customers are using with your product.
## Use as Filters in Chat Sessions
If you prefer to view documentation or feature gaps on a conversation-by-conversation level, you can use the **Chat Sessions** experience.
0. Open the relevant Project in the [Inkeep Dashboard](https://portal.inkeep.com)
1. Navigate to **Chat Sessions**
2. Use the **Documentation Gap** and **Feature Supported** filters
3. Click on individual rows to view each full conversation
***
title: Viewing Conversation Details and Stats
sidebarTitle: Usage Reports
icon: chart-line
keywords: chat sessions, usage metrics, conversation analytics, user engagement, feedback tracking, chat statistics, analytics dashboard, user interactions, chat performance, data analysis, conversation tracking, user behavior, chat monitoring, analytics reporting
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
*"Prefer a visual walkthrough? Check out this video instead."*
## Chat Sessions
With the **Chat Sessions** table you get a granular view of all conversations users are having with your AI assistant.
You can:
* **View full conversations** - view all chats in full, including sources used and all messages.
* **Review Thumbs Up / Thumbs down** - review conversations users gave feedback on.
* **Use AI filters** - drill down on questions where there wasn't supporting content in your documentation.
* **Export as CSV** - download all question-answer pairs for further analysis.
## Usage Metrics
In the **Analytics** dashboard you can see key statistics about how users engage with your AI assistant.
Metrics include:
* **Total chat messages**
* **Chat sessions**
* **Unique users**
* **Thumbs up vs. Thumbs down**
* **Chat messages over time**
* **Code snippets copied**
* **Chat messages copied**
* **Shared chats**
* **New chat sessions**
Want to correlate AI chat usage with your own user funnels or BI stack? Follow [this guide](/ui-components/customization-guides/use-your-own-analytics).
***
title: Projects Overview
sidebarTitle: Overview
icon: LuBox
keywords: project management, AI assistant configuration, knowledge base organization, content sources, assistant types, project settings, custom guidance, API integration, web integration, Slack integration, Discord integration, support copilot, project setup, content management, API keys, project configuration, integration setup
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
Projects in Inkeep let you group together related sources and settings specific to a scenario.
For example, you may have independent projects for:
* Customer-facing (Public) vs employee-facing (Private) assistants
* Independent products within your organization
* Development vs production environments
When you start with Inkeep, you'll typically already have at least one project pre-made for you with all your public sources already selected.
## Public vs Private Projects
We recommend separating your projects based on their audience to ensure appropriate content access. Typically, this means two projects for your team vs your users:
| Type | Use Case | Sources | Assistant types |
| ------- | -------------------------- | ---------------- | ------------------------------------------------------------------------- |
| Public | Customer-facing assistants | Public | - Website chat - Documentation - Community forums |
| Private | Employee-facing copilots | Public & Private | - Support Copilot - Internal Slack channels - Help desk systems |
## Settings
Projects have several key settings that define their scenario. These can be configured under **Settings** under a project in the [Inkeep Dashboard](https://portal.inkeep.com).
### Chat Subject Name
The topic that the AI Assistants in the project are knowledgeable about. Typically, this corresponds to a product name like `Inkeep`.
### Get Help Links
When the AI assistant can't answer, it'll incorporate in it's answer links to your support channel\[s].
For example, the AI assistant may say `I wasn't able to find information about {X}, please reach out for additional help at {get_help_link}`
Support channels can include:
* Contact us pages
* Help Center
* Community forums (Slack, Discord)
* Email address
### Custom Guidance
These are custom instructions (prompts) that extend the default behavior of the AI assistant to modify its tone or behavior.
Check out [this tutorial](/projects/rules-and-prompts) to learn more.
## Manage Sources
A Source is a collection of content that your AI assistant can reference. A project can use multiple sources, and sources can be shared between projects.
1. Go to the [Inkeep dashboard](https://portal.inkeep.com)
2. Select **Projects** and click on the project you'd like to configure
3. Click on **Sources**
4. Click on **Select Sources**
5. *Check* or *Un-check* sources to modify the ones used by the Project.
6. Click **Save**
To create additional projects or modify sources, please [contact
us](mailto:support@inkeep.com?subject=Add%20new%20project).
## Assistants
Assistants generally use and inherit settings from the project.
### Types
* **Web**: For your website, docs, app, or help center. See our [quickstarts](/overview/ai-for-customers#add-to-your-site).
* **Slack**: A bot for [Slack communities](/integrations/slack/community) or [workspaces](/integrations/slack/internal-team).
* **Discord**: A bot for [Discord communities](/integrations/discord).
* **Support Copilot**: AI assistant that works as a sidebar within [help desks](/support-tools/agent-copilot/overview).
* **API**: For custom UIs or workflows that use the [Inkeep AI API](/ai-api/chat-completions-api) (chat completion APIs).
### Create an Assistant
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com)
2. Select your project under **Projects**
3. Go to the **Assistants** tab
4. Click on **Create assistant**
5. Select the assistant type
6. Configure assistant-specific settings
7. Get your API key and follow the relevant guide
Each assistant's usage can be tracked separately in analytics.
### Create a Web Assistant
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com)
2. Select your project under **Projects**
3. Go to the **Assistants** tab
4. Click on **Create assistant**
5. Select **Web**
6. Provide a **Name**.
7. Specify a **URL** for where this assistant will be used.
8. For production API keys, leave **Enforce referrer URL** checked.
9. Click on **Create**
10. Click the **Example \< />** button to get your API key and view suggested settings
For local or staging API keys, see [here](/ui-components/public-api-keys).
***
title: Provide custom rules (prompts) for your assistant
sidebarTitle: Rules & Prompts
icon: code-branch
keywords: custom prompts, AI guidance, prompt engineering, LLM configuration, conversation flow, response formatting, tone customization, AI behavior, prompt examples, custom instructions, AI personality, response structure, prompt templates, AI assistant configuration, conversation design, prompt optimization
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
Prompts give you control over the AI Assistant tone and behavior with natural language instructions. We often refer to prompts that follow an `If` -> `Then` format as **Rules**, which we find a useful way to structure prompts.
You can use Rules to customize:
* **Tone**: Use a specific tone throughout the conversation.
* **Structure and Style**: Format answers with a certain style or structure.
* **Length of Answers**: Prescribe how short or long assistant messages should be.
* **Conversation Flow**: Customize the conversation flow, like being more conversational.
* **Ask clarifying questions**: For when you'd like the AI assistant to ask the user clarifying questions on certain topics.
We include examples below for common scenarios that can be good starting points for your own prompts.
By default, Inkeep assistants already minimize hallucinations, cite sources, include guard rails to protect your brand, and have other behaviors we've found to work well for "question answer" support scenarios. When developing your own prompts, we recommend trying the assistant out-of-the-box and identifying specific behaviors you'd like to see that aren't already included.
## Where to configure
### Dashboard
To control the AI Assistant across all or specific assistants of a project:
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to your Project under **Projects**.
3. Under **AI Assistant**, click on **Rules**.
4. Click on **Create Rule**.
5. Add guidance in the `Label`, `If`, and `Then` structure as described in this guide.
6. Click on **Create** to save the rule.
7. You can see the effects by testing the AI assistant under **AI Chat > Sandbox**.
### UI Widgets
If you prefer to customize the guidance on a per-integration basis, you can configure the [aiChatSettings.prompts](/ui-components/common-settings/ai-chat#prompts) property of the `@inkeep/cxkit-react` components.
You can structure the prompts as XML that follow the below structure:
```ts
const prompt = `
{Label}
{If}
{Then}
`;
```
Adding prompts in the UI components can be helpful when the behavior of the assistant should be dynamic, like when incorporated inside of your application and should vary based on user-specific properties or custom application logic. Otherwise, we recommend using the Inkeep dashboard.
### API
In the `inkeep-qa` [API](/ai-api/chat-completions-api), you can provide rules as one or more system-level messages.
```ts
const messages = [
{
role: "system",
content: `
{Label}
{If}
{Then}
`,
},
// ...
];
```
## Prompting LLMs
When creating a rule, we recommend breaking down your instructions into an **Label**, **If**, and **Then** format. This mindset helps structure your instructions in a way that LLMs are more likely to "listen" to.
* **Label**: A succinct summary of the rule you're applying.
* **If**: A brief description of when your rule should be applied, usually as a condition or scenario. If you want it to always be applied, use `At All Times`.
* **Then**: The action or behavior that should occur when the condition is met.
`If` and `Then` statements can be:
* *Short*: Succinct and to the point. Ideal for tones and speech patterns that are common and easy to understand.
* *Long*: Best for complex instructions or when extra context is needed. In these cases, we recommend using **structured Markdown** with **Examples**.
## Example Guidance
* **Label**: `Emoji Inclusion β€οΈ`
* **If**: `At All Times`
* **Then**:
```
Frequent use of emojis and symbols like heart emojis (β€οΈ), American flags (πΊπΈ), and smiley faces π are common, adding a casual, friendly flair to the writing. You should try to always include an emoji!
```
* **Label**: `Answer Every Question Like PERSON A`
* **If**: `At All Times`
* **Then**:
```
Try your best to be helpful and answer the user. When answering questions, use PERSON A's tone and personality, described below:
#### Trait 1: Humorous
**Description**: PERSON A often incorporates light-hearted jokes and playful commentary while still being informative. His humor makes the process feel approachable and fun, even when tackling complex issues.
- **When Introducing a New Topic**:
"Alright, today we're diving into the ultimate solution for modern data managementβour flagship database system! But this isn't just any database; we're talking about the kind of seamless scalability and blazing-fast query speeds that make legacy systems feel like trying to find a needle in a haystack with a flashlight. Been there, done that, and let me tell youβthis is a game-changer."
- **When Giving a Tip**:
"Remember, when designing your schema, keep your tables normalized to avoid redundancy. It's not just for better performanceβit's also a great way to impress your team when you can answer the question 'What's a foreign key?' like a pro."
- **When Something Goes Wrong**:
"Whoops! Looks like you hit a performance bottleneck during peak hours. If you're not too busy chasing error logs, here are a few quick optimization tricks you can use to get your system back on track..."
```
{" "}
* **Label**: `Make All Links Clickable Hyperlinks ` - **If**: `When writing a
link to another website` - **Then**: `` Please make all links clickable
hyperlinks like so: `[title](hyperlink)` ``
* **Label**: `Add Related Sources as Clickable Hyperlinks`
* **If**: `At All Times`
* **Then**:
```
Always finish your messages with links to **Related Sources**.
Attach as a new paragraph at the end of your message with the following format:
Related Sources:
- [Title](hyperlink)[^citation_number]
- [Title](hyperlink)[^citation_number]
- [Title](hyperlink)[^citation_number]
**Important**: **Related Sources** should be more comprehensive and creative than those that strictly contain the answer. They can be materials or resources about the topic of the question, even if they don't contain an explicit answer. Think of it as the explicit sources of your answer plus "Learn more" resources.
```
{" "}
* **Label**: `Avoid Verbosity` - **If**: `At All Times` - **Then**: `Limit
each response to **fewer than 150 words**. You are not allowed to exceed 150
words in your response. Omit the least relevant details where necessary to
stay under this limit.`
* **Label**: `Ask Clarifying Questions About Integration Platform`
* **If**: `User query does not specify which platform or framework they are using when asking about Inkeep integration or setup`
* **Then**:
```
NEVER MAKE ASSUMPTIONS! Ask a clarifying question to understand which platform or framework the user is currently using. This is essential for providing accurate integration guidance since Inkeep supports many different platforms.
# Examples
## Good Examples
**Example 1**
User: "How do I add Inkeep chat to my docs?"
Answer: "I'd be happy to help you integrate Inkeep's chat widget. Which documentation platform or framework are you using (e.g., Docusaurus, Next.js, VitePress, GitBook, etc.)?"
**Example 2**
User: "I want to add AI search to my site"
Answer: "I can guide you through adding Inkeep's AI search. Could you tell me which platform or framework your site is built with?"
**Example 3**
User: "How do I customize the chat widget?"
Answer: "I can help you customize the Inkeep chat widget. Are you using our JavaScript snippet, React components, or integrating through a specific platform?"
## Bad Examples
**Example 1**
User: "How do I add Inkeep chat to my docs?"
Answer: "Here's how to add Inkeep to Docusaurus. First, install the npm package..."
**Example 2**
User: "I want to add AI search to my site"
Answer: "Here's a step-by-step guide to adding the search bar using our JavaScript snippet..."
**Example 3**
User: "How do I customize the chat widget?"
Answer: "You can customize the widget using the aiChatSettings prop in React..."
## Conclusion
Notice how the bad examples jump straight into platform-specific solutions without understanding the user's context? We want to avoid making assumptions and instead gather the necessary information first. DO NOT PROVIDE SPECIFIC INTEGRATION GUIDANCE UNTIL YOU KNOW WHICH PLATFORM THE USER IS WORKING WITH!
```
## General Tips
* **Use Assertive and Direct Language**: Employ clear and concise wording to increase the likelihood that the AI will follow your instructions.
* **Be Specific and Unambiguous**: Write instructions that are detailed and leave no room for interpretation. If a human might misunderstand your instructions, an LLM likely will too.
* **Include Examples**: Provide brief examples of both correct (good) and incorrect (bad) outputs to common scenarios relevant to a given rule.
* **Use Exclamations and Bold Text for Emphasis**: Highlight important phrases and words by incorporating exclamation points and applying bold formatting.
* **Be careful with XML Tags**: XML Tags can be powerful tools to structure and organize your prompts. However, if you use them, ensure they are properly closed. Use Markdown to start, and XML if your instructions get lengthy or list-like.
* **Don't Be Afraid to Explain Reasoning**: Within your action, you can explain your reasoning for how the examples were chosen and how the rule was applied. This helps the LLM understand your intent.
* **Test Thoroughly**: Create diverse test cases that capture your scenarios and verify the AI Assistant behaves consistently across all of them.
* **Increase Level of Detail Gradually**: Start with concise rules, but be prepared to use longer and more prescriptive `If` and `Then` statements as you test your prompts.
{" "}
Paste the content of this file into Anthropic's Claude or ChatGPT, and ask it
to help you improve and iterate your prompt based on the guidance and examples
in this document.
## Conclusion
Custom Guidance can help customize your AI assistant to your liking. If you need help, reach out to [prompting@inkeep.com](mailto:prompting@inkeep.com?subject=Help%20with%20prompting).
***
title: Tune Answers with FAQs
sidebarTitle: Tune Answers
icon: sliders
keywords: FAQ management, answer tuning, knowledge base customization, AI response optimization, custom FAQs, answer correction, private knowledge, response management, AI training, knowledge base updates, answer configuration, FAQ creation, answer improvement, knowledge management, AI customization
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
*"Prefer a visual walkthrough? Check out this video instead."*
## Overview
Inkeep managed **FAQs** let you add question-answer pairs to your AI assistant knowledge base. FAQs can be used for two scenarios:
* **Tuning Answers**: You can use FAQs to correct or "tune" answers from the AI assistant. FAQs are treated as high priority sources of truth for the AI assistant that "override" what it may see in other content sources or how it responds.
* **Document Private Knowledge**: Sometimes, there is knowledge you want the AI assistant to know but doesn't easily belong in your docs or public content. You can treat Inkeep's FAQs as a private set of FAQs for your AI assistant.
Most customers do **not** find the need to tune answers. Inkeep is designed to
be accurate and be clear and transparent when it's unsure. If you do see poor
answers, we suggest checking if there's missing information, conflicting
information, or ambiguous terms in the underlying documentation or supporting
content. Fixing this often resolves issues and is beneficial to both the AI
and end-users.
## Accessing FAQs
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Select your project
3. Click **Tune AI with FAQs** in the sidebar
## Managing FAQs
### Create an FAQ
1. Click **+New FAQ** in the top-right corner
2. Fill in the fields:
* **Question**: (Required) The primary question to match. Matches don't have to be exact.
* **Alternative questions**: (Optional) Add variations of how users might ask similar questions for which the same answer applies.
* **Answer**: (Required) Your preferred response
* **External URL**: (Optional) Link to reference material or source of answer. This is not shown to users, it's used for internal tracking.
3. Confirm **Is enabled?** is toggled for the FAQ to be active
4. Click **Save**
### View and Edit
From the **Tune AI with FAQs** tab, you can search, edit, and enable or disable FAQs.
## Best Practices
### Writing Effective FAQs
* **Be Specific**: Target precise questions rather than broad topics
* **Keep it Concise**: Provide clear, direct answers
* **Stay Current**: Regularly review and update content
## FAQ Sources
The **Tune AI with FAQs** tab is actually a consolidated list of all FAQs across all "Custom FAQs" sources.
A **Custom FAQs** source may come from:
1. **Default for Project**: Whenever a project is created, there is a default **Tuning FAQs** source also created for the project.
2. **Manual Creation**: Created directly from the Sources management UI.
3. **Support Tickets**: Created whenever a [Support Copilot](/support-tools/agent-copilot/draft-faq) assistant is created. The **Ticket into FAQ** feature will save FAQs to this source.
## Project Scope
You may enable a **Custom FAQs** source to be used across more than one project if you'd like. To do so, [enable the source](/projects/overview#manage-sources) in the corresponding projects.
***
title: Onboarding sources
icon: LuBoxes
keywords: content onboarding, source integration, content management, data sources, content ingestion, source configuration, content setup, data integration, source management, content indexing, source setup
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Our goal is to make it effortless to create a knowledge base for search and chat experiences. With our integrations and intelligent crawlers, we automatically index, chunk, embed, and re-rank all types of different content to get the best search and chat retrieval performance (learn more [here](../overview/why-inkeep)).
## Onboarding new content
Send us a message over Slack or send an email to [sources@inkeep.com](mailto:sources@inkeep.com?subject=Adding%20a%20new%20source%20to%20Inkeep). We personally onboard and vet the quality of all new sources.
## Common sources
Below are sources that we support out of the box. Note that this list is *not exhaustive*, we're generally able to ingest any source.
### Documentation
* Document360
* Docusaurus
* Next.js (Nextra and custom)
* Astro (Starlight and custom)
* Mintlify
* ReadMe
* MkDocs
* GitBook
* Redocly
* VitePress / VuePress
* Sphinx
* Read the docs
* Hugo
* Gatsby
* Custom
### Community
* Discourse
* Slack threads
* Discord threads
### Marketing / blogs / landing pages
* Webflow
* Framer
* Next.js
* Astro
* Custom
### CMS / Blogs
* Wordpress
* Sanity
* Prismic
* DatoCMS
* Contentful
* Strapi
* Agility CMS
* Cosmic
* ButterCMS
* Storyblok
* Hygraph
* Sitecore
* Custom
### Technical
* GitHub (pull requests, issues, readmes, releases)
* Changelogs
* GraphQL specifications
* OpenAPI specifications
## Enterprise Sources
We support ingestion of historical support tickets, internal documents, and others sources that contains knowledge about your product. We'll work with your team to ingest any source in any format and your security team to ensure compliance with your data processing policies.
#### Help center and support tickets
* Intercom
* Zendesk
* Help Scout
* Freshdesk
#### Internal knowledge
* Notion
* Google Drive
* Confluence
* Files (.docx, .md, .csv, .pdf, etc.)
* Jira
***
title: Updating content
description: How content is kept up to date for any source
icon: rotate
keywords: content updates, content management, update process, content refresh, data synchronization, content maintenance, update automation, content workflow, update scheduling, content versioning
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Automatic re-indexing
We automatically re-index all content **every 24 hours**. We calculate differences in content and update all downstream dependencies as needed.
## Update from the dashboard
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to **Projects** on the left sidebar
3. Click on the project you want to sync a source for
4. Click on **Sources** on the left sidebar
5. Click on the source you want to sync
6. Click on **Sync** in the top right
7. You can view the status of the current sync under **Sync status** in the top left.
## Update with a webhook call
To update content on-demand, you can make an API call to Inkeep's management service that will trigger a source synchronization job. This is useful for content that has a CI/CD pipeline or for CMS systems that offer webhooks when content changes. [Contact us](mailto:sources@inkeep.com?subject=Access%20to%20webhook%20for%20content%20updates) for a management API key and guidance on how to set this up.
## Update with a GitHub Action
You can set up a GitHub Action workflow to automatically trigger Inkeep to re-crawl a source that corresponds to a (public or private) GitHub repo. This way of triggering indexing is possible for publicly available web content managed via Git, like documentation or marketing sites.
1. Get an Inkeep Management API key by contacting [help@inkeep.com](mailto:help@inkeep.com).
2. Under your repository settings, navigate to **Secrets and variables** -> **Actions**. Click on **New repository secret** and add your Inkeep API key with the name `INKEEP_API_KEY`.
{" "}
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com) 2. Navigate to
**Sources** 3. Selecting the source and copy the `ID`.
1. In your GitHub repository, navigate to the **Actions** tab and click on **New workflow**.
2. Choose the **Set up a workflow yourself** option.
3. Insert the below into the workflow file:
```yml title="files"
name: Sync Inkeep Source
on:
push:
branches:
- main
jobs:
syncSourceJob:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Sync Source
uses: inkeep/pr-commenter-action@v10
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
with:
apiKey: ${{secrets.INKEEP_API_KEY}}
sourceId: "{SOURCE_ID}"
```
```yml title="Folder"
name: Inkeep Source Sync
on:
push:
branches:
- main
paths:
- "docs/**"
jobs:
syncSourceJob:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check for changes
uses: dorny/paths-filter@v2
id: changes
with:
filters: |
docs:
- 'docs/**'
- name: Sync Source
if: steps.changes.outputs.docs == 'true'
uses: inkeep/pr-commenter-action@v10
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
with:
apiKey: ${{secrets.INKEEP_API_KEY}}
sourceId: "{SOURCE_ID}"
```
4. Replace `{SOURCE_ID}` with the ID of your Inkeep source.
5. Commit the workflow file to your repository.
### How it Works
* The workflow is triggered whenever changes are pushed to the `main` branch and there are changes in the matching paths. Note that this only happens when a PR is merged or push is made to the target branch.
* If the push to `main` is associated with a pull request, a comment will be added to the PR confirming that an ingestion job was triggered:
:mag\_right: :speech\_balloon: [Inkeep](https://inkeep.com) AI search and chat service is syncing content for source '\{Source-Name}'
* The new content will be ingested within **1 hour**.
### Permissions
| Permission | Reason |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `contents: read` | Allows the workflow to read the content of the repository, which is needed to detect changes in the content. |
| `pull-requests: write` | Allows the workflow to write a comment on the PR when the workflow succeeds. Note that this only happens once the PR is merged to the target branch. |
## Update source settings
1. Go to the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to **Projects** on the left sidebar
3. Click on the project you want to update a source for
4. Click on **Sources** on the left sidebar
5. Click on the source you want to update
6. Click on **Edit** in the top right
7. Update the source settings
8. Click on **Save**
For updating specific source types, see the relevant guide:
* [API Spec](/sources/management/openapi-spec)
* [Confluence](/sources/management/confluence)
* [Discord](/sources/management/discord)
* [Discourse](/sources/management/discourse)
* [Freshdesk Tickets](/sources/management/freshdesk-tickets)
* [General Web](/sources/management/general-web)
* [GitHub](/sources/management/github)
* [Google Drive](/sources/management/google-drive)
* [Help Scout Docs](/sources/management/helpscout-docs)
* [Help Scout Tickets](/sources/management/helpscout-tickets)
* [Jira](/sources/management/jira)
* [Missive](/sources/management/missive)
* [Notion](/sources/management/notion)
* [Plain](/sources/management/plain)
* [Slack](/sources/management/slack)
* [YouTube](/sources/management/youtube)
* [Zendesk Knowledge Base](/sources/management/zendesk-knowledge-base)
* [Zendesk Tickets](/sources/management/zendesk-tickets)
***
title: OpenAPI Spec
description: Learn how to manage OpenAPI spec sources in Inkeep
icon: SiOpenapiinitiative
keywords: API, OpenAPI, spec, specification, documentation, endpoints, REST API
-------------------------------------------------------------------------------
## Overview
An OpenAPI spec source allows Inkeep to ingest an OpenAPI specification file.
## Configuration Parameters
### URL
Specifies the location where your OpenAPI specification is hosted.
**Requirements:**
* The URL must be publicly accessible (no authentication required)
* The specification must be valid OpenAPI/Swagger format
### Citation URL
Specifies the location of your API documentation pages that correspond to the OpenAPI specification. When using the openapi spec in its answers, Inkeep will use this link as a citation.
***
title: Confluence
description: Learn how to manage Confluence sources in Inkeep
icon: confluence
keywords: Confluence, wiki, documentation, knowledge base, articles, collaboration
----------------------------------------------------------------------------------
## Overview
A Confluence source allows Inkeep to ingest articles from your Confluence instance.
## Setup Requirements
### OAuth Authorization
When you create a Confluence source, you will be redirected to an OAuth flow. Please ensure that you have admin access to the Confluence instance.
**Authorization Process:**
1. Open the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the project you want to add the source to
3. Click on **Add new source**
4. Select **Confluence**
5. Click on **Connect**
6. An Atlassian web popup (OAuth redirect) will open
7. Sign in to your Atlassian account if prompted
8. Review the permissions requested by Inkeep
9. Authorize access to your Confluence instance
10. Complete the OAuth flow and return to Inkeep
## Authorization
You can configure read-access for Inkeep based on:
* spaces
* tags
## User vs Service Accounts
By default, the Atlassian OAuth connection happens at the user level (so the read permissions are tied to what the user has access to and what is selected during the OAuth redirect). A pattern that some customers use is to create a user account that represents the connecting service, e.g. a user named "Inkeep Connector". This allows use of Atlassian's permissioning and RBAC system, and doesn't tie the connection to the status of a single employee.
For additional details, contact [sources@inkeep.com](mailto:sources@inkeep.com) or reach out to us on Slack.
***
title: Discord
description: Learn how to manage Discord sources in Inkeep
icon: discord
keywords: Discord, sources, channels, forum, messaging, community, server
-------------------------------------------------------------------------
## Overview
A Discord source allows Inkeep to ingest content from your Discord server channels.
The Inkeep Source Connector app must be installed in your Discord server before channels can be ingested.
## Setup Requirements
### Installing the Inkeep Source Connector App
Before configuring your Discord source, you must install the "Inkeep Source Connector" app in your Discord server.
The app requires permissions to read message history and access channels in your server.
**Installation Steps:**
1. Navigate to your Discord source configuration page in Inkeep
2. Click the **Add Inkeep Source Connector** button
3. You will be redirected to Discord to authorize the app
## Configuration Fields
If you are using the Discord desktop app, enable **Developer Mode** under **User Settings** -> **Advanced** -> **Developer Mode**.
### Server ID
**Server ID** specifies the Discord server containing the channels from which to ingest content.
**Finding Your Server ID:**
**Desktop/Web App:**
1. Right-click on your server name in the server list
2. Click **Copy Server ID** (you may need to enable Developer Mode in Discord settings first)
### Channel IDs
**Channel IDs** control which channels from your Discord server get ingested. This field accepts a list of Discord channel IDs.
**Supported Channel Types:**
* **Message Channels**: Regular text channels with conversations
* **Forum Channels**: Forum-style channels with threaded discussions
**Finding Channel IDs:**
**Desktop/Web App:**
1. Right-click on the channel name
2. Click **Copy Channel ID** (Developer Mode must be enabled)
***
title: Discourse
description: Learn how to manage Discourse sources in Inkeep
icon: discourse
keywords: Discourse, forum, community, discussions, topics, posts
-----------------------------------------------------------------
## Overview
A Discourse source allows Inkeep to crawl and ingest content from a Discourse forum.
## Configuration Parameters
### URL
Specifies the URL of your Discourse forum that you want to crawl and ingest content from.
**Requirements:**
* The forum must be publicly accessible
* The URL should point to the root of your Discourse instance
### Filtering
If would like certain posts or tags to be excluded from the source please contact the Inkeep team through Slack or email at [sources@inkeep.com](mailto:sources@inkeep.com).
***
title: Freshdesk Tickets
description: Learn how to manage Freshdesk tickets sources in Inkeep
icon: custom/FreshdeskIcon
keywords: Freshdesk, tickets, support, customer service, help desk, API key
---------------------------------------------------------------------------
## Overview
A Freshdesk tickets source allows Inkeep to ingest support tickets from your Freshdesk instance.
## Setup Requirements
### Freshdesk Subdomain
To connect your Freshdesk instance, you need to provide your Freshdesk subdomain. This is found in your Freshdesk URL:
**URL Format:** `https://{subdomain}.freshdesk.com`
### API Key
To create the Freshdesk tickets source, you will need an API key from your Freshdesk instance.
**Getting Your API Key:**
Follow the [official Freshdesk documentation](https://support.freshdesk.com/support/solutions/articles/215517) to obtain your Freshdesk API key.
**API Key Configuration:**
1. Follow the Freshdesk documentation to access your API key
2. Copy the API key from your Freshdesk account
3. Enter both the subdomain and API key when creating your Inkeep source
***
title: Web Sources
description: Learn how to manage web sources in Inkeep
icon: PiGlobeDuotone
keywords: GeneralWeb, web, sources, documentation, landing pages, websites
--------------------------------------------------------------------------
## Overview
A general web source allows Inkeep to crawl and ingest content from websites. This source type is ideal for documentation sites, marketing pages, blogs, and other web-based content.
The following instructions also apply for **Docusaurus**, **Readme**, **Redocly**, **Gitbook** and **Zendesk Help Center** sources.
When you configure a general web source, Inkeep's crawler will systematically discover and index content from your website.
Websites with complex javascript or dynamic content may not be fully indexed.
## Crawler Configuration Fields
All crawler fields below must be of the same domain as the **URL** field.
### URL
The **URL** field specifies the root URL of the website being crawled. This serves as the primary domain and starting point for content discovery.
**Example:** `https://docs.yourcompany.com`
### Ingestion URLs
**Ingestion URLs** is a list of specific URLs that you want Inkeep to scrape. Use this when you want to target specific pages.
**Example:**
* `https://docs.yourcompany.com/getting-started`
* `https://docs.yourcompany.com/api-reference`
* `https://docs.yourcompany.com/tutorials`
### Crawler Sitemap URLs
**Crawler Sitemap URLs** allows you to specify XML sitemaps that contain URLs to scrape. Sitemaps provide an efficient way to tell Inkeep exactly which pages to index.
**Benefits:**
* Faster discovery of content
* More comprehensive coverage
* Better control over what gets indexed
**Example:**
* `https://docs.yourcompany.com/sitemap.xml`
* `https://blog.yourcompany.com/sitemap.xml`
Sitemaps can often be found in the robots.txt file e.g. `https://docs.yourcompany.com/robots.txt`.
### Crawler Start URLs
**Crawler Start URLs** defines the URLs where the crawler should begin if there is no sitemap available. The crawler will start from these URLs and follow links to discover additional content. Crawls are restricted to subpaths of the input start URLs.
**Example:**
* `https://docs.yourcompany.com/`
* `https://docs.yourcompany.com/guides/`
## Filtering
### URL Matching Patterns
**URL Exclude Patterns** allow you to specify strings or patterns to exclude certain URLs from being scraped. This helps you avoid indexing irrelevant or sensitive content.
**URL Include Patterns** allow you to specify patterns to only include certain URLs in the scrape. This is useful when you want to be very selective about what content gets indexed.
**Pattern Types:**
* **Exact Match**: Excludes URLs that exactly match the specified string
* **Regex**: Searches for the pattern in the URL path.
**Examples:**
* **Exact Match:** `https://docs.yourcompany.com/docs/page-to-include`
* **Regex:** `docs\.yourcompany\.com/docs`
### Title Matching Patterns
**Title Exclude Patterns** allow you to exclude pages based on their titles.
**Title Include Patterns** allow you to only include pages with specific titles in the scrape.
**Pattern Types:**
* **Exact Match**: Excludes pages with titles that exactly match the specified string
* **Regex**: Searches for the pattern in the title of the page.
**Examples:**
* **Exact Match:** `404 Not Found`
* **Regex:** `^[Pp]rivacy [Pp]olicy.*`
## Best Practices
* **Start with sitemaps** when available for comprehensive coverage. Crawls without sitemaps are not gauranteed to find all content.
* **Use URL patterns** to focus on relevant content areas, particularly if you have a large number of pages to crawl.
* **Exclude unnecessary content** like user accounts, admin panels, and downloads.
* **Test patterns** on a small set of urls to ensure they are working as expected.
***
title: GitHub
description: Learn how to manage GitHub sources in Inkeep
icon: github
keywords: GitHub, sources, documentation, landing pages, websites
-----------------------------------------------------------------
## Overview
A GitHub source allows Inkeep to ingest content from a GitHub repository.
The types of content that can be ingested from a GitHub repository are:
* Issues
* Discussions
* Releases
* Source Code
## Configuration Fields
To remove or add content types: toggle the corresponding checkbox -> click **update** -> click **sync**.
### Include Issues
**Include Issues** allows you to specify if you want to include issues in the source. Issues will be ingested going back one year.
### Include Discussions
**Include Discussions** allows you to specify if you want to include discussions in the source. Discussions will be ingested going back one year.
### Include LatestReleases
**Include Latest Releases** allows you to specify if you want to include the latest release notes in the source.
### Include Source Code
**Include Source Code** allows you to specify if you want to include the source code in the source.
### Source Code Filtering
If you are including source code, you can filter the files that are ingested under **advanced settings**.
**Include Patterns** allows you to specify patterns to only include certain files in the source.
**Exclude Patterns** allows you to specify patterns to exclude certain files from the source.
**Pattern Types:**
* **Exact Match**: Excludes file urls that exactly match the specified string
* **Regex**: Searches for the pattern in the file url.
**Examples:**
* To exclude all json files you might use a regex pattern like `.*\.json$`.
* To only include files from the examples folder you might use a regex pattern like `examples/.*`.
***
title: Google Drive
description: Learn how to manage Google Drive sources in Inkeep
icon: google-drive
keywords: Google Drive, files, documents, cloud storage, file picker, integration
---------------------------------------------------------------------------------
## Overview
A Google Drive source allows Inkeep to ingest specific files from your Google Drive for indexing and search.
## Setup Requirements
### OAuth Authorization
When you create a Google Drive source, you will be redirected to an OAuth flow to connect the integration to your Google Drive.
**Authorization Process:**
1. Create a new Google Drive source in your Inkeep dashboard
2. You will be redirected to Google's OAuth authorization page
3. Sign in to your Google account if prompted
4. Review the permissions requested by Inkeep
5. Authorize access to your Google Drive
6. Complete the OAuth flow and return to Inkeep
The integration requires permission to read files that you explicitly select from your Google Drive.
## File Selection
### Using the File Picker
Once your Google Drive source is created, you must use the file picker to select which files you want ingested.
**File Selection Process:**
1. In your configured Google Drive source, click **"Add files via Google Drive picker"**
2. Browse through your Google Drive files
3. Select the files you want to include in your knowledge base
4. Deselect any files you no longer want ingested
5. Confirm your selections
**Managing File Selection:**
* **Add new files** by using the file picker to select additional content
* **Remove files** by deselecting them in the file picker
* **Update selections** anytime your content changes
The Google Drive picker will only work with the account that you signed in with upon initial setup. Create a new source to use a different account.
### Large Folder Management
If you have a large folder with many files that doesn't change frequently, you can use a more efficient approach:
**Zip File Method:**
1. Compress your folder into a ZIP file
2. Upload the ZIP file to your Google Drive
3. Select the ZIP file using the file picker
4. Inkeep will extract and index the contents of the ZIP file
## Supported File Types
Inkeep can process the following file types from your Google Drive:
**Document Formats:**
* **PDF** - Portable Document Format files
* **DOCX** - Microsoft Word documents
* **TXT** - Plain text files
* **HTML** - Web page files
**Presentation Formats:**
* **PPTX** - Microsoft PowerPoint presentations
**Data Formats:**
* **XLSX** - Microsoft Excel spreadsheets
* **CSV** - Comma-separated values files
**Media Formats:**
* **MP3** - Audio files (transcripts will be generated)
* **MP4** - Video files (transcripts will be generated)
**Image Formats:**
* **PNG** - Image files (only if they contain text that can be extracted)
***
title: HelpScout Docs
description: Learn how to manage HelpScout docs sources in Inkeep
icon: SiHelpscout
keywords: HelpScout, docs, documentation, help center, knowledge base, collections
----------------------------------------------------------------------------------
## Overview
A HelpScout docs source allows Inkeep to ingest content from your HelpScout docs collections.
## Setup Requirements
### API Key
When creating a HelpScout docs source, you will need an API key to authenticate Inkeep's access to your HelpScout docs.
**Getting Your API Key:**
For detailed instructions on obtaining your HelpScout docs API key, please refer to the official [HelpScout documentation](https://developer.helpscout.com/docs-api/).
## Configuration Parameters
### Collection IDs
**Collection IDs** specify which HelpScout docs collections you want Inkeep to ingest. You can specify one or multiple collection IDs to control which documentation gets indexed.
**Finding Collection IDs:**
1. Navigate to your HelpScout docs
2. Open the collection you want to include
3. Look at the URL in your browser: `https://secure.helpscout.net/docs/{collectionId}`
4. Copy the collection ID from the URL
**Behavior:**
* **With Collection IDs specified**: Only articles from the specified collections will be ingested
* **No Collection IDs**: All collections will be included in the ingestion
***
title: HelpScout Tickets
description: Learn how to manage HelpScout tickets sources in Inkeep
icon: SiHelpscout
keywords: HelpScout, tickets, conversations, support, customer service, help desk
---------------------------------------------------------------------------------
## Overview
A HelpScout tickets source allows Inkeep to ingest support tickets from your HelpScout instance.
## Setup Requirements
### OAuth Authorization
When you create a HelpScout tickets source, you will be redirected to an OAuth flow where you can authorize the integration.
**Authorization Requirements:**
Please ensure you are an admin with read permissions on all tickets before proceeding with the OAuth flow.
**Authorization Process:**
1. Create a new HelpScout tickets source in your Inkeep dashboard
2. You will be redirected to HelpScout's OAuth authorization page
3. Sign in to your HelpScout account if prompted
4. Review the permissions requested by Inkeep
5. Authorize access to your HelpScout tickets
6. Complete the OAuth flow and return to Inkeep
***
title: Jira
description: Learn how to manage Jira sources in Inkeep
icon: jira
keywords: Jira, tickets, issues, project management, bug tracking, agile
------------------------------------------------------------------------
## Overview
A Jira source allows Inkeep to ingest tickets from your Jira instance.
## Setup Requirements
### OAuth Authorization
When you create a Jira source, you will be redirected to an OAuth flow. Please ensure that you have admin access to the Jira instance.
**Authorization Process:**
1. Create a new Jira source in your Inkeep dashboard
2. You will be redirected to Atlassian's authorization page
3. Sign in to your Atlassian account if prompted
4. Review the permissions requested by Inkeep
5. Authorize access to your Jira instance
6. Complete the OAuth flow and return to Inkeep
## Filtering
If would like certain ticket labels, projects, or statuses to be excluded from the source please contact the Inkeep team through Slack or email at [sources@inkeep.com](mailto:sources@inkeep.com).
***
title: Missive
description: Learn how to manage Missive sources in Inkeep
icon: custom/MissiveIcon
keywords: Missive, tickets, team collaboration, email management, API key, support
----------------------------------------------------------------------------------
## Overview
A Missive source allows Inkeep to ingest tickets from your Missive instance.
## Setup Requirements
### API Key
To create a Missive source, you will need an API key from your Missive account.
**Getting Your API Key:**
1. Go to your Missive preferences
2. Click the **API** tab
3. Click the **Create a new token** link
4. Copy the generated API token
5. Enter the API key when creating your Inkeep source
**Plan Requirement:**
You need to be part of an organization subscribed to the **Productive plan** in order to generate API tokens.
## Filtering
If would like certain ticket tags or statuses to be excluded from the source please contact the Inkeep team through Slack or email at [sources@inkeep.com](mailto:sources@inkeep.com).
***
title: Notion
description: Learn how to manage Notion sources in Inkeep
icon: SiNotion
keywords: Notion, sources, databases, pages, workspace, knowledge base, documentation
-------------------------------------------------------------------------------------
## Overview
A Notion source allows Inkeep to ingest content from your Notion workspace.
Initial ingestion can take time due to API rate limiting.
## Setup Requirements
### Authorizing the Inkeep Integration
When you first create a Notion source, you will be automatically redirected to authorize the Inkeep integration with your Notion workspace.
**Authorization Steps:**
1. Create a new Notion source in your Inkeep dashboard
2. You will be redirected to Notion's authorization page
3. Sign in to your Notion account if prompted
4. Review the permissions requested by Inkeep Source Connector
5. Select which databases and pages you want to share with the integration
## Managing Shared Content
### Updating Shared Content
If you want to modify what content is shared with the Inkeep integration after the initial setup:
**Steps to Update Access:**
1. Open your Notion workspace
2. Go to **Settings** (click your workspace name in the sidebar)
3. Navigate to **Connections**
4. Find **Inkeep Source Connector** hover over the **...** and click **Access selected pages**
5. Select the databases and pages you want to share with Inkeep
6. Click **Update Access**
Changes to shared content will be reflected in your Inkeep source during the next synchronization.
***
title: Plain
description: Learn how to manage Plain sources in Inkeep
icon: custom/PlainIcon
keywords: Plain, tickets, customer support, help desk, API key, support conversations
-------------------------------------------------------------------------------------
## Overview
A Plain source allows Inkeep to ingest tickets from your Plain instance.
## Setup Requirements
### Plain API Key
In order to create a Plain source, you will need a Plain API key with specific permissions.
**Creating Your API Key:**
1. Follow [this guide ](https://www.plain.com/docs/api-reference/graphql/authentication) to create an API key
2. Copy this permissions string:
```
roles:read,company:read,customer:read,machineUser:read,thread:read,threadDiscussion:read,threadDiscussionMessage:read,threadField:read,threadFieldSchema:read,tier:read,timeline:read,user:read,email:read,note:read
```
3. Click the **From clipboard** button to paste the permissions
4. Paste the new API key in the **Plain API Field** in Inkeep
5. Click **Create** to complete the source setup
***
title: Slack
description: Learn how to manage Slack sources in Inkeep
icon: slack
keywords: Slack, sources, channels, messaging, team communication, knowledge base
---------------------------------------------------------------------------------
## Overview
A Slack source allows Inkeep to ingest content from your Slack workspace channels.
Initial ingestion can take a while due to API rate limits.
## Setup Requirements
### Adding the Knowledge Base Connector Bot
To enable your Slack source, you must add the "Knowledge Base Connector" bot to your Slack workspace and the channels you want to ingest.
**Step 1: Add the bot to your workspace**
When first creating a Slack source, you will be redirected to authorize the bot to access your workspace. If this did not work for you, you can manually add the bot to your workspace [here](https://slack-ingester.inkeep.com/).
**Step 2: Add the bot to specific channels**
1. Go to the channel you want to ingest
2. Click the **members button** on the top right
3. Go to the **Integrations** tab
4. Click **Add an app**
5. Search for **Knowledge Base Connector**
6. Add the bot to the channel
Repeat this process for each channel you want to include in your knowledge base.
## Configuration Fields
### Channel IDs
**Channel IDs** control which channels from your Slack workspace get ingested. This field accepts a list of Slack channel IDs.
**Behavior:**
* **With Channel IDs specified**: Only the listed channels will be ingested
* **No Channel IDs specified**: All channels where the Knowledge Base Connector bot has been added will be ingested
**Finding Channel IDs:**
**Browser:**
1. Open the Slack channel in your browser
2. The channel ID is in the URL: `https://yourworkspace.slack.com/channels/C1234567890`
3. Copy the ID (e.g., `C1234567890`)
**Slack App:**
1. Go to the channel in your Slack workspace
2. Click the channel name in the top left
3. Copy the channel ID from the bottom of the popup window
***
title: YouTube
description: Learn how to manage YouTube sources in Inkeep
icon: youtube
keywords: YouTube, sources, videos, shorts, channel content, video ingestion
----------------------------------------------------------------------------
## Overview
A YouTube source allows Inkeep to ingest content from YouTube channels.
When you configure a YouTube source, Inkeep will systematically discover and index content from the specified YouTube channel.
Only publicly available YouTube content can be ingested. Private or unlisted videos will not be accessible. This is a limitation of the YouTube API.
## Configuration Fields
### URL
The **URL** field determines which type of content will be ingested from the YouTube channel. The URL format controls whether videos, shorts, or both are included:
**URL Formats:**
* `https://www.youtube.com/@{channel}/videos` - **Videos only**: Ingests only regular videos from the channel
* `https://www.youtube.com/@{channel}/shorts` - **Shorts only**: Ingests only YouTube Shorts from the channel
* `https://www.youtube.com/@{channel}` - **All content**: Ingests both videos and shorts from the channel
### Cut Off Date
**Cut Off Date** specifies the earliest video publication date to include in the ingestion. Videos published before this date will be excluded from the source.
**Example:** Setting the cut off date to `2023-01-01` will only ingest videos published on or after January 1, 2023.
### Max Video Duration
**Max Video Duration** sets the maximum length (in minutes) for videos to be ingested. Videos longer than this duration will be excluded from the source.
**Example:** Setting max duration to `30` will only ingest videos that are 30 minutes or shorter.
## Filtering
### URL Matching Patterns
**URL Include Patterns** allow you to specify patterns to only include certain videos based on their URLs.
**URL Exclude Patterns** allow you to specify patterns to exclude certain videos based on their URLs.
**Pattern Types:**
* **Exact Match**: Includes videos with URLs that exactly match the specified string
* **Regex**: Searches for the pattern in the video URL
### Title Matching Patterns
**Title Include Patterns** allow you to specify patterns to only include videos with specific titles.
**Title Exclude Patterns** allow you to exclude videos based on their titles.
**Pattern Types:**
* **Exact Match**: Matches videos with titles that exactly match the specified string
* **Regex**: Searches for the pattern in the video title
***
title: Zendesk Knowledge Base
description: Learn how to manage Zendesk knowledge base sources in Inkeep
icon: SiZendesk
keywords: Zendesk, knowledge base, articles, help center, documentation, support content
----------------------------------------------------------------------------------------
## Overview
A Zendesk Knowledge Base source allows Inkeep to ingest articles from your Zendesk directly through the Zendesk API.
## Setup Requirements
### Zendesk Subdomain
To connect your Zendesk you need to provide your Zendesk subdomain. This is found in your Zendesk URL:
**URL Format:** `https://{subdomain}.zendesk.com`
### OAuth Authorization
The authorization process for Zendesk Knowledge Base sources is the same as for [Zendesk Tickets Sources](/docs/sources/management/zendesk_tickets#oauth-authorization). When you create a Zendesk Knowledge Base source, you will be redirected to authorize Inkeep's access to your Zendesk instance.
The integration requires permission to read articles and associated metadata from your Zendesk instance.
## Configuration Parameters
### Ingestion URLs
**Ingestion URLs** allows you to specify specific article URLs that you want Inkeep to ingest from your Zendesk Help Center.
**Behavior:**
* **With URLs specified**: Only the articles at the specified URLs will be ingested
* **No URLs specified**: All available articles in your Help Center will be ingested
**Finding Article URLs:**
1. Navigate to your Zendesk Help Center
2. Open the article you want to include
3. Copy the full URL from your browser's address bar
4. Paste the URL into the Ingestion URLs field
***
title: Zendesk Tickets
description: Learn how to manage Zendesk tickets sources in Inkeep
icon: SiZendesk
keywords: Zendesk, tickets, support, customer service, help desk, knowledge base
--------------------------------------------------------------------------------
## Overview
A Zendesk tickets source allows Inkeep to ingest support tickets from your Zendesk instance.
Inkeep limits its Zendesk API usage to 75% of **your API rate limit**. Initial data ingestion time may vary based on your data volume and API limits.
## Setup Requirements
### Zendesk Subdomain
To connect your Zendesk instance, you need to provide your Zendesk subdomain. This is found in your Zendesk URL:
**URL Format:** `https://{subdomain}.zendesk.com`
### OAuth Authorization
When you create a Zendesk tickets source, you will be redirected to authorize Inkeep's access to your Zendesk instance.
The integration requires permission to read tickets, comments, and associated metadata from your Zendesk instance.
## Filtering
If would like certain ticket tags or statuses to be excluded from the source please contact the Inkeep team through Slack or email at [sources@inkeep.com](mailto:sources@inkeep.com).
***
title: Zendesk Help Center
description: Learn how to manage Zendesk Help Center sources in Inkeep
icon: SiZendesk
keywords: Zendesk, help center, crawling, public site, support documentation, web crawler
-----------------------------------------------------------------------------------------
## Overview
A Zendesk Help Center source allows Inkeep to crawl and ingest content from your public-facing Zendesk help center. This source type differs from the Zendesk Knowledge Base source in that it does not use the Zendesk API, but rather crawls your publicly accessible help center site.
This approach is ideal when you want to index your help center content without API access or when working with public help centers that don't require authentication.
## Configuration Parameters
### URL
Specifies the root URL of your public-facing help center that you want Inkeep to crawl.
**Example:** `https://support.yourcompany.com`
## Filtering
### URL Matching Patterns
**URL Exclude Patterns** allow you to specify strings or patterns to exclude certain URLs from being scraped. This helps you avoid indexing irrelevant or sensitive content.
**URL Include Patterns** allow you to specify patterns to only include certain URLs in the scrape. This is useful when you want to be very selective about what content gets indexed.
**Pattern Types:**
* **Exact Match**: Excludes URLs that exactly match the specified string
* **Regex**: Searches for the pattern in the URL path.
**Examples:**
* **Exact Match:** `support.yourcompany.com/hc/en-us/articles/`
* **Regex:** `support\.yourcompany\.com/hc/en-us/.*`
### Title Matching Patterns
**Title Exclude Patterns** allow you to exclude pages based on their titles.
**Title Include Patterns** allow you to only include pages with specific titles in the scrape.
**Pattern Types:**
* **Exact Match**: Excludes pages with titles that exactly match the specified string
* **Regex**: Searches for the pattern in the title of the page.
**Examples:**
* **Exact Match:** `Getting Started Guide`
* **Regex:** `^(How to|Tutorial|Guide).*`
***
title: UI Kit Components
sidebarTitle: Overview
keywords: UI components, React components, JavaScript snippets, component library, UI customization, theme customization, user authentication, analytics integration, support form, chat sharing, user privacy, custom instructions, UI integration, component embedding, UI toolkit
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Use the `@inkeep/cxkit-react` UI library to embed an AI assistant as a React component or JavaScript snippet anywhere your users have questions.
## Components
Using the `@inkeep/cxkit-js` library.
Add a floating `Ask AI` chat button to any site or app.
Add to your docs or marketing site.
Use your own button or UI element to trigger the assistant UI.
Integrate an intelligent form to deflect new tickets.
Embed the chat directly in a dedicated standalone page.
Embed a search UI directly on a dedicated page.
Embed the chat in a sidebar on the left or right side of the page.
Using the `@inkeep/cxkit-react` library.
Add a floating `Ask AI` chat button to any site or app.
Add to your docs or marketing site.
Use your own button or UI element to trigger the assistant UI.
Integrate an intelligent form to deflect new tickets.
Embed the chat directly in a dedicated standalone page.
Embed a search UI directly on a dedicated page.
Embed the chat in a sidebar on the left or right side of the page.
## Customization
Here are some common scenarios:
* **[Customize theme & CSS](/ui-components/customization-guides/style-components)** - Customize the look and feel of the UI components.
* **[Add guidance & context](/ui-components/customization-guides/custom-instructions)** - Provide user-specific information or provide custom instructions to the LLM.
* **[Manage user privacy preferences](/ui-components/customization-guides/use-your-own-analytics#configuration-options)** - Handle user privacy settings and analytics opt-outs.
* **[Authenticate users](/ui-components/customization-guides/authenticate-users)** - Limit chat or search usage to users authenticated with your app.
* **[Log events to your own analytics](/ui-components/customization-guides/use-your-own-analytics)** - Log events to your own custom analytics system.
* **[Embed a support form](/ui-components/common-settings/actions#open-form-action)** - Add a support form embedded within the chat experience to create support tickets.
* **[Make chats sharable](/ui-components/customization-guides/sharable-chats)** - Enable the 'Share' button to make chats sharable.
## Public clients
For an overview of local development and security for AI assistant's that are used on public sites, check out [this](/ui-components//public-api-keys) guide.
***
title: Chat Button (JS)
sidebarTitle: Chat Button
description: Add the Inkeep chat button using a JS snippet.
keywords: JavaScript chat button, chat component, UI components, JavaScript integration, chat functionality, component configuration, chat settings, modal trigger, component methods, JavaScript implementation, chat implementation, UI customization, button styling, component setup, chat interface
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
The chat button is a great way to add an AI copilot to your landing page, documentation, or app without changing your current search experience.
## Quick start
Add the below `
```
Insert the Chat Button by using the `Inkeep.ChatButton()` function.
```javascript
const config = {
baseSettings: {
apiKey: "YOUR_API_KEY",
organizationDisplayName: "Your Company",
primaryBrandColor: "#4F46E5",
},
aiChatSettings: {
aiAssistantName: "Keepie",
},
label: "Ask AI",
};
const chatButton = Inkeep.ChatButton("#chat-button", config);
```
## Chat Button Props
Chat button props control the behavior and interaction of the chat button.
| Prop | Type | Required | Description |
| ---------------- | ------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `aiChatSettings` | `object` | No | AI chat configuration settings. See [AI Chat Settings](/ui-components/common-settings/ai-chat) for details. |
| `modalSettings` | `object` | No | Modal configuration settings. See [Modal Settings](/ui-components/js-snippet/custom-modal-trigger#modal-settings) for details. |
| `label` | `string` | No | Custom label for the chat button. |
| `canToggleView` | `boolean` | No | Whether to allow toggling between chat and search views. Defaults to true. |
| `defaultView` | `'search' \| 'chat'` | No | The default view to show when opened. Defaults to 'chat'. |
| `avatar` | `string \| { light: string, dark: string }` | No | URL for ai button's avatar (40x40px recommended) |
| `askAICardLabel` | `string` | No | The label for the Ask AI card in search results. Defaults to `Ask AI` or `askAILabel` if provided. |
| `askAILabel` | `string` | No | The label for the Ask AI button in the search/chat toggle. Defaults to `Ask AI`. |
| `searchLabel` | `string` | No | The label for the search button in the search/chat toggle. Defaults to `Search`. |
## Examples
### Set the default view
```javascript
const config = {
// ... other config
defaultView: "chat", // or "search"
};
const widget = Inkeep.ChatButton(config);
```
### Force the default view
If you want to force the default view to be the search or the chat, you can use the `forceDefaultView` property. This is useful to ensure the widget always opens the defaultView instead of last used view.
```javascript
const config = {
// ... other config
forceDefaultView: true,
};
const widget = Inkeep.ChatButton(config);
```
Refer to the [Search Settings](/ui-components/common-settings/search) and [Chat Settings](/ui-components/common-settings/chat) docs for more details on the available properties.
## Changing props after initial render
Sometimes you may need to manage change settings after a widget has already been initialized, for example, to update user privacy preferences. To do this, you can use the `update` method.
The below example illustrates how you change the primary color on the widget when a button is clicked.
```typescript
const colors = [
"#26D6FF",
"#e300bd",
"#512fc9",
"#fde046",
"#2ecc71",
"#e74c3c",
"#9b59b6",
"#f1c40f",
];
let count = 0;
const changeColorButton = document.getElementById("change-color-button");
changeColorButton.addEventListener("click", () => {
count++;
widget.update({
baseSettings: {
primaryBrandColor: colors[count % colors.length],
},
});
});
```
## Accessing methods
The instance of the widget object returned by `Inkeep.ChatButton()` exposes some methods that you can use to interact with the widget.
```javascript
// Access chat methods
widget.chat.clearChat();
widget.chat.focusInput();
// Access search methods
widget.search.updateQuery("Hello!");
widget.search.focusInput();
// Access widget methods
widget.setView("search");
```
### Chat Methods
| Method | Description |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `submitMessage(message?: string)` | Programmatically sends a message in chat. If message is omitted, sends the current input value. |
| `updateInputMessage(message: string)` | Updates the text in chat input field |
| `clearChat()` | Resets the chat to its initial state |
| `openForm(formSettings: FormSettings)` | Displays a form overlay in chat interface |
| `focusInput()` | Sets focus to the chat input field |
Refer to the [Form Settings](/ui-components/common-settings/actions#formconfig-reference) reference docs for more details on the available properties for the `openForm` method.
### Search methods
| Method | Description |
| ---------------------------- | ------------------------------------------ |
| `updateQuery(query: string)` | Programmatically updates the search query. |
| `focusInput()` | Sets focus to the search input field |
### Widget methods
```typescript
type ModalViewTypes = "search" | "chat";
```
| Method | Description |
| ------------------------------- | --------------------------------------------------- |
| `setView(view: ModalViewTypes)` | Set the view of the widget to either search or chat |
***
title: Search Bar (JS)
sidebarTitle: Search Bar
description: Add the Inkeep search bar using a JS snippet.
keywords: JavaScript search bar, search component, UI components, JavaScript integration, search functionality, component configuration, search settings, chat integration, component methods, JavaScript implementation, search implementation, UI customization, search bar styling, component setup, search interface
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
The search bar is a great way to add an AI powered search bar to your website.
## Quick start
Add the below `
```
Insert the Search Bar by using the `Inkeep.SearchBar()` function.
```javascript
const config = {
baseSettings: {
apiKey: "YOUR_API_KEY",
organizationDisplayName: "Your Company",
primaryBrandColor: "#4F46E5",
},
searchSettings: {
placeholder: "Search documentation...",
},
};
const searchBar = Inkeep.SearchBar("#search-bar", config);
```
## Search Bar Props
Search bar props control the behavior and interaction of the search bar.
| Prop | Type | Required | Description |
| --------------------- | -------------------- | -------- | ----------------------------------------------------------------------------------------------------------- |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `aiChatSettings` | `object` | No | AI chat configuration settings. See [AI Chat Settings](/ui-components/common-settings/ai-chat) for details. |
| `modalSettings` | `object` | No | Modal configuration settings. See [Modal Settings](/ui-components/common-settings/modal) for details. |
| `canToggleView` | `boolean` | No | Whether to allow toggling between chat and search views. Defaults to true. |
| `defaultView` | `'search' \| 'chat'` | No | The default view to show when opened. Defaults to 'search'. |
| `shouldShowAskAICard` | `boolean` | No | Whether to show the Ask AI card. Defaults to true. |
| `askAICardLabel` | `string` | No | The label for the Ask AI card in search results. Defaults to `Ask AI` or `askAILabel` if provided. |
| `askAILabel` | `string` | No | The label for the Ask AI button in the search/chat toggle. Defaults to `Ask AI`. |
| `searchLabel` | `string` | No | The label for the search button in the search/chat toggle. Defaults to `Search`. |
## Examples
### Set the default view
```javascript
const config = {
// ... other config
defaultView: "search", // or "chat"
};
const widget = Inkeep.SearchBar(config);
```
### Force the default view
If you want to force the default view to be the search or the chat, you can use the `forceDefaultView` property. This is useful to ensure the widget always opens the defaultView instead of last used view.
```javascript
const config = {
// ... other config
forceDefaultView: true,
};
const widget = Inkeep.SearchBar(config);
```
Refer to the [Search Settings](/ui-components/common-settings/search) and [Chat Settings](/ui-components/common-settings/chat) docs for more details on the available properties.
## Changing props after initial render
Sometimes you may need to manage change settings after a widget has already been initialized, for example, to update user privacy preferences. To do this, you can use the `update` method.
The below example illustrates how you change the primary color on the widget when a button is clicked.
```typescript
const colors = [
"#26D6FF",
"#e300bd",
"#512fc9",
"#fde046",
"#2ecc71",
"#e74c3c",
"#9b59b6",
"#f1c40f",
];
let count = 0;
const changeColorButton = document.getElementById("change-color-button");
changeColorButton.addEventListener("click", () => {
count++;
widget.update({
baseSettings: {
primaryBrandColor: colors[count % colors.length],
},
});
});
```
## Accessing methods
The instance of the widget object returned by `Inkeep.SearchBar()` exposes some methods that you can use to interact with the widget.
```javascript
// Access search methods
widget.search.updateQuery("Hello!");
widget.search.focusInput();
// Access chat methods
widget.chat.clearChat();
widget.chat.focusInput();
// Access widget methods
widget.setView("search");
```
### Chat Methods
| Method | Description |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `submitMessage(message?: string)` | Programmatically sends a message in chat. If message is omitted, sends the current input value. |
| `updateInputMessage(message: string)` | Updates the text in chat input field |
| `clearChat()` | Resets the chat to its initial state |
| `openForm(formSettings: FormSettings)` | Displays a form overlay in chat interface |
| `focusInput()` | Sets focus to the chat input field |
Refer to the [Form Settings](/ui-components/common-settings/actions#formconfig-reference) reference docs for more details on the available properties for the `openForm` method.
### Search methods
| Method | Description |
| ---------------------------- | ------------------------------------------ |
| `updateQuery(query: string)` | Programmatically updates the search query. |
| `focusInput()` | Sets focus to the search input field |
### Widget methods
```typescript
type ModalViewTypes = "search" | "chat";
```
| Method | Description |
| ------------------------------- | --------------------------------------------------- |
| `setView(view: ModalViewTypes)` | Set the view of the widget to either search or chat |
***
title: Trigger the Inkeep modal with a custom trigger (JS)
sidebarTitle: Custom Trigger
keywords: custom modal trigger, JavaScript modal, modal component, UI customization, modal implementation, custom button, modal trigger, JavaScript events, modal configuration, UI components, modal settings, component integration, modal functionality, custom UI, modal events
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Use the "Custom Trigger" if you want to use a custom button, search bar, link, or any other UI element for opening and closing Inkeep's modal components.
## Overview
The Inkeep modal can contain search, chat, or a combined experience.
The available modal components are:
| Component | Description |
| -------------------------- | ---------------------------------------------------------------- |
| `InkeepModalSearchAndChat` | Combined search and chat experience with a toggle for switching. |
| `InkeepModalSearch` | Search-only experience |
| `InkeepModalChat` | Chat-only experience |
## Modal Settings
Modal settings control the behavior and interaction of modal components. These settings are passed in the `modalSettings` prop.
| Setting | Type | Default | Description |
| ----------------- | --------------------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `isOpen` | `boolean` | `false` | Controls the visibility of the modal. Set to `true` to show the modal, `false` to hide it. |
| `onOpenChange` | `(isOpen: boolean) => void` | - | Callback function triggered when the modal's open state changes. Useful for syncing state with your application. |
| `shortcutKey` | `string \| null` | - | The keyboard key that triggers the modal when pressed with Cmd (Mac) or Ctrl (Windows). Set to `null` to disable the shortcut. |
| `triggerSelector` | `string` | `'[data-inkeep-modal-trigger]'` | The selector for the trigger element that opens the modal. If you add a button with the `data-inkeep-modal-trigger` attribute, you do not need to implement your own `onOpenChange` handler or pass the `isOpen` prop to the `modalSettings`. |
## Basic Usage
### Initialize
Let's use the Modal version of the [Search and Chat](/ui-components/js-snippet/in-page/embedded-search-and-chat) component as an example.
```javascript
const config = {
baseSettings: {
apiKey: "YOUR_API_KEY",
},
modalSettings: {
shortcutKey: "k",
},
aiChatSettings: {
aiAssistantName: "Keepie",
},
searchSettings: {
placeholder: "Search...",
},
};
const modalWidget = Inkeep.ModalSearchAndChat(config);
```
### Update
The instance of an initialized Inkeep widget exposes an `update` method that can be used to update the widget's props/config. Whatever you pass subsequently is deeply merged with the previous props/config.
```javascript
modalWidget.update({ modalSettings: { isOpen: true } });
```
### Toggle Modal Disclosure
An example of a button trigger that opens the modal when clicked:
```javascript
document.querySelector("#open-modal").addEventListener("click", () => {
modalWidget.update({ modalSettings: { isOpen: true } });
});
```
## Modal Types
Basically means the modal extensions of the following components:
* [Search](/ui-components/js-snippet/in-page/embedded-search)
* [Chat](/ui-components/js-snippet/in-page/embedded-chat)
* [Search and Chat](/ui-components/js-snippet/in-page/embedded-search-and-chat)
### Modal Search
A modal version of the embedded search component. For detailed information about search functionality and available settings, see [Embedded Search](/ui-components/js-snippet/in-page/embedded-search).
```js
const config = {
baseSettings: {
apiKey: "YOUR_API_KEY",
},
searchSettings: {
placeholder: "Search...",
},
modalSettings: {
onOpenChange: handleOpenChange,
},
};
// Initialize modal search
const modalSearch = Inkeep.ModalSearch(config);
function handleOpenChange(newOpen) {
modalSearch.update({ modalSettings: { isOpen: newOpen } });
}
// trigger
document.querySelector("#search-button").addEventListener("click", () => {
modalSearch.update({ modalSettings: { isOpen: true } });
});
// Access search methods
modalSearch.updateQuery("new search query");
```
```html
Open Search Modal
```
### Modal Chat
A modal version of the embedded chat component. For detailed information about chat functionality and available settings, see [Embedded Chat](/ui-components/js-snippet/in-page/embedded-chat).
```js
const config = {
baseSettings: {
apiKey: "YOUR_API_KEY",
},
aiChatSettings: {
aiAssistantName: "Keepie",
},
modalSettings: {
onOpenChange: handleOpenChange,
},
};
// Initialize modal chat
const modalChat = Inkeep.ModalChat(config);
function handleOpenChange(newOpen) {
modalChat.update({ modalSettings: { isOpen: newOpen } });
}
// trigger
document.querySelector("#chat-button").addEventListener("click", () => {
modalChat.update({ modalSettings: { isOpen: true } });
});
// Access chat methods
modalChat.clearChat();
```
```html
Open Chat Modal
```
### Modal Search and Chat
A modal version of the embedded search and chat component. For detailed information about search and chat functionality and available settings, see [Embedded Search and Chat](/ui-components/js-snippet/in-page/embedded-search-and-chat).
```js
const config = {
baseSettings: {
apiKey: "YOUR_API_KEY",
},
searchSettings: {
placeholder: "Search...",
},
aiChatSettings: {
aiAssistantName: "Keepie",
},
modalSettings: {
onOpenChange: handleOpenChange,
},
};
// Initialize modal search and chat
const modalSearchAndChat = Inkeep.ModalSearchAndChat(config);
function handleOpenChange(newOpen) {
modalSearchAndChat.update({ modalSettings: { isOpen: newOpen } });
}
// trigger
document
.querySelector("#search-and-chat-button")
.addEventListener("click", () => {
modalSearchAndChat.update({ modalSettings: { isOpen: true } });
});
// Access search methods
modalSearchAndChat.search.updateQuery("new search query");
// Access chat methods
modalSearchAndChat.chat.clearChat();
// Access widget methods
modalSearchAndChat.setView("search");
```
```html
Open Search and Chat Modal
```
## Available Methods
### Chat Methods
| Method | Description |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `submitMessage(message?: string)` | Programmatically sends a message in chat. If message is omitted, sends the current input value. |
| `updateInputMessage(message: string)` | Updates the text in chat input field |
| `clearChat()` | Resets the chat to its initial state |
| `openForm(formSettings: FormSettings)` | Displays a form overlay in chat interface |
| `focusInput()` | Sets focus to the chat input field |
Refer to the [Form Settings](/ui-components/common-settings/actions#formconfig-reference) reference docs for more details on the available properties for the `openForm` method.
### Search methods
| Method | Description |
| ---------------------------- | ------------------------------------------ |
| `updateQuery(query: string)` | Programmatically updates the search query. |
| `focusInput()` | Sets focus to the search input field |
### Widget methods
```typescript
type ModalViewTypes = "search" | "chat";
```
| Method | Description |
| ------------------------------- | --------------------------------------------------- |
| `setView(view: ModalViewTypes)` | Set the view of the widget to either search or chat |
## Widget Updates
Update component props using the `update` method. Each modal component accepts the same configuration options as its embedded counterpart, plus the additional modal-specific settings:
```js
// Modal Search updates
modalSearch.update({
modalSettings: {
isOpen: true,
},
searchSettings: {
placeholder: "Search documentation...",
defaultQuery: "getting started",
},
});
// Modal Chat updates
modalChat.update({
modalSettings: {
isOpen: true,
},
aiChatSettings: {
aiAssistantName: "Assistant",
placeholder: "Ask a question...",
},
});
// Combined Modal updates
modalWidget.update({
defaultView: "search", // or 'chat'
modalSettings: {
isOpen: true,
},
searchSettings: {
placeholder: "Search documentation...",
},
aiChatSettings: {
aiAssistantName: "Assistant",
},
});
```
***
title: Intelligent Form (JS)
sidebarTitle: Intelligent Form
description: Add an intelligent form UI directly on a dedicated page
keywords: intelligent form, JavaScript form, AI-powered form, form automation, form configuration, form fields, form submission, JavaScript snippet, form UI, form validation, form customization, form handling, form integration, form settings, form implementation
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
The Intelligent Form component is designed to help deflect support tickets at creation time in a tasteful way.
If the AI is confident, it'll attempt to deflect the user's question prior to ticket creation.
If it's not confident - it can still be helpful by taking a user's input and prefilling other parts of the form. Useful for simplifying your form while extracting structured information needed by your ticketing platform.
## How It Works
1. **Primary Screen**: Users enter their initial information (name, email, question/details)
2. **AI Deflection**: The AI assistant analyzes the user's input
* If confident it can help: The user is shown an answer. They can continue to the secondary screen if it doesn't resolve their question.
* If not confident: User proceeds directly to the secondary screen
3. **Secondary Screen**: Contains additional fields to collect structured information
* These fields can be automatically pre-filled by AI based on the user's initial input
* User reviews and confirms the information
4. **Submission**: When the user submits the form, your custom callback function is triggered
* Your callback receives all form data and conversation context
* You can connect this to your ticketing system, CRM, or other backend systems
This flow aims to reduce support tickets in an elegant way that also simplifies the end-user experience.
## Quick start
Add the below `
```
Define an element in your page that will be the "container" for the intelligent form.
```html
```
Insert the Intelligent Form by using the `Inkeep.IntelligentForm()` function.
```html
```
## Configuration
| Property | Type | Required | Description |
| -------------- | -------- | -------- | -------------------------------------------------------------------------------------------------- |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `formSettings` | `object` | Yes | Form configuration settings. See below for details. |
## Form Settings
The `formSettings` object configures the behavior, layout, and functionality of the Intelligent Form widget. The form is divided into primary and secondary sections, with additional settings for success messages and submission handling.
### Configuration Structure
```typescript
interface IntelligentFormSettings {
aiAssistantName?: string;
primary: PrimarySection;
secondary: SecondarySection;
successView: IntelligentFormSuccessView;
buttons: IntelligentFormButtons;
}
```
### Assistant Name
An optional name that's displayed in the form header:
```typescript
const formSettings = {
aiAssistantName: "Support Agent",
};
```
### Primary Section
The initial form fields that are always displayed to the user:
```typescript
interface PrimarySection {
fields: IntelligentFormField[];
description?: string;
}
```
| Property | Type | Required | Description |
| ------------- | ------------------------ | -------- | ------------------------------------------------ |
| `fields` | `IntelligentFormField[]` | Yes | Array of form fields to display initially |
| `description` | `string` | No | Optional description text shown above the fields |
#### Example
```javascript
{
primary: {
fields: [
{
label: 'Name',
name: 'name',
inputType: 'text',
isRequired: true,
},
{
label: 'Email',
name: 'email',
inputType: 'email',
isRequired: true,
},
{
label: 'How can we help?', // This information is processed by the AI assistant
name: 'additionalDetails',
inputType: 'textarea',
placeholder: 'Please provide any additional details that may be helpful.',
},
],
}
}
```
### Secondary Section
Additional fields that can be conditionally shown, typically used for AI-enhanced form fields:
```typescript
interface SecondarySection {
fields: IntelligentFormField[];
description?:
| string
| {
default: string; // Used when AI is not confident
confident: string; // Used when AI is confident it can help
};
}
```
| Property | Type | Required | Description |
| ------------- | ----------------------------- | -------- | --------------------------------------------------------- |
| `fields` | `IntelligentFormField[]` | Yes | Array of form fields to display in the secondary section |
| `description` | `string \| DescriptionObject` | No | Description text or object with confidence-based messages |
#### Example
```javascript
{
secondary: {
description: {
default: 'To finish submitting a support ticket, confirm the fields below and click Submit.',
confident: 'Understood. Please confirm the below information:',
},
fields: [
{
label: 'Subject line',
name: 'subject',
inputType: 'text',
isRequired: true,
description: 'Overview of the issue',
defaultValue: 'General Inquiry',
shouldPrefillWithAI: true, // This field will be automatically populated based on initial input
},
{
label: 'Priority',
name: 'priority',
inputType: 'select',
isRequired: true,
items: [
{ label: 'Urgent', value: 'URGENT' },
{ label: 'High', value: 'HIGH' },
{ label: 'Medium', value: 'MEDIUM' },
{ label: 'Low', value: 'LOW' },
],
placeholder: 'Select a priority',
shouldPrefillWithAI: true, // Priority will be suggested based on the query
},
],
}
}
```
### Form Fields
All form fields share these common properties:
| Property | Type | Required | Description |
| --------------------- | --------- | -------- | ---------------------------------------------------------------------------------- |
| `name` | `string` | Yes | Unique identifier for the field |
| `label` | `string` | Yes | Display label for the field |
| `isRequired` | `boolean` | No | Whether the field is required |
| `isHidden` | `boolean` | No | Whether to hide the field |
| `description` | `string` | No | Helper text shown below the field |
| `shouldPrefillWithAI` | `boolean` | No | Determines if the field gets pre-generated by AI based on the user's initial query |
#### Text Field
```typescript
{
name: 'name',
label: 'Full Name',
inputType: 'text',
defaultValue?: string,
placeholder?: string
}
```
#### Email Field
```typescript
{
name: 'email',
label: 'Email Address',
inputType: 'email',
defaultValue?: string,
placeholder?: string
}
```
#### Textarea Field
```typescript
{
name: 'description',
label: 'Description',
inputType: 'textarea',
defaultValue?: string,
placeholder?: string
}
```
#### Checkbox Field
```typescript
{
name: 'subscribe',
label: 'Subscribe to newsletter',
inputType: 'checkbox',
defaultValue?: boolean
}
```
#### Select Field
```typescript
{
name: 'category',
label: 'Category',
inputType: 'select',
items: [
{ label: 'Option 1', value: 'opt1' },
{ label: 'Option 2', value: 'opt2' }
],
defaultValue?: string,
placeholder?: string
}
```
#### File Field
```typescript
{
name: 'attachment',
label: 'Attach File',
inputType: 'file'
}
```
When using a `file` field in your form, you may need to convert the files to Base64 before sending to your backend or an external API, this can be done by using the following snippet.
```typescript
function convertFilesToBase64(files: FileList) {
const filesArray = Array.from(files);
return Promise.all(
filesArray.map((file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event) => {
const result = (event.target as FileReader).result;
const base64Data = result.replace(/^data:.+;base64,/, "");
resolve({
data: base64Data,
fileName: file.name,
mimeType: file.type,
});
};
reader.onerror = (error) => reject(error);
reader.readAsDataURL(file);
});
})
);
}
```
### Success View
Configuration for the view shown after successful form submission:
```typescript
interface IntelligentFormSuccessView {
heading: string;
message: string;
icon?: InkeepCustomIcon;
}
```
| Property | Type | Required | Description |
| --------- | ------------------ | -------- | ------------------------ |
| `heading` | `string` | Yes | Success message heading |
| `message` | `string` | Yes | Detailed success message |
| `icon` | `InkeepCustomIcon` | No | Custom icon to display |
#### Example
```javascript
{
successView: {
heading: 'Thank you!',
message: "We'll be in touch soon",
}
}
```
### Button Configuration
The `buttons` property configures the form's submit button:
```typescript
{
buttons: {
submit: {
label?: string, // Optional custom label
onSubmit: async ({ values, conversation }) => {
// Handle form submission with form values and conversation context
console.log("Form submitted:", {
values,
conversationId: conversation?.id,
});
},
}
}
}
```
### Complete Example
```javascript
const formSettings = {
// Optional name for the AI assistant shown to users
aiAssistantName: "Support Assistant",
// Primary screen - The first form users interact with
primary: {
fields: [
{
label: "Name",
name: "name",
inputType: "text",
isRequired: true,
},
{
label: "Email",
name: "email",
inputType: "email",
isRequired: true,
},
{
label: "How can we help?",
name: "additionalDetails",
inputType: "textarea",
placeholder:
"Please provide any additional details that may be helpful.",
},
],
},
// Secondary screen - Appears after AI processing
secondary: {
description: {
default:
"To finish submitting a support ticket, confirm the fields below.",
confident: "Understood. Please confirm the below information:",
},
fields: [
{
label: "Subject line",
name: "subject",
inputType: "text",
isRequired: true,
description: "Overview of the issue",
defaultValue: "General Inquiry",
shouldPrefillWithAI: true,
},
{
label: "Priority",
name: "priority",
inputType: "select",
isRequired: true,
items: [
{ label: "Urgent", value: "URGENT" },
{ label: "High", value: "HIGH" },
{ label: "Medium", value: "MEDIUM" },
{ label: "Low", value: "LOW" },
],
placeholder: "Select a priority",
shouldPrefillWithAI: true,
},
{
label: "Ticket type",
name: "ticketType",
inputType: "select",
isRequired: true,
items: [
{ label: "Talk to sales", value: "talk_to_sales" },
{ label: "Issue in production", value: "issue_in_production" },
{ label: "Issue in development", value: "issue_in_development" },
{ label: "Report bug", value: "report_bug" },
{ label: "Onboarding help", value: "onboarding_help" },
{ label: "Account management", value: "account_management" },
{ label: "Feature request", value: "feature_request" },
],
placeholder: "Select a ticket type",
shouldPrefillWithAI: true,
},
],
},
// Success view shown after form submission
successView: {
heading: "Thank you!",
message: "We'll be in touch soon",
},
// Button configuration
buttons: {
submit: {
label: "Submit",
onSubmit: async ({ values, conversation }) => {
// Send form data to your backend
console.log("Form submitted:", {
values,
conversationId: conversation?.id,
});
},
},
},
};
```
## Changing props after initial render
Sometimes you may need to manage change settings after a widget has already been initialized, for example, to update user privacy preferences. To do this, you can use the `update` method.
The below example illustrates how you change the primary color on the widget when a button is clicked.
```typescript
const colors = [
"#26D6FF",
"#e300bd",
"#512fc9",
"#fde046",
"#2ecc71",
"#e74c3c",
"#9b59b6",
"#f1c40f",
];
let count = 0;
const changeColorButton = document.getElementById("change-color-button");
changeColorButton.addEventListener("click", () => {
count++;
widget.update({
baseSettings: {
primaryBrandColor: colors[count % colors.length],
},
});
});
```
***
title: Sidebar Chat (JS)
sidebarTitle: Sidebar Chat
description: Add a chat sidebar to your application.
keywords: embedded chat, sidebar chat, copilot, JavaScript chat, chat UI, chat implementation, JavaScript integration, chat functionality, component methods, chat configuration, UI customization, chat settings, chat interface, JavaScript snippet, chat automation, component setup, chat features
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
A "sidebar chat" is a chat UI that is displayed in a sidebar on the either the left or right side of the page and is resizable.
## Scenarios
You may want to add a sidebar chat directly into your application for a copilot-like experience. Allowing users to chat with the AI assistant directly in your application without needing to leave the context of your application can help them get answers to their questions faster.
## Quick start
Add the below `
```
Define an element in your page that will be the "container" for the sidebar chat.
```html
```
Add a button element that will trigger the sidebar chat and give it the data attribute `data-inkeep-sidebar-chat-trigger`. You can also use your own custom attribute if you prefer, just be sure to pass it to the `triggerSelector` prop.
```html
```
Insert the Sidebar Chat by using the `Inkeep.SidebarChat()` function.
```html
```
## Sidebar Chat Props
This type represents the configuration for the Inkeep sidebar chat widget.
| Prop | Type | Required | Description |
| -------------------- | --------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `aiChatSettings` | `object` | No | AI chat configuration settings. See [AI Chat Settings](/ui-components/common-settings/ai-chat) for details. |
| `position` | `'left' \| 'right'` | No | The position of the sidebar. Defaults to `'right'`. |
| `triggerSelector` | `string` | No | The selector for the trigger element that opens the sidebar. Defaults to `'[data-inkeep-sidebar-chat-trigger]'`. |
| `minWidth` | `number` | No | The minimum width of the sidebar chat. Defaults to `250`. |
| `maxWidth` | `number` | No | The maximum width of the sidebar chat. Defaults to `600`. |
| `defaultWidth` | `number` | No | The default width of the sidebar chat. Defaults to `420`. |
| `defaultOpen` | `boolean` | No | Whether the sidebar chat is open by default. Defaults to `false`. |
| `isOpen` | `boolean` | No | Controls whether the sidebar chat is open. Set to `true` to show the sidebar, `false` to hide it. |
| `onOpenChange` | `(isOpen: boolean) => void` | No | Callback function triggered when the sidebar's open state changes. Useful for syncing state with your application. |
| `autoCloseThreshold` | `number` | No | The threshold for auto-closing the sidebar chat when resizing. When dragging below `minWidth * autoCloseThreshold`, the sidebar will auto-close. Defaults to `0.7` (70% of minimum width). |
## Examples
### Change the sidebar position
```javascript
const config = {
// ... other config
position: "left",
};
const widget = Inkeep.SidebarChat("#ikp-sidebar-chat-target", config);
```
### With AI Chat Settings
```javascript
const config = {
// ... other config
aiChatSettings: {
aiAssistantName: "Support Assistant",
introMessage: "π Hi! How can I help you today?",
},
};
const widget = Inkeep.SidebarChat("#ikp-sidebar-chat-target", config);
```
Refer to the [Chat Settings](/ui-components/common-settings/ai-chat) docs for more details on the available properties.
## Changing props after initial render
Sometimes you may need to manage change settings after a widget has already been initialized, for example, to update user privacy preferences. To do this, you can use the `update` method.
The below example illustrates how you change the primary color on the widget when a button is clicked.
```typescript
const colors = [
"#26D6FF",
"#e300bd",
"#512fc9",
"#fde046",
"#2ecc71",
"#e74c3c",
"#9b59b6",
"#f1c40f",
];
let count = 0;
const changeColorButton = document.getElementById("change-color-button");
changeColorButton.addEventListener("click", () => {
count++;
widget.update({
baseSettings: {
primaryBrandColor: colors[count % colors.length],
},
});
});
```
## Accessing chat methods
The instance of the chat object returned by `Inkeep.SidebarChat()` exposes some methods that you can use to interact with the chat.
```javascript
// Access chat methods
chat.clearChat();
chat.submitMessage("Hello!");
```
| Method | Description |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `submitMessage(message?: string)` | Programmatically sends a message in chat. If message is omitted, sends the current input value. |
| `updateInputMessage(message: string)` | Updates the text in chat input field |
| `clearChat()` | Resets the chat to its initial state |
| `openForm(formSettings: FormSettings)` | Displays a form overlay in chat interface |
| `focusInput()` | Sets focus to the chat input field |
Refer to the [Form Settings](/ui-components/common-settings/actions#formconfig-reference) reference docs for more details on the available properties for the `openForm` method.
***
title: Embedded Chat (JS)
sidebarTitle: Embedded Chat
description: Add a chat UI directly on a dedicated page
keywords: embedded chat, JavaScript chat, chat UI, chat implementation, JavaScript integration, chat functionality, component methods, chat configuration, UI customization, chat settings, chat interface, JavaScript snippet, chat automation, component setup, chat features
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
An "embedded chat" is a chat UI that is directly incorporated into a page instead of within a pop-up modal.
## Scenarios
You may want to add an embedded chat in places where you want to encourage the user to interact with the AI chat directly. For example, an embedded chat can be useful to:
* Deflect questions in your help center site
* Provide an AI chat experience if your documentation site doesn't allow third party components, like for GitBook and ReadMe.
* Create a place for sharable chat sessions
You can incorporate the embedded chat directly on an existing page like `help.domain.com` or create a dedicated one like `domain.com/ask-ai`.
## Quick start
Add the below `
```
Define an element in your page that will be the "container" for the embedded chat.
```html
```
Insert the Embedded Chat by using the `Inkeep.EmbeddedChat()` function.
```html
```
## Embedded Chat Props
This type represents the configuration for the Inkeep embedded chat widget.
| Prop | Type | Required | Description |
| ---------------------- | --------- | -------- | ----------------------------------------------------------------------------------------------------------- |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `aiChatSettings` | `object` | No | AI chat configuration settings. See [AI Chat Settings](/ui-components/common-settings/ai-chat) for details. |
| `isHidden` | `boolean` | No | Whether to hide the chat interface. Defaults to false. |
| `shouldAutoFocusInput` | `boolean` | No | Whether to auto focus the input. Defaults to true. |
## Examples
### Auto Focus Input
```javascript
const config = {
// ... other config
shouldAutoFocusInput: true,
};
const widget = Inkeep.EmbeddedChat("#chat", config);
```
### With AI Chat Settings
```javascript
const config = {
// ... other config
aiChatSettings: {
aiAssistantName: "Support Assistant",
introMessage: "π Hi! How can I help you today?",
},
};
const widget = Inkeep.EmbeddedChat("#ikp-embedded-chat-target", config);
```
Refer to the [Chat Settings](/ui-components/common-settings/ai-chat) docs for more details on the available properties.
## Changing props after initial render
Sometimes you may need to manage change settings after a widget has already been initialized, for example, to update user privacy preferences. To do this, you can use the `update` method.
The below example illustrates how you change the primary color on the widget when a button is clicked.
```typescript
const colors = [
"#26D6FF",
"#e300bd",
"#512fc9",
"#fde046",
"#2ecc71",
"#e74c3c",
"#9b59b6",
"#f1c40f",
];
let count = 0;
const changeColorButton = document.getElementById("change-color-button");
changeColorButton.addEventListener("click", () => {
count++;
widget.update({
baseSettings: {
primaryBrandColor: colors[count % colors.length],
},
});
});
```
## Accessing chat methods
The instance of the chat object returned by `Inkeep.EmbeddedChat()` exposes some methods that you can use to interact with the chat.
```javascript
// Access chat methods
chat.clearChat();
chat.submitMessage("Hello!");
```
| Method | Description |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `submitMessage(message?: string)` | Programmatically sends a message in chat. If message is omitted, sends the current input value. |
| `updateInputMessage(message: string)` | Updates the text in chat input field |
| `clearChat()` | Resets the chat to its initial state |
| `openForm(formSettings: FormSettings)` | Displays a form overlay in chat interface |
| `focusInput()` | Sets focus to the chat input field |
Refer to the [Form Settings](/ui-components/common-settings/actions#formconfig-reference) reference docs for more details on the available properties for the `openForm` method.
***
title: Embedded Search (JS)
sidebarTitle: Embedded Search
description: Add a search UI directly on a dedicated page
keywords: embedded search, JS search component, search UI, search implementation, JS integration, search functionality, component methods, search configuration, UI customization, search settings, search interface, search automation, component props, search features
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
An "embedded search" is a search UI that is directly incorporated into a page instead of within a pop-up modal.
## Quick start
Add the below `
```
Define an element in your page that will be the "container" for the embedded search.
```html
```
Insert the Embedded Search by using the `Inkeep.EmbeddedSearch()` function.
```html
```
## Embedded Search Props
This type represents the configuration for the Inkeep embedded search widget.
| Prop | Type | Required | Description |
| ---------------------- | --------- | -------- | -------------------------------------------------------------------------------------------------------- |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `searchSettings` | `object` | No | Search configuration settings. See [Search Settings](/ui-components/common-settings/search) for details. |
| `isHidden` | `boolean` | No | Whether to hide the search interface. Defaults to false. |
| `shouldAutoFocusInput` | `boolean` | No | Whether to auto focus the input. Defaults to true. |
## Examples
### Auto Focus Input
```javascript
const config = {
// ... other config
shouldAutoFocusInput: true,
};
const widget = Inkeep.EmbeddedSearch("#search", config);
```
### With Search Settings
```javascript
const config = {
// ... other config
searchSettings: {
placeholder: "Search...",
debounceTimeMs: 300,
},
};
const widget = Inkeep.EmbeddedSearch("#ikp-embedded-search-target", config);
```
Refer to the [Search Settings](/ui-components/common-settings/search) docs for more details on the available properties.
## Changing props after initial render
Sometimes you may need to manage change settings after a widget has already been initialized, for example, to update user privacy preferences. To do this, you can use the `update` method.
The below example illustrates how you change the primary color on the widget when a button is clicked.
```typescript
const colors = [
"#26D6FF",
"#e300bd",
"#512fc9",
"#fde046",
"#2ecc71",
"#e74c3c",
"#9b59b6",
"#f1c40f",
];
let count = 0;
const changeColorButton = document.getElementById("change-color-button");
changeColorButton.addEventListener("click", () => {
count++;
widget.update({
baseSettings: {
primaryBrandColor: colors[count % colors.length],
},
});
});
```
## Accessing search methods
The instance of the search object returned by `Inkeep.EmbeddedSearch()` exposes some methods that you can use to interact with the search.
```javascript
// Access search methods
search.updateQuery("Hello!");
search.focusInput();
```
| Method | Description |
| ---------------------------- | ------------------------------------------ |
| `updateQuery(query: string)` | Programmatically updates the search query. |
| `focusInput()` | Sets focus to the search input field |
***
title: Embedded Search and Chat (JS)
sidebarTitle: Embedded Search and Chat
description: Add a toggleable search and chat UI directly on a dedicated page
keywords: embedded search and chat, JavaScript components, combined UI, search functionality, chat interface, component integration, UI customization, JavaScript implementation, search settings, chat configuration, component methods, JavaScript events, UI toggling, search and chat features, component setup
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
This is a toggleable chat / search UI that is directly incorporated into a page instead of within a pop-up modal.
It's a combination of the [Embedded Chat](/ui-components/js-snippet/in-page/embedded-chat) and the [Embedded Search](/ui-components/js-snippet/in-page/embedded-search) components, allowing you to toggle between chat and search.
## Quick start
Add the below `
```
Define an element in your page that will be the "container" for the embedded search and chat.
```html
```
Insert the Embedded Search and Chat by using the `Inkeep.EmbeddedSearchAndChat()` function.
```html
```
## Embedded Search Props
This type represents the configuration for the Inkeep embedded search widget.
| Prop | Type | Required | Description |
| ---------------------- | --------- | -------- | -------------------------------------------------------------------------------------------------------- |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `searchSettings` | `object` | No | Search configuration settings. See [Search Settings](/ui-components/common-settings/search) for details. |
| `isHidden` | `boolean` | No | Whether to hide the search interface. Defaults to false. |
| `shouldAutoFocusInput` | `boolean` | No | Whether to auto focus the input. Defaults to true. |
| `askAICardLabel` | `string` | No | The label for the Ask AI card in search results. Defaults to `Ask AI` or `askAILabel` if provided. |
| `askAILabel` | `string` | No | The label for the Ask AI button in the search/chat toggle. Defaults to `Ask AI`. |
| `searchLabel` | `string` | No | The label for the search button in the search/chat toggle. Defaults to `Search`. |
## Examples
### Set the default view
```javascript
const config = {
// ... other config
defaultView: "chat", // or "search"
};
const widget = Inkeep.EmbeddedSearchAndChat(
"#ikp-embedded-search-and-chat-target",
config
);
```
### Force the default view
If you want to force the default view to be the search or the chat, you can use the `forceDefaultView` property. This is useful to ensure the widget always opens the defaultView instead of last used view.
```javascript
const config = {
// ... other config
forceDefaultView: true,
};
const widget = Inkeep.EmbeddedSearchAndChat(
"#ikp-embedded-search-and-chat-target",
config
);
```
Refer to the [Search Settings](/ui-components/common-settings/search) and [Chat Settings](/ui-components/common-settings/chat) docs for more details on the available properties.
## Changing props after initial render
Sometimes you may need to manage change settings after a widget has already been initialized, for example, to update user privacy preferences. To do this, you can use the `update` method.
The below example illustrates how you change the primary color on the widget when a button is clicked.
```typescript
const colors = [
"#26D6FF",
"#e300bd",
"#512fc9",
"#fde046",
"#2ecc71",
"#e74c3c",
"#9b59b6",
"#f1c40f",
];
let count = 0;
const changeColorButton = document.getElementById("change-color-button");
changeColorButton.addEventListener("click", () => {
count++;
widget.update({
baseSettings: {
primaryBrandColor: colors[count % colors.length],
},
});
});
```
## Accessing methods
The instance of the widget object returned by `Inkeep.EmbeddedSearchAndChat()` exposes some methods that you can use to interact with the widget.
You can access both the search and the chat methods.
```javascript
// Access chat methods
widget.chat.clearChat();
widget.chat.focusInput();
// Access search methods
widget.search.updateQuery("Hello!");
widget.search.focusInput();
// Access widget methods
widget.setView("search");
```
### Chat Methods
| Method | Description |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `submitMessage(message?: string)` | Programmatically sends a message in chat. If message is omitted, sends the current input value. |
| `updateInputMessage(message: string)` | Updates the text in chat input field |
| `clearChat()` | Resets the chat to its initial state |
| `openForm(formSettings: FormSettings)` | Displays a form overlay in chat interface |
| `focusInput()` | Sets focus to the chat input field |
Refer to the [Form Settings](/ui-components/common-settings/actions#formconfig-reference) reference docs for more details on the available properties for the `openForm` method.
### Search methods
| Method | Description |
| ---------------------------- | ------------------------------------------ |
| `updateQuery(query: string)` | Programmatically updates the search query. |
| `focusInput()` | Sets focus to the search input field |
### Widget methods
```typescript
type ModalViewTypes = "search" | "chat";
```
| Method | Description |
| ------------------------------- | --------------------------------------------------- |
| `setView(view: ModalViewTypes)` | Set the view of the widget to either search or chat |
***
title: Chat Button (React)
sidebarTitle: Chat Button
description: Add a chat button React component that triggers the Inkeep modal.
keywords: React chat button, chat component, UI components, React integration, chat functionality, component configuration, chat settings, modal trigger, component methods, React hooks, chat implementation, UI customization, button styling, component props, chat interface
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
The chat button is a great way to add an AI copilot to your landing page, documentation, or app without changing your current search experience.
## Quick Start
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Define the component
```tsx
import {
InkeepChatButton,
type InkeepChatButtonProps,
} from "@inkeep/cxkit-react";
const config: InkeepChatButtonProps = {
baseSettings: {
apiKey: "YOUR_API_KEY",
},
aiChatSettings: {
aiAssistantName: "Keepie",
},
label: "Ask AI",
};
const App = () => {
return ;
};
```
## Chat Button Props
Chat button props control the behavior and interaction of the chat button.
| Prop | Type | Required | Description |
| ---------------- | ------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------- |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `aiChatSettings` | `object` | No | AI chat configuration settings. See [AI Chat Settings](/ui-components/common-settings/ai-chat) for details. |
| `modalSettings` | `object` | No | Modal configuration settings. See [Modal Settings](/ui-components/react/custom-modal-trigger#modal-settings) for details. |
| `label` | `string` | No | Custom label for the chat button. |
| `canToggleView` | `boolean` | No | Whether to allow toggling between chat and search views. Defaults to true. |
| `defaultView` | `'search' \| 'chat'` | No | The default view to show when opened. Defaults to 'chat'. |
| `avatar` | `string \| { light: string, dark: string }` | No | URL for ai button's avatar (40x40px recommended) |
| `askAICardLabel` | `string` | No | The label for the Ask AI card in search results. Defaults to `Ask AI` or `askAILabel` if provided. |
| `askAILabel` | `string` | No | The label for the Ask AI button in the search/chat toggle. Defaults to `Ask AI`. |
| `searchLabel` | `string` | No | The label for the search button in the search/chat toggle. Defaults to `Search`. |
## Examples
### Set the default view
```tsx
import {
InkeepChatButton,
type InkeepChatButtonProps,
} from "@inkeep/cxkit-react";
const config: InkeepChatButtonProps = {
// ... other config
defaultView: "chat", // or "search"
};
const App = () => {
return ;
};
```
### Force the default view
If you want to force the default view to be the search or the chat, you can use the `forceDefaultView` property. This is useful to ensure the widget always opens the defaultView instead of last used view.
```tsx
import {
InkeepChatButton,
type InkeepChatButtonProps,
} from "@inkeep/cxkit-react";
const config: InkeepChatButtonProps = {
// ... other config
forceDefaultView: true,
};
const App = () => {
return ;
};
```
Refer to the [Search Settings](/ui-components/common-settings/search) and [Chat Settings](/ui-components/common-settings/chat) docs for more details on the available properties.
### Accessing Component Methods
Exactly how you'd do it in the [Embedded Search](/ui-components/react/in-page/embedded-search#accessing-component-methods) and [Embedded Chat](/ui-components/react/in-page/embedded-chat#accessing-component-methods) components respectively.
```tsx
const App = () => {
import type {
SearchFunctions,
ChatFunctions,
InkeepChatButtonProps,
} from "@inkeep/cxkit-types";
const searchFunctionsRef = useRef(null);
const chatFunctionsRef = useRef(null);
const config: InkeepChatButtonProps = {
// ... other config
searchSettings: {
searchFunctionsRef,
},
aiChatSettings: {
chatFunctionsRef,
},
};
const updateSearchQuery = () => {
searchFunctionsRef.current?.updateQuery("Hello!");
};
const clearChat = () => {
chatFunctionsRef.current?.clearChat();
};
return (
<>
Update Query
Clear Chat
>
);
};
```
### Chat Methods
| Method | Description |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `submitMessage(message?: string)` | Programmatically sends a message in chat. If message is omitted, sends the current input value. |
| `updateInputMessage(message: string)` | Updates the text in chat input field |
| `clearChat()` | Resets the chat to its initial state |
| `openForm(formSettings: FormSettings)` | Displays a form overlay in chat interface |
| `focusInput()` | Sets focus to the chat input field |
Refer to the [Form Settings](/ui-components/common-settings/actions#formconfig-reference) reference docs for more details on the available properties for the `openForm` method.
### Search methods
| Method | Description |
| ---------------------------- | ------------------------------------------ |
| `updateQuery(query: string)` | Programmatically updates the search query. |
| `focusInput()` | Sets focus to the search input field |
### Widget methods
```typescript
type ModalViewTypes = "search" | "chat";
```
| Method | Description |
| ------------------------------- | --------------------------------------------------- |
| `setView(view: ModalViewTypes)` | Set the view of the widget to either search or chat |
## FAQ
If you use a `webpack` build. You could come across this error.
To fix this you need to create a custom loader for your webpack configuration to disable
this behavior.
> Since webpack 5.0.0-beta.30, you're required to specify extensions when
> using imports in .mjs files or any .js files with a package.json with "type":
> "module". You can still disable the behavior with resolve.fullySpecified set
> to false if you see any related errors in your project.
We can add a new rule to our webpack configuration to disable this behavior.
```js
module.exports = {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
```
Then add this to your `webpack.config.js` file.
If you use docusaurus, you can add this to your `docusaurus.config.js` file as a `webpack` config override with plugins.
```js
/** @type {import('@docusaurus/types').Config} */
const config = {
// ...
plugins: [
() => {
return {
name: "loader",
configureWebpack() {
return {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
},
};
},
],
// ...
};
module.exports = config;
```
***
title: Search Bar (React)
sidebarTitle: Search Bar
description: Add the Inkeep search bar as a React component.
keywords: React search bar, search component, UI components, React integration, search functionality, component configuration, search settings, chat integration, component methods, React hooks, search implementation, UI customization, search bar styling, component props, search interface
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
The search bar is a great way to add an AI powered search bar to your website.
## Quick Start
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Define the component
```tsx
import {
InkeepSearchBar,
type InkeepSearchBarProps,
} from "@inkeep/cxkit-react";
const config: InkeepSearchBarProps = {
baseSettings: {
apiKey: "YOUR_API_KEY",
organizationDisplayName: "Your Company",
primaryBrandColor: "#4F46E5",
},
searchSettings: {
placeholder: "Search documentation...",
},
};
const App = () => {
return ;
};
```
## Search Bar Props
Search bar props control the behavior and interaction of the search bar.
| Prop | Type | Required | Description |
| --------------------- | -------------------- | -------- | ----------------------------------------------------------------------------------------------------------- |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `aiChatSettings` | `object` | No | AI chat configuration settings. See [AI Chat Settings](/ui-components/common-settings/ai-chat) for details. |
| `modalSettings` | `object` | No | Modal configuration settings. See [Modal Settings](/ui-components/common-settings/modal) for details. |
| `canToggleView` | `boolean` | No | Whether to allow toggling between chat and search views. Defaults to true. |
| `defaultView` | `'search' \| 'chat'` | No | The default view to show when opened. Defaults to 'search'. |
| `shouldShowAskAICard` | `boolean` | No | Whether to show the Ask AI card. Defaults to true. |
| `askAICardLabel` | `string` | No | The label for the Ask AI card in search results. Defaults to `Ask AI` or `askAILabel` if provided. |
| `askAILabel` | `string` | No | The label for the Ask AI button in the search/chat toggle. Defaults to `Ask AI`. |
| `searchLabel` | `string` | No | The label for the search button in the search/chat toggle. Defaults to `Search`. |
## Examples
### Set the default view
```tsx
import {
InkeepSearchBar,
type InkeepSearchBarProps,
} from "@inkeep/cxkit-react";
const config: InkeepSearchBarProps = {
// ... other config
defaultView: "search", // or "chat"
};
const App = () => {
return ;
};
```
### Force the default view
If you want to force the default view to be the search or the chat, you can use the `forceDefaultView` property. This is useful to ensure the widget always opens the defaultView instead of last used view.
```tsx
import {
InkeepSearchBar,
type InkeepSearchBarProps,
} from "@inkeep/cxkit-react";
const config: InkeepSearchBarProps = {
// ... other config
forceDefaultView: true,
};
const App = () => {
return ;
};
```
Refer to the [Search Settings](/ui-components/common-settings/search) and [Chat Settings](/ui-components/common-settings/chat) docs for more details on the available properties.
### Accessing Component Methods
Exactly how you'd do it in the [Embedded Search](/ui-components/react/in-page/embedded-search#accessing-component-methods) and [Embedded Chat](/ui-components/react/in-page/embedded-chat#accessing-component-methods) components respectively.
```tsx
const App = () => {
import type {
SearchFunctions,
ChatFunctions,
InkeepSearchBarProps,
} from "@inkeep/cxkit-types";
const searchFunctionsRef = useRef(null);
const chatFunctionsRef = useRef(null);
const config: InkeepSearchBarProps = {
// ... other config
searchSettings: {
searchFunctionsRef,
},
aiChatSettings: {
chatFunctionsRef,
},
};
const updateSearchQuery = () => {
searchFunctionsRef.current?.updateQuery("Hello!");
};
const clearChat = () => {
chatFunctionsRef.current?.clearChat();
};
return (
<>
Update Query
Clear Chat
>
);
};
```
### Chat Methods
| Method | Description |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `submitMessage(message?: string)` | Programmatically sends a message in chat. If message is omitted, sends the current input value. |
| `updateInputMessage(message: string)` | Updates the text in chat input field |
| `clearChat()` | Resets the chat to its initial state |
| `openForm(formSettings: FormSettings)` | Displays a form overlay in chat interface |
| `focusInput()` | Sets focus to the chat input field |
Refer to the [Form Settings](/ui-components/common-settings/actions#formconfig-reference) reference docs for more details on the available properties for the `openForm` method.
### Search methods
| Method | Description |
| ---------------------------- | ------------------------------------------ |
| `updateQuery(query: string)` | Programmatically updates the search query. |
| `focusInput()` | Sets focus to the search input field |
### Widget methods
```typescript
type ModalViewTypes = "search" | "chat";
```
| Method | Description |
| ------------------------------- | --------------------------------------------------- |
| `setView(view: ModalViewTypes)` | Set the view of the widget to either search or chat |
## FAQ
If you use a `webpack` build. You could come across this error.
To fix this you need to create a custom loader for your webpack configuration to disable
this behavior.
> Since webpack 5.0.0-beta.30, you're required to specify extensions when
> using imports in .mjs files or any .js files with a package.json with "type":
> "module". You can still disable the behavior with resolve.fullySpecified set
> to false if you see any related errors in your project.
We can add a new rule to our webpack configuration to disable this behavior.
```js
module.exports = {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
```
Then add this to your `webpack.config.js` file.
If you use docusaurus, you can add this to your `docusaurus.config.js` file as a `webpack` config override with plugins.
```js
/** @type {import('@docusaurus/types').Config} */
const config = {
// ...
plugins: [
() => {
return {
name: "loader",
configureWebpack() {
return {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
},
};
},
],
// ...
};
module.exports = config;
```
***
title: Trigger the Inkeep modal with a custom trigger (React)
sidebarTitle: Custom Trigger
keywords: custom modal trigger, React modal, modal component, UI customization, modal implementation, custom button, modal trigger, React hooks, modal configuration, UI components, modal settings, component integration, modal functionality, custom UI, modal events
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Use the "Custom Trigger" if you want to use your own button, search bar, link, or any other UI element for opening and closing Inkeep's modal. This is an alternative to using the Inkeep `SearchBar` or `ChatButton` components.
## Overview
The Inkeep modal can contain search, chat, or a combined experience.
The available modal components are:
| Component | Description |
| -------------------------- | ---------------------------------------------------------------- |
| `InkeepModalSearchAndChat` | Combined search and chat experience with a toggle for switching. |
| `InkeepModalSearch` | Search-only experience |
| `InkeepModalChat` | Chat-only experience |
## Quick Start
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Define the component
Lets start with the `InkeepModalSearchAndChat`. To trigger the modal, you configure the `isOpen` property to be `true` or `false` based on whether the user clicks on your own custom trigger.
```tsx
import React, { useState, useRef, useCallback } from "react";
import {
InkeepModalSearchAndChat,
type InkeepModalSearchAndChatProps,
} from "@inkeep/cxkit-react";
const App = () => {
const [isOpen, setIsOpen] = useState(false);
const config: InkeepModalSearchAndChatProps = {
defaultView: "chat", // or "search"
forceDefaultView: true, // always open with the `defaultView`
baseSettings: {
apiKey: "YOUR_API_KEY",
primaryBrandColor: "#000000",
},
modalSettings: {
isOpen,
onOpenChange: handleOpenChange,
},
aiChatSettings: {
aiAssistantName: "Keepie",
},
searchSettings: {
placeholder: "Search...",
},
};
const handleOpenChange = useCallback((newOpen: boolean) => {
setIsOpen(newOpen);
}, []);
return (
<>
{/* Your Custom Trigger */}
setIsOpen(true)}>Open Modal
{/* The Inkeep Modal Component */}
>
);
};
```
## Modal Settings
Modal settings control the behavior and interaction of modal components. These settings are passed in the `modalSettings` prop.
| Setting | Type | Default | Description |
| ----------------- | --------------------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `isOpen` | `boolean` | `false` | Controls the visibility of the modal. Set to `true` to show the modal, `false` to hide it. |
| `onOpenChange` | `(isOpen: boolean) => void` | - | Callback function triggered when the modal's open state changes. Useful for syncing state with your application. |
| `shortcutKey` | `string \| null` | - | The keyboard key that triggers the modal when pressed with Cmd (Mac) or Ctrl (Windows). Set to `null` to disable the shortcut. |
| `triggerSelector` | `string` | `'[data-inkeep-modal-trigger]'` | The selector for the trigger element that opens the modal. If you add a button with the `data-inkeep-modal-trigger` attribute, you do not need to implement your own `onOpenChange` handler or pass the `isOpen` prop to the `modalSettings`. |
### Modal Search
A modal version of the embedded search component. For detailed information about search functionality and available settings, see [Embedded Search](./embedded-search.md).
```tsx
import React, { useState, useRef, useCallback } from "react";
import {
InkeepModalSearch,
type InkeepModalSearchProps,
} from "@inkeep/cxkit-react";
const App = () => {
const [isOpen, setIsOpen] = useState(false);
const searchFunctionsRef = useRef(null);
const config: InkeepModalSearchProps = {
baseSettings: {
apiKey: "YOUR_API_KEY",
primaryBrandColor: "#000000",
},
searchSettings: {
placeholder: "Search...",
searchFunctionsRef,
},
modalSettings: {
isOpen,
onOpenChange: handleOpenChange,
},
};
const handleOpenChange = useCallback((newOpen: boolean) => {
setIsOpen(newOpen);
}, []);
// Access search methods
const updateQuery = () => {
searchFunctionsRef.current?.updateQuery("Hello!");
};
return (
<>
{/* Custom Trigger */}
setIsOpen(true)}>Open Search Modal
{/* Modal Component */}
{/* Update Query */}
Update Query
>
);
};
```
### Modal Chat
A modal version of the embedded chat component. For detailed information about chat functionality and available settings, see [Embedded Chat](/ui-components/react/in-page/embedded-chat).
```tsx
import React, { useState, useRef, useCallback } from "react";
import {
InkeepModalChat,
type InkeepModalChatProps,
} from "@inkeep/cxkit-react";
const App = () => {
const [isOpen, setIsOpen] = useState(false);
const chatFunctionsRef = useRef(null);
const config: InkeepModalChatProps = {
baseSettings: {
apiKey: "YOUR_API_KEY",
primaryBrandColor: "#000000",
},
aiChatSettings: {
aiAssistantName: "Keepie",
},
modalSettings: {
isOpen,
onOpenChange: handleOpenChange,
},
};
const handleOpenChange = useCallback((newOpen: boolean) => {
setIsOpen(newOpen);
}, []);
// Access chat methods
const clearChat = () => {
chatFunctionsRef.current?.clearChat();
};
return (
<>
{/* Custom Trigger */}
setIsOpen(true)}>Open Chat Modal
{/* Modal Component */}
{/* Clear Chat */}
Clear Chat
>
);
};
```
## Component Methods
### Chat Methods
| Method | Description |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `submitMessage(message?: string)` | Programmatically sends a message in chat. If message is omitted, sends the current input value. |
| `updateInputMessage(message: string)` | Updates the text in chat input field |
| `clearChat()` | Resets the chat to its initial state |
| `openForm(formSettings: FormSettings)` | Displays a form overlay in chat interface |
| `focusInput()` | Sets focus to the chat input field |
Refer to the [Form Settings](/ui-components/common-settings/actions#formconfig-reference) reference docs for more details on the available properties for the `openForm` method.
### Search methods
| Method | Description |
| ---------------------------- | ------------------------------------------ |
| `updateQuery(query: string)` | Programmatically updates the search query. |
| `focusInput()` | Sets focus to the search input field |
### Widget methods
```typescript
type ModalViewTypes = "search" | "chat";
```
| Method | Description |
| ------------------------------- | --------------------------------------------------- |
| `setView(view: ModalViewTypes)` | Set the view of the widget to either search or chat |
## FAQ
If you use a `webpack` build. You could come across this error.
To fix this you need to create a custom loader for your webpack configuration to disable
this behavior.
> Since webpack 5.0.0-beta.30, you're required to specify extensions when
> using imports in .mjs files or any .js files with a package.json with "type":
> "module". You can still disable the behavior with resolve.fullySpecified set
> to false if you see any related errors in your project.
We can add a new rule to our webpack configuration to disable this behavior.
```js
module.exports = {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
```
Then add this to your `webpack.config.js` file.
If you use docusaurus, you can add this to your `docusaurus.config.js` file as a `webpack` config override with plugins.
```js
/** @type {import('@docusaurus/types').Config} */
const config = {
// ...
plugins: [
() => {
return {
name: "loader",
configureWebpack() {
return {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
},
};
},
],
// ...
};
module.exports = config;
```
***
title: Intelligent Form (React)
sidebarTitle: Intelligent Form
description: Add an intelligent form UI directly on a dedicated React powered page.
keywords: intelligent form, React form, AI-powered form, form automation, form configuration, form fields, form submission, React components, form UI, form validation, form customization, form handling, form integration, form settings, form implementation
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
The Intelligent Form component is designed to help deflect support tickets at creation time in a tasteful way.
If the AI is confident, it'll attempt to deflect the user's question prior to ticket creation.
If it's not confident - it can still be helpful by taking a user's input and prefilling other parts of the form. Useful for simplifying your form while extracting structured information needed by your ticketing platform.
## How It Works
1. **Primary Screen**: Users enter their initial information (name, email, question/details)
2. **AI Deflection**: The AI assistant analyzes the user's input
* If confident it can help: The user is shown an answer. They can continue to the secondary screen if it doesn't resolve their question.
* If not confident: User proceeds directly to the secondary screen
3. **Secondary Screen**: Contains additional fields to collect structured information
* These fields can be automatically pre-filled by AI based on the user's initial input
* User reviews and confirms the information
4. **Submission**: When the user submits the form, your custom callback function is triggered
* Your callback receives all form data and conversation context
* You can connect this to your ticketing system, CRM, or other backend systems
This flow aims to reduce support tickets in an elegant way that also simplifies the end-user experience.
## Quick Start
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Define the component
```tsx
import {
InkeepIntelligentForm,
type InkeepIntelligentFormProps,
} from "@inkeep/cxkit-react";
const config: InkeepIntelligentFormProps = {
baseSettings: {
apiKey: "YOUR_API_KEY",
primaryBrandColor: "#000000",
},
formSettings: {
primary: {
fields: [
{
label: "Name",
name: "name",
inputType: "text",
isRequired: true,
},
{
label: "Email",
name: "email",
inputType: "email",
isRequired: true,
},
{
label: "How can we help?",
name: "additionalDetails",
inputType: "textarea",
placeholder:
"Please provide any additional details that may be helpful.",
},
],
},
secondary: {
description: {
default:
"To finish submitting your request, please confirm the details below.",
confident:
"We found an answer that might help. Please confirm your details to continue.",
},
fields: [
{
label: "Subject",
name: "subject",
inputType: "text",
isRequired: true,
shouldPrefillWithAI: true, // Automatically populate based on user's query
},
],
},
successView: {
heading: "Thank you!",
message: "We'll be in touch soon",
},
buttons: {
submit: {
label: "Submit",
onSubmit: async ({ values, conversation }) => {
// Process form data with your backend system
console.log("Form submitted:", values, conversation?.id);
},
},
},
},
};
const App = () => {
return ;
};
```
## Props
| Prop | Type | Required | Description |
| -------------- | -------- | -------- | -------------------------------------------------------------------------------------------------- |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `formSettings` | `object` | Yes | Form configuration settings. See below for details. |
## Form Settings
The `formSettings` object configures the behavior, layout, and functionality of the Intelligent Form widget. The form is divided into primary and secondary sections, with additional settings for success messages and submission handling.
### Configuration Structure
```typescript
interface IntelligentFormSettings {
aiAssistantName?: string;
primary: PrimarySection;
secondary: SecondarySection;
successView: IntelligentFormSuccessView;
buttons: IntelligentFormButtons;
}
```
### Assistant Name
An optional name that's displayed in the form header:
```typescript
const formSettings = {
aiAssistantName: "Support Agent",
};
```
### Primary Section
The initial form fields that are always displayed to the user:
```typescript
interface PrimarySection {
fields: IntelligentFormField[];
description?: string;
}
```
| Property | Type | Required | Description |
| ------------- | ------------------------ | -------- | ------------------------------------------------ |
| `fields` | `IntelligentFormField[]` | Yes | Array of form fields to display initially |
| `description` | `string` | No | Optional description text shown above the fields |
#### Example
```javascript
{
primary: {
fields: [
{
label: 'Name',
name: 'name',
inputType: 'text',
isRequired: true,
},
{
label: 'Email',
name: 'email',
inputType: 'email',
isRequired: true,
},
{
label: 'How can we help?', // This information is processed by the AI assistant
name: 'additionalDetails',
inputType: 'textarea',
placeholder: 'Please provide any additional details that may be helpful.',
},
],
}
}
```
### Secondary Section
Additional fields that can be conditionally shown, typically used for AI-enhanced form fields:
```typescript
interface SecondarySection {
fields: IntelligentFormField[];
description?:
| string
| {
default: string; // Used when AI is not confident
confident: string; // Used when AI is confident it can help
};
}
```
| Property | Type | Required | Description |
| ------------- | ----------------------------- | -------- | --------------------------------------------------------- |
| `fields` | `IntelligentFormField[]` | Yes | Array of form fields to display in the secondary section |
| `description` | `string \| DescriptionObject` | No | Description text or object with confidence-based messages |
#### Example
```javascript
{
secondary: {
description: {
default: 'To finish submitting a support ticket, confirm the fields below and click Submit.',
confident: 'Understood. Please confirm the below information:',
},
fields: [
{
label: 'Subject line',
name: 'subject',
inputType: 'text',
isRequired: true,
description: 'Overview of the issue',
defaultValue: 'General Inquiry',
shouldPrefillWithAI: true, // This field will be automatically populated based on initial input
},
{
label: 'Priority',
name: 'priority',
inputType: 'select',
isRequired: true,
items: [
{ label: 'Urgent', value: 'URGENT' },
{ label: 'High', value: 'HIGH' },
{ label: 'Medium', value: 'MEDIUM' },
{ label: 'Low', value: 'LOW' },
],
placeholder: 'Select a priority',
shouldPrefillWithAI: true, // Priority will be suggested based on the query
},
],
}
}
```
### Form Fields
All form fields share these common properties:
| Property | Type | Required | Description |
| --------------------- | --------- | -------- | ---------------------------------------------------------------------------------- |
| `name` | `string` | Yes | Unique identifier for the field |
| `label` | `string` | Yes | Display label for the field |
| `isRequired` | `boolean` | No | Whether the field is required |
| `isHidden` | `boolean` | No | Whether to hide the field |
| `description` | `string` | No | Helper text shown below the field |
| `shouldPrefillWithAI` | `boolean` | No | Determines if the field gets pre-generated by AI based on the user's initial query |
#### Text Field
```typescript
{
name: 'name',
label: 'Full Name',
inputType: 'text',
defaultValue?: string,
placeholder?: string
}
```
#### Email Field
```typescript
{
name: 'email',
label: 'Email Address',
inputType: 'email',
defaultValue?: string,
placeholder?: string
}
```
#### Textarea Field
```typescript
{
name: 'description',
label: 'Description',
inputType: 'textarea',
defaultValue?: string,
placeholder?: string
}
```
#### Checkbox Field
```typescript
{
name: 'subscribe',
label: 'Subscribe to newsletter',
inputType: 'checkbox',
defaultValue?: boolean
}
```
#### Select Field
```typescript
{
name: 'category',
label: 'Category',
inputType: 'select',
items: [
{ label: 'Option 1', value: 'opt1' },
{ label: 'Option 2', value: 'opt2' }
],
defaultValue?: string,
placeholder?: string
}
```
#### File Field
```typescript
{
name: 'attachment',
label: 'Attach File',
inputType: 'file'
}
```
When using a `file` field in your form, you may need to convert the files to Base64 before sending to your backend or an external API, this can be done by using the following snippet.
```typescript
function convertFilesToBase64(files: FileList) {
const filesArray = Array.from(files);
return Promise.all(
filesArray.map((file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event) => {
const result = (event.target as FileReader).result;
const base64Data = result.replace(/^data:.+;base64,/, "");
resolve({
data: base64Data,
fileName: file.name,
mimeType: file.type,
});
};
reader.onerror = (error) => reject(error);
reader.readAsDataURL(file);
});
})
);
}
```
### Success View
Configuration for the view shown after successful form submission:
```typescript
interface IntelligentFormSuccessView {
heading: string;
message: string;
icon?: InkeepCustomIcon;
}
```
| Property | Type | Required | Description |
| --------- | ------------------ | -------- | ------------------------ |
| `heading` | `string` | Yes | Success message heading |
| `message` | `string` | Yes | Detailed success message |
| `icon` | `InkeepCustomIcon` | No | Custom icon to display |
#### Example
```javascript
{
successView: {
heading: 'Thank you!',
message: "We'll be in touch soon",
}
}
```
### Button Configuration
The `buttons` property configures the form's submit button:
```typescript
{
buttons: {
submit: {
label?: string, // Optional custom label
onSubmit: async ({ values, conversation }) => {
// Handle form submission with form values and conversation context
console.log("Form submitted:", {
values,
conversationId: conversation?.id,
});
},
}
}
}
```
### Complete Example
```javascript
const formSettings = {
// Optional name for the AI assistant shown to users
aiAssistantName: "Support Assistant",
// Primary screen - The first form users interact with
primary: {
fields: [
{
label: "Name",
name: "name",
inputType: "text",
isRequired: true,
},
{
label: "Email",
name: "email",
inputType: "email",
isRequired: true,
},
{
label: "How can we help?",
name: "additionalDetails",
inputType: "textarea",
placeholder:
"Please provide any additional details that may be helpful.",
},
],
},
// Secondary screen - Appears after AI processing
secondary: {
description: {
default:
"To finish submitting a support ticket, confirm the fields below.",
confident: "Understood. Please confirm the below information:",
},
fields: [
{
label: "Subject line",
name: "subject",
inputType: "text",
isRequired: true,
description: "Overview of the issue",
defaultValue: "General Inquiry",
shouldPrefillWithAI: true,
},
{
label: "Priority",
name: "priority",
inputType: "select",
isRequired: true,
items: [
{ label: "Urgent", value: "URGENT" },
{ label: "High", value: "HIGH" },
{ label: "Medium", value: "MEDIUM" },
{ label: "Low", value: "LOW" },
],
placeholder: "Select a priority",
shouldPrefillWithAI: true,
},
{
label: "Ticket type",
name: "ticketType",
inputType: "select",
isRequired: true,
items: [
{ label: "Talk to sales", value: "talk_to_sales" },
{ label: "Issue in production", value: "issue_in_production" },
{ label: "Issue in development", value: "issue_in_development" },
{ label: "Report bug", value: "report_bug" },
{ label: "Onboarding help", value: "onboarding_help" },
{ label: "Account management", value: "account_management" },
{ label: "Feature request", value: "feature_request" },
],
placeholder: "Select a ticket type",
shouldPrefillWithAI: true,
},
],
},
// Success view shown after form submission
successView: {
heading: "Thank you!",
message: "We'll be in touch soon",
},
// Button configuration
buttons: {
submit: {
label: "Submit",
onSubmit: async ({ values, conversation }) => {
// Send form data to your backend
console.log("Form submitted:", {
values,
conversationId: conversation?.id,
});
},
},
},
};
```
## FAQ
If you use a `webpack` build. You could come across this error.
To fix this you need to create a custom loader for your webpack configuration to disable
this behavior.
> Since webpack 5.0.0-beta.30, you're required to specify extensions when
> using imports in .mjs files or any .js files with a package.json with "type":
> "module". You can still disable the behavior with resolve.fullySpecified set
> to false if you see any related errors in your project.
We can add a new rule to our webpack configuration to disable this behavior.
```js
module.exports = {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
```
Then add this to your `webpack.config.js` file.
If you use docusaurus, you can add this to your `docusaurus.config.js` file as a `webpack` config override with plugins.
```js
/** @type {import('@docusaurus/types').Config} */
const config = {
// ...
plugins: [
() => {
return {
name: "loader",
configureWebpack() {
return {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
},
};
},
],
// ...
};
module.exports = config;
```
***
title: Sidebar Chat (React)
sidebarTitle: Sidebar Chat
description: Add a chat sidebar to your React application.
keywords: embedded chat, sidebar chat, copilot, React chat component, chat UI, chat implementation, React integration, chat functionality, component methods, chat configuration, UI customization, chat settings, chat interface, React hooks, chat automation, component props, chat features
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
A "sidebar chat" is a chat UI that is displayed in a sidebar on the either the left or right side of the page and is resizable.
## Scenarios
You may want to add a sidebar chat directly into your application for a copilot-like experience. Allowing users to chat with the AI assistant directly in your application without needing to leave the context of your application can help them get answers to their questions faster.
## Quick Start
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Define the component
```tsx
import {
InkeepSidebarChat,
type InkeepSidebarChatProps,
} from "@inkeep/cxkit-react";
const config: InkeepSidebarChatProps = {
baseSettings: {
apiKey: "YOUR_API_KEY",
},
aiChatSettings: {
exampleQuestions: ["How do I get started?"],
},
};
const App = () => {
return (
);
};
```
## Sidebar Chat Props
This type represents the configuration for the Inkeep sidebar chat widget.
| Prop | Type | Required | Description |
| -------------------- | --------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `aiChatSettings` | `object` | No | AI chat configuration settings. See [AI Chat Settings](/ui-components/common-settings/ai-chat) for details. |
| `position` | `'left' \| 'right'` | No | The position of the sidebar. Defaults to `'right'`. |
| `triggerSelector` | `string` | No | The selector for the trigger element that opens the sidebar. Defaults to `'[data-inkeep-sidebar-chat-trigger]'`. |
| `minWidth` | `number` | No | The minimum width of the sidebar chat. Defaults to `250`. |
| `maxWidth` | `number` | No | The maximum width of the sidebar chat. Defaults to `600`. |
| `defaultWidth` | `number` | No | The default width of the sidebar chat. Defaults to `420`. |
| `defaultOpen` | `boolean` | No | Whether the sidebar chat is open by default. Defaults to `false`. |
| `isOpen` | `boolean` | No | Controls whether the sidebar chat is open. Set to `true` to show the sidebar, `false` to hide it. |
| `onOpenChange` | `(isOpen: boolean) => void` | No | Callback function triggered when the sidebar's open state changes. Useful for syncing state with your application. |
| `autoCloseThreshold` | `number` | No | The threshold for auto-closing the sidebar chat when resizing. When dragging below `minWidth * autoCloseThreshold`, the sidebar will auto-close. Defaults to `0.7` (70% of minimum width). |
## Examples
### Change the sidebar position
```tsx
const App = () => {
const config: InkeepSidebarChatProps = {
// ... other config
position: "left",
};
return (
);
};
```
### With AI Chat Settings
```tsx
const App = () => {
const config: InkeepSidebarChatProps = {
// ... other config
aiChatSettings: {
aiAssistantName: "Support Assistant",
introMessage: "π Hi! How can I help you today?",
},
};
return (
);
};
```
### Controlled Open State
```tsx
import { useState } from "react";
const App = () => {
const [isOpen, setIsOpen] = useState(false);
const config: InkeepSidebarChatProps = {
// ... other config
isOpen,
onOpenChange: setIsOpen,
};
return (
setIsOpen(!isOpen)}>{isOpen ? "Close" : "Open"} Sidebar
);
};
```
### Accessing Component Methods
The `aiChatSettings` config accepts a `chatFunctionsRef` prop that allows you to access the chat methods.
```tsx
const App = () => {
import type { AIChatFunctions } from "@inkeep/cxkit-types";
const chatFunctionsRef = useRef(null);
const config: InkeepSidebarChatProps = {
// ... other config
aiChatSettings: {
chatFunctionsRef,
},
};
const clearChat = () => {
chatFunctionsRef.current?.clearChat();
};
const submitMessage = () => {
chatFunctionsRef.current?.submitMessage("Hello!");
};
return (
);
};
```
| Method | Description |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `submitMessage(message?: string)` | Programmatically sends a message in chat. If message is omitted, sends the current input value. |
| `updateInputMessage(message: string)` | Updates the text in chat input field |
| `clearChat()` | Resets the chat to its initial state |
| `openForm(formSettings: FormSettings)` | Displays a form overlay in chat interface |
| `focusInput()` | Sets focus to the chat input field |
Refer to the [Form Settings](/ui-components/common-settings/actions#formconfig-reference) reference docs for more details on the available properties for the `openForm` method.
## FAQ
If you use a `webpack` build. You could come across this error.
To fix this you need to create a custom loader for your webpack configuration to disable
this behavior.
> Since webpack 5.0.0-beta.30, you're required to specify extensions when
> using imports in .mjs files or any .js files with a package.json with "type":
> "module". You can still disable the behavior with resolve.fullySpecified set
> to false if you see any related errors in your project.
We can add a new rule to our webpack configuration to disable this behavior.
```js
module.exports = {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
```
Then add this to your `webpack.config.js` file.
If you use docusaurus, you can add this to your `docusaurus.config.js` file as a `webpack` config override with plugins.
```js
/** @type {import('@docusaurus/types').Config} */
const config = {
// ...
plugins: [
() => {
return {
name: "loader",
configureWebpack() {
return {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
},
};
},
],
// ...
};
module.exports = config;
```
***
title: Embedded Chat (React)
sidebarTitle: Embedded Chat
description: Add a chat UI directly on a dedicated React powered page.
keywords: embedded chat, React chat component, chat UI, chat implementation, React integration, chat functionality, component methods, chat configuration, UI customization, chat settings, chat interface, React hooks, chat automation, component props, chat features
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
An "embedded chat" is a chat UI that is directly incorporated into a page instead of within a pop-up modal.
## Scenarios
You may want to add an embedded chat in places where you want to encourage the user to interact with the AI chat directly. For example, an embedded chat can be useful to:
* Deflect questions in your help center site
* Provide an AI chat experience if your documentation site doesn't allow third party components, like for GitBook and ReadMe.
* Create a place for sharable chat sessions
You can incorporate the embedded chat directly on an existing page like `help.domain.com` or create a dedicated one like `domain.com/ask-ai`.
## Quick Start
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Define the component
```tsx
import {
InkeepEmbeddedChat,
type InkeepEmbeddedChatProps,
} from "@inkeep/cxkit-react";
const config: InkeepEmbeddedChatProps = {
baseSettings: {
apiKey: "YOUR_API_KEY",
},
aiChatSettings: {
aiAssistantName: "Keepie",
},
};
const App = () => {
return ;
};
```
## Embedded Chat Props
This type represents the configuration for the Inkeep embedded chat widget.
| Prop | Type | Required | Description |
| ---------------------- | --------- | -------- | ----------------------------------------------------------------------------------------------------------- |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `aiChatSettings` | `object` | No | AI chat configuration settings. See [AI Chat Settings](/ui-components/common-settings/ai-chat) for details. |
| `isHidden` | `boolean` | No | Whether to hide the chat interface. Defaults to false. |
| `shouldAutoFocusInput` | `boolean` | No | Whether to auto focus the input. Defaults to true. |
## Examples
### Auto Focus Input
```tsx
const App = () => {
const config: InkeepEmbeddedChatProps = {
// ... other config
shouldAutoFocusInput: true,
};
return ;
};
```
### With AI Chat Settings
```tsx
const App = () => {
const config: InkeepEmbeddedChatProps = {
// ... other config
aiChatSettings: {
aiAssistantName: "Support Assistant",
introMessage: "π Hi! How can I help you today?",
},
};
return ;
};
```
### Accessing Component Methods
The `aiChatSettings` config accepts a `chatFunctionsRef` prop that allows you to access the chat methods.
```tsx
const App = () => {
import type { AIChatFunctions } from "@inkeep/cxkit-types";
const chatFunctionsRef = useRef(null);
const config: InkeepEmbeddedChatProps = {
// ... other config
aiChatSettings: {
chatFunctionsRef,
},
};
const clearChat = () => {
chatFunctionsRef.current?.clearChat();
};
const submitMessage = () => {
chatFunctionsRef.current?.submitMessage("Hello!");
};
return (
<>
Clear Chat
Send Message
>
);
};
```
| Method | Description |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `submitMessage(message?: string)` | Programmatically sends a message in chat. If message is omitted, sends the current input value. |
| `updateInputMessage(message: string)` | Updates the text in chat input field |
| `clearChat()` | Resets the chat to its initial state |
| `openForm(formSettings: FormSettings)` | Displays a form overlay in chat interface |
| `focusInput()` | Sets focus to the chat input field |
Refer to the [Form Settings](/ui-components/common-settings/actions#formconfig-reference) reference docs for more details on the available properties for the `openForm` method.
## FAQ
If you use a `webpack` build. You could come across this error.
To fix this you need to create a custom loader for your webpack configuration to disable
this behavior.
> Since webpack 5.0.0-beta.30, you're required to specify extensions when
> using imports in .mjs files or any .js files with a package.json with "type":
> "module". You can still disable the behavior with resolve.fullySpecified set
> to false if you see any related errors in your project.
We can add a new rule to our webpack configuration to disable this behavior.
```js
module.exports = {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
```
Then add this to your `webpack.config.js` file.
If you use docusaurus, you can add this to your `docusaurus.config.js` file as a `webpack` config override with plugins.
```js
/** @type {import('@docusaurus/types').Config} */
const config = {
// ...
plugins: [
() => {
return {
name: "loader",
configureWebpack() {
return {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
},
};
},
],
// ...
};
module.exports = config;
```
***
title: Embedded Search (React)
sidebarTitle: Embedded Search
description: Add a search UI directly on a dedicated React powered page.
keywords: embedded search, React search component, search UI, search implementation, React integration, search functionality, component methods, search configuration, UI customization, search settings, search interface, React hooks, search automation, component props, search features
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
An "embedded search" is a search UI that is directly incorporated into a page instead of within a pop-up modal.
## Quick Start
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Define the component
```tsx
import {
InkeepEmbeddedSearch,
type InkeepEmbeddedSearchProps,
} from "@inkeep/cxkit-react";
const config: InkeepEmbeddedSearchProps = {
baseSettings: {
apiKey: "YOUR_API_KEY",
},
searchSettings: {
placeholder: "Search...",
},
};
const App = () => {
return ;
};
```
## Embedded Search Props
This type represents the configuration for the Inkeep embedded search widget.
| Prop | Type | Required | Description |
| ---------------------- | --------- | -------- | -------------------------------------------------------------------------------------------------------- |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `searchSettings` | `object` | No | Search configuration settings. See [Search Settings](/ui-components/common-settings/search) for details. |
| `isHidden` | `boolean` | No | Whether to hide the search interface. Defaults to false. |
| `shouldAutoFocusInput` | `boolean` | No | Whether to auto focus the input. Defaults to true. |
## Examples
### Auto Focus Input
```tsx
const App = () => {
const config: InkeepEmbeddedSearchProps = {
// ... other config
shouldAutoFocusInput: true,
};
return ;
};
```
### With Search Settings
```tsx
const App = () => {
const config: InkeepEmbeddedSearchProps = {
// ... other config
searchSettings: {
placeholder: "Search...",
debounceTimeMs: 300,
},
};
return ;
};
```
### Accessing Component Methods
The `searchSettings` config accepts a `searchFunctionsRef` prop that allows you to access the search methods.
```tsx
const App = () => {
import type { SearchFunctions } from "@inkeep/cxkit-types";
const searchFunctionsRef = useRef(null);
const config: InkeepEmbeddedSearchProps = {
// ... other config
searchSettings: {
searchFunctionsRef,
},
};
const updateQuery = () => {
searchFunctionsRef.current?.updateQuery("Hello!");
};
const focusInput = () => {
searchFunctionsRef.current?.focusInput();
};
return (
<>
Update Query
Focus Input
>
);
};
```
| Method | Description |
| ---------------------------- | ------------------------------------------ |
| `updateQuery(query: string)` | Programmatically updates the search query. |
| `focusInput()` | Sets focus to the search input field |
## FAQ
If you use a `webpack` build. You could come across this error.
To fix this you need to create a custom loader for your webpack configuration to disable
this behavior.
> Since webpack 5.0.0-beta.30, you're required to specify extensions when
> using imports in .mjs files or any .js files with a package.json with "type":
> "module". You can still disable the behavior with resolve.fullySpecified set
> to false if you see any related errors in your project.
We can add a new rule to our webpack configuration to disable this behavior.
```js
module.exports = {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
```
Then add this to your `webpack.config.js` file.
If you use docusaurus, you can add this to your `docusaurus.config.js` file as a `webpack` config override with plugins.
```js
/** @type {import('@docusaurus/types').Config} */
const config = {
// ...
plugins: [
() => {
return {
name: "loader",
configureWebpack() {
return {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
},
};
},
],
// ...
};
module.exports = config;
```
***
title: Embedded Search and Chat (React)
sidebarTitle: Embedded Search and Chat
description: Add a toggle-able search and chat UI directly on a dedicated page
keywords: embedded search and chat, React components, combined UI, search functionality, chat interface, component integration, UI customization, React implementation, search settings, chat configuration, component methods, React hooks, UI toggling, search and chat features, component props
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
This is a toggleable chat / search UI that is directly incorporated into a page instead of within a pop-up modal.
It's a combination of the [Embedded Chat](/ui-components/js-snippet/in-page/embedded-chat) and the [Embedded Search](/ui-components/js-snippet/in-page/embedded-search) components, allowing you to toggle between chat and search.
## Quick Start
### Install the component library
```bash
npm install @inkeep/cxkit-react
```
```bash
bun add @inkeep/cxkit-react
```
```bash
pnpm add @inkeep/cxkit-react
```
```bash
yarn add @inkeep/cxkit-react
```
### Define the component
```tsx
import {
InkeepEmbeddedSearchAndChat,
type InkeepEmbeddedSearchAndChatProps,
} from "@inkeep/cxkit-react";
const config: InkeepEmbeddedSearchAndChatProps = {
baseSettings: {
apiKey: "YOUR_API_KEY",
},
aiChatSettings: {
aiAssistantName: "Keepie",
},
searchSettings: {
placeholder: "Search...",
},
};
const App = () => {
return ;
};
```
## Embedded Search Props
This type represents the configuration for the Inkeep embedded search widget.
| Prop | Type | Required | Description |
| ---------------------- | --------- | -------- | -------------------------------------------------------------------------------------------------------- |
| `baseSettings` | `object` | Yes | Core configuration settings. See [Base Settings](/ui-components/common-settings/base) for details. |
| `searchSettings` | `object` | No | Search configuration settings. See [Search Settings](/ui-components/common-settings/search) for details. |
| `isHidden` | `boolean` | No | Whether to hide the search interface. Defaults to false. |
| `shouldAutoFocusInput` | `boolean` | No | Whether to auto focus the input. Defaults to true. |
| `askAICardLabel` | `string` | No | The label for the Ask AI card in search results. Defaults to `Ask AI` or `askAILabel` if provided. |
| `askAILabel` | `string` | No | The label for the Ask AI button in the search/chat toggle. Defaults to `Ask AI`. |
| `searchLabel` | `string` | No | The label for the search button in the search/chat toggle. Defaults to `Search`. |
## Examples
### Set the default view
```tsx
const App = () => {
const config: InkeepEmbeddedSearchAndChatProps = {
// ... other config
defaultView: "chat", // or "search"
};
return ;
};
```
### Force the default view
If you want to force the default view to be the search or the chat, you can use the `forceDefaultView` property. This is useful to ensure the widget always opens the defaultView instead of last used view.
```tsx
const App = () => {
const config: InkeepEmbeddedSearchAndChatProps = {
// ... other config
forceDefaultView: true,
};
return ;
};
```
Refer to the [Search Settings](/ui-components/common-settings/search) and [Chat Settings](/ui-components/common-settings/chat) docs for more details on the available properties.
## Accessing Component Methods
Exactly how you'd do it in the [Embedded Search](/ui-components/react/in-page/embedded-search#accessing-component-methods) and [Embedded Chat](/ui-components/react/in-page/embedded-chat#accessing-component-methods) components respectively.
```tsx
const App = () => {
import type { SearchFunctions } from "@inkeep/cxkit-types";
const searchFunctionsRef = useRef(null);
const chatFunctionsRef = useRef(null);
const config: InkeepEmbeddedSearchAndChatProps = {
// ... other config
searchSettings: {
searchFunctionsRef,
},
aiChatSettings: {
chatFunctionsRef,
},
};
const updateSearchQuery = () => {
searchFunctionsRef.current?.updateQuery("Hello!");
};
const clearChat = () => {
chatFunctionsRef.current?.clearChat();
};
return (
<>
Update Query
Clear Chat
>
);
};
```
### Chat Methods
| Method | Description |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `submitMessage(message?: string)` | Programmatically sends a message in chat. If message is omitted, sends the current input value. |
| `updateInputMessage(message: string)` | Updates the text in chat input field |
| `clearChat()` | Resets the chat to its initial state |
| `openForm(formSettings: FormSettings)` | Displays a form overlay in chat interface |
| `focusInput()` | Sets focus to the chat input field |
Refer to the [Form Settings](/ui-components/common-settings/actions#formconfig-reference) reference docs for more details on the available properties for the `openForm` method.
### Search methods
| Method | Description |
| ---------------------------- | ------------------------------------------ |
| `updateQuery(query: string)` | Programmatically updates the search query. |
| `focusInput()` | Sets focus to the search input field |
### Widget methods
```typescript
type ModalViewTypes = "search" | "chat";
```
| Method | Description |
| ------------------------------- | --------------------------------------------------- |
| `setView(view: ModalViewTypes)` | Set the view of the widget to either search or chat |
## FAQ
If you use a `webpack` build. You could come across this error.
To fix this you need to create a custom loader for your webpack configuration to disable
this behavior.
> Since webpack 5.0.0-beta.30, you're required to specify extensions when
> using imports in .mjs files or any .js files with a package.json with "type":
> "module". You can still disable the behavior with resolve.fullySpecified set
> to false if you see any related errors in your project.
We can add a new rule to our webpack configuration to disable this behavior.
```js
module.exports = {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
```
Then add this to your `webpack.config.js` file.
If you use docusaurus, you can add this to your `docusaurus.config.js` file as a `webpack` config override with plugins.
```js
/** @type {import('@docusaurus/types').Config} */
const config = {
// ...
plugins: [
() => {
return {
name: "loader",
configureWebpack() {
return {
module: {
rules: [
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
};
},
};
},
],
// ...
};
module.exports = config;
```
***
title: Base Settings
sidebarTitle: Base
description: Review the basic configuration settings for our widgets.
keywords: base configuration, widget settings, core settings, user properties, privacy settings, event handling, widget customization, authentication settings, branding configuration, theme settings, analytics configuration, user identification, widget setup, configuration options
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The base configuration provides core settings for all Inkeep widgets. These settings control authentication, branding, theming, and general behavior.
## Basic Configuration
```typescript
import { type InkeepBaseSettings } from "@inkeep/cxkit-types";
// Simple configuration
const baseSettings: InkeepBaseSettings = {
// Core authentication and branding
env: "production",
apiKey: "YOUR_API_KEY",
organizationDisplayName: "Your Organization",
primaryBrandColor: "#26D6FF", // See "Theme Customization" section for advanced theming options
shouldBypassCaptcha: false, // Only enable with server-side API keys
// User identification - See "User Properties" section for all options
userProperties: {
id: "user-id",
email: "user@example.com",
name: "User Name",
},
// Optional: Analytics configuration - See "Analytics Configuration" section
privacyPreferences: {
optOutAnalyticalCookies: false,
optOutAllAnalytics: false,
},
// Optional: Color mode sync - See "Color Mode" section for advanced options
colorMode: {
sync: {
target: document.documentElement,
attributes: ["data-theme"],
isDarkMode: (attrs) => attrs["data-theme"] === "dark",
},
},
};
// Advanced configuration with enterprise features
const baseSettings: InkeepBaseSettings = {
env: process.env.NODE_ENV,
apiKey: process.env.INKEEP_API_KEY,
organizationDisplayName: "Enterprise Corp",
primaryBrandColor: "#0A2463",
aiApiBaseUrl: "https://api.enterprise.com/inkeep",
analyticsApiBaseUrl: "https://analytics.enterprise.com",
userProperties: {
id: getUserId(),
email: getUserEmail(),
name: getUserName(),
role: getUserRole(),
team: getCurrentTeam(),
},
userAuthToken: getAuthToken(),
analyticsProperties: {
url: window.location.href,
},
tags: ["enterprise", "self-hosted", getCurrentRegion()],
};
```
## Configuration Options
### Core Settings
Essential configuration options for authentication, branding, and basic widget setup. These settings form the foundation of your Inkeep integration.
Each setting serves a specific purpose in customizing the widget behavior:
| Option | Type | Required | Description |
| ------------------------- | ------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `env` | `'production' \| 'development'` | No | Environment setting (defaults to 'production') |
| `apiKey` | `string` | Yes | Your Inkeep API key |
| `organizationDisplayName` | `string` | No | Display name for your organization |
| `primaryBrandColor` | `string` | Yes | Primary brand color (hex code) |
| `aiApiBaseUrl` | `string` | No | Custom base URL for API endpoints |
| `analyticsApiBaseUrl` | `string` | No | Custom base URL for analytics endpoints |
| `shadowHost` | `HTMLElement \| null` | No | Reference to shadow DOM host element |
| `rootElement` | `HTMLElement \| null` | No | Reference to root mounting element |
| `shouldBypassCaptcha` | `boolean` | No | Bypass captcha challenge (server-side API only) |
| `tags` | `string[]` | No | Custom tags for widget identification |
| `prism` | `Prism` | No | Instance of Prism for syntax highlighting. You can add support for additional languages by importing them from `prismjs` and passing in the Prism instance |
### User Properties
Configure user-specific information that is logged to the Inkeep Analytics system. This allows you to filter chat sessions by these properties in the Inkeep Dashboard or export the analytics data using the [Analytics API](/analytics-api/add-analytics-to-any-chat).
```typescript
interface UserProperties {
/**
* The user ID.
*/
id?: string;
/**
* The user email.
*/
email?: string;
/**
* The user name.
*/
name?: string;
/**
* The user cohorts.
*/
cohorts?: string[];
}
```
| Property | Type | Required | Description |
| ---------------- | ---------------- | -------- | --------------------------------- |
| `userProperties` | `UserProperties` | No | User identification and metadata |
| `userAuthToken` | `string` | No | Authentication token for the user |
```typescript
// Basic user configuration
const baseSettings: InkeepBaseSettings = {
userProperties: {
id: "user-123",
email: "user@example.com",
name: "John Doe",
},
};
// Advanced user configuration
const baseSettings: InkeepBaseSettings = {
userProperties: {
id: "user-456",
email: "jane@enterprise.com",
name: "Jane Smith",
cohorts: ["admin", "engineering"],
},
userAuthToken: "jwt-token-here",
};
```
### Privacy Preferences
Control analytics and cookie preferences for tracking user interactions with the widget.
```typescript
interface PrivacyPreferences {
/**
* Whether to opt out of analytical cookies
*/
optOutAnalyticalCookies?: boolean;
/**
* Whether to opt out of all analytics
*/
optOutAllAnalytics?: boolean;
/**
* Whether to opt out of functional cookies
*/
optOutFunctionalCookies?: boolean;
}
```
| Property | Type | Required | Description |
| -------------------- | -------------------- | -------- | --------------------------------- |
| `privacyPreferences` | `PrivacyPreferences` | No | Privacy preferences configuration |
```typescript
// Basic analytics configuration
const baseSettings: InkeepBaseSettings = {
// ...
privacyPreferences: {
optOutAnalyticalCookies: false,
optOutAllAnalytics: false,
optOutFunctionalCookies: false,
},
};
// Privacy-focused configuration
const baseSettings: InkeepBaseSettings = {
// ...
privacyPreferences: {
optOutAnalyticalCookies: true,
optOutAllAnalytics: true,
optOutFunctionalCookies: true,
},
};
```
### Event Handling
Configure callbacks for tracking and processing widget events. This allows you to integrate with your own analytics or monitoring systems.
```typescript
type InkeepCallbackEvent = InkeepEventWithCommon & {
userProperties: UserProperties;
eventName: string;
properties: {
componentType?: any;
tags?: string[];
[key: string]: any;
};
};
```
| Property | Type | Required | Description |
| --------------------- | -------------------------------------- | -------- | ------------------------------------------ |
| `onEvent` | `(event: InkeepCallbackEvent) => void` | No | Event processing callback function |
| `analyticsProperties` | `Record` | No | Additional properties to send to analytics |
```typescript
// Basic event handling
const baseSettings: InkeepBaseSettings = {
// ...
onEvent: (event) => {
console.log("Event:", event.eventName, event.properties);
analytics.track(event.eventName, event.properties);
},
};
```
You can see the [Analytics](/ui-components/customization-guides/use-your-own-analytics) guide for more information.
### Color Mode
Synchronize the widget's appearance with your application's theme. This enables seamless dark/light mode integration.
```typescript
interface ColorMode {
// ...
sync?: {
target: HTMLElement | string;
attributes: string[];
isDarkMode: (attributes: Record) => boolean;
onChange?: (colorMode: string) => void;
};
}
```
| Property | Type | Required | Description |
| ----------- | ----------- | -------- | ----------------------------------- |
| `colorMode` | `ColorMode` | No | Theme synchronization configuration |
```typescript
// Basic color mode configuration
const baseSettings: InkeepBaseSettings = {
// ...
colorMode: {
sync: {
target: document.documentElement,
attributes: ["data-theme"],
isDarkMode: (attrs) => attrs["data-theme"] === "dark",
},
},
};
// Advanced color mode configuration
const advancedSettings: InkeepBaseSettings = {
// ...
colorMode: {
sync: {
target: document.documentElement,
attributes: ["data-theme", "class"],
isDarkMode: (attrs) => {
const preference = localStorage.getItem("theme");
return (
preference === "dark" ||
attrs["data-theme"] === "dark" ||
attrs["class"]?.includes("dark") ||
window.matchMedia("(prefers-color-scheme: dark)").matches
);
},
onChange: (mode) => {
localStorage.setItem("theme", mode);
updateThemeColor(mode);
},
},
},
};
```
### Theme Customization
Configure advanced styling and branding options for the widget. This includes colors, styles, and custom CSS.
```typescript
interface UserTheme {
// ...
syntaxHighlighter?: {
lightTheme?: any;
darkTheme?: any;
};
primaryColors?: PrimaryColors;
varsClassName?: string;
styles?: Array<{
key: string;
type: "link" | "style";
value: string;
}>;
disableLoadingDefaultFont?: boolean;
}
```
| Property | Type | Required | Description |
| -------- | ----------- | -------- | ---------------------------- |
| `theme` | `UserTheme` | No | Theme customization settings |
```typescript
// Basic theme configuration
const baseSettings: InkeepBaseSettings = {
// ...
theme: {
primaryColors: {
medium: "#26D6FF",
light: "#60a5fa",
strong: "#1d4ed8",
},
styles: [
{
key: "chat-container",
type: "style",
value: ".ikp-chat { border-radius: 8px; }",
},
],
},
};
// Advanced theme configuration
const baseSettings: InkeepBaseSettings = {
// ...
theme: {
primaryColors: {
mediumSubtle: "rgba(38, 214, 255, 0.3)",
strong: "#1d4ed8",
stronger: "#1e40af",
},
syntaxHighlighter: {
lightTheme: themes.github,
darkTheme: themes.dracula,
},
styles: [
{
key: "google-fonts",
type: "link",
value:
"https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap",
},
{
key: "custom-theme",
type: "style",
value: `
.ikp-chat {
width: min(95vw, 600px);
border-radius: clamp(8px, 2vw, 16px);
background: var(--ikp-color-background);
@media (max-width: 768px) {
width: 100vw;
border-radius: 0;
}
}
`,
},
],
},
};
```
You can see the [Theme Customization](/ui-components/customization-guides/style-components) guide for more information.
### Custom Icons
Configure custom icons for various widget elements. You can use built-in icons from popular icon libraries or provide custom SVG URLs.
```typescript
type InkeepCustomIcon =
| {
builtIn: AvailableBuiltInIcons;
}
| {
custom: string; // url of svg or png of icon
};
type CustomIconMap = {
[K in keyof CustomIcons]?: InkeepCustomIcon;
};
```
| Property | Type | Required | Description |
| ------------- | --------------- | -------- | -------------------------- |
| `customIcons` | `CustomIconMap` | No | Custom icon configurations |
```typescript
const baseSettings: InkeepBaseSettings = {
env: "production",
apiKey: "YOUR_API_KEY",
organizationDisplayName: "Enterprise Corp",
primaryBrandColor: "#26D6FF",
customIcons: {
search: {
builtIn: "LuBookOpen",
},
close: {
custom: "https://assets.enterprise.com/icons/close.svg",
},
chat: {
builtIn: "LuMessageSquare",
},
},
};
```
You can see the [Custom Icons](/ui-components/customization-guides/style-components#available-icons) guide for more information.
### URL Parameters
Configure URL parameters that will be automatically appended to all links within the widget. This is useful for tracking and maintaining context across page navigations.
```typescript
type URLParametersConfig = {
urlQueryParamsToAppend?: {
[key: string]: string | number | boolean;
};
};
```
| Property | Type | Required | Description |
| ------------------------ | -------- | -------- | --------------------------------- |
| `urlQueryParamsToAppend` | `object` | No | URL parameters to append to links |
```typescript
// Basic URL parameters configuration
const baseSettings: InkeepBaseSettings = {
urlQueryParamsToAppend: {
utm_source: "widget",
user_id: "123",
},
};
// Advanced URL parameters configuration
const baseSettings: InkeepBaseSettings = {
urlQueryParamsToAppend: {
utm_source: window.location.hostname,
utm_medium: "widget",
user_id: getUserId(),
team_id: getTeamId(),
features: getEnabledFeatures().join(","),
session: getSessionId(),
},
};
```
### Source Transformation
See the [Source Transformation](/ui-components/customization-guides/source-transformation) guide for more information on how to customize how source information is displayed in the search and chat results.
### Custom Filters
See the [Search and Chat Filters](/ui-components/customization-guides/filters) guide for more information on how to use filters to dynamically filter search and chat results.
```typescript
export interface SearchAndChatFilters {
attributes?: {
[key: string]: any;
};
}
```
***
title: Search Settings
sidebarTitle: Search
description: Customize search-related settings for the Inkeep widgets.
keywords: search configuration, search settings, search customization, search behavior, search interface, search results, search tabs, search events, search functionality, search appearance, search parameters, search options, search implementation, search features
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The search configuration provides settings for all search-related components, including search behavior, appearance, and functionality. These settings allow you to customize how users interact with the search interface, how results are displayed, and how the search behavior works.
## Basic Configuration
```typescript
// Basic search configuration
const searchSettings: InkeepSearchSettings = {
placeholder: "Search documentation...",
defaultQuery: "",
maxResults: 40,
debounceTimeMs: 300,
shouldOpenLinksInNewTab: true,
};
// Advanced configuration with analytics and customization
const searchSettings: InkeepSearchSettings = {
placeholder: "Search our docs, GitHub, and community...",
defaultQuery: new URLSearchParams(window.location.search).get("q") || "",
maxResults: 50,
debounceTimeMs: 250,
shouldOpenLinksInNewTab: true,
searchQueryParamKey: "search",
onQueryChange: (query) => {
analytics.track("search_query", { query });
updateURLParams(query);
},
tabs: ["Publications", ["GitHub", { isAlwaysVisible: true }], "Forums"],
};
```
## Core Settings
Configure basic search behavior and appearance:
| Option | Type | Default | Description |
| ------------------------- | ------------------------------ | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `placeholder` | `string` | `'Search anything...'` (desktop), `'Search'` (mobile) | Text shown in empty search input |
| `defaultQuery` | `string` | `''` | Initial search query on load |
| `maxResults` | `number` | `40` | Maximum number of results to show |
| `debounceTimeMs` | `number` | `0` | Milliseconds to wait before searching |
| `shouldOpenLinksInNewTab` | `boolean` | `false` | Open results in new tab |
| `searchQueryParamKey` | `string` | `null` | URL parameter for search query; gets appended to the URL when a result is clicked |
| `view` | `"single-pane" \| "dual-pane"` | `"single-pane"` | Whether to render the search results in a single list or a two pane view with a list of results on the left and a preview of the content on the right |
```typescript
const searchSettings: InkeepSearchSettings = {
// ...
placeholder: "Search documentation...",
defaultQuery: "",
maxResults: 40,
debounceTimeMs: 300,
shouldOpenLinksInNewTab: true,
searchQueryParamKey: "q",
};
```
## Search Tabs
Configure result categorization and organization:
```typescript
interface SearchTab {
[0]: string;
[1]: {
isAlwaysVisible?: boolean;
};
}
```
| Option | Type | Required | Description |
| ------ | ------------------------- | -------- | -------------------------- |
| `tabs` | `(string \| SearchTab)[]` | No | Tabs to display in results |
The tabs feature supports several configuration patterns:
```typescript
const searchSettings: InkeepSearchSettings = {
// Basic tabs
tabs: ["All", "Publications", "GitHub", "Forums"],
// With always visible option
tabs: [
"All",
"Publications",
["GitHub", { isAlwaysVisible: true }],
"Forums",
],
// Hide "All" tab, show only Publications and GitHub
tabs: ["Publications", "GitHub"],
// No tabs (just show all results)
tabs: [],
};
```
Default tabs if none provided:
* `All`
* `Publications`
* `PDFs`
* `GitHub`
* `Forums`
* `Discord`
* `Slack`
* `StackOverflow`
> The tabs are displayed in the order they are provided in the `tabs` array.
## Event Handling
Configure search event callbacks:
| Option | Type | Required | Description |
| --------------- | ------------------------- | -------- | -------------------------------- |
| `onQueryChange` | `(query: string) => void` | No | Called when search query changes |
```typescript
const searchSettings: InkeepSearchSettings = {
// ...
onQueryChange: (query) => {
// Maybe Update URL
const url = new URL(window.location.href);
url.searchParams.set("q", query);
window.history.replaceState({}, "", url);
},
};
```
***
title: AI Assistant Settings
sidebarTitle: AI Chat
description: Customize the chat experience for the Inkeep widgets.
keywords: AI chat settings, chat customization, AI assistant configuration, chat interface, chat features, example questions, chat sharing, chat disclaimers, help actions, chat appearance, chat personalization, chat UI, chat tools, chat workflows, chat integration, chat experience
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Settings for Inkeep's AI-powered chat features, including AI assistant's personality, workflows, tools, and UI customization.
## Basic Configuration
```typescript
// Basic chat configuration
const aiChatSettings: InkeepAIChatSettings = {
// ...
aiAssistantName: 'Keepie',
chatSubjectName: 'Inkeep',
placeholder: 'Ask me anything about our API...',
introMessage: 'π Hi! I'm here to help you with technical questions...',
isShareButtonVisible: true,
isCopyChatButtonVisible: true
}
// Advanced configuration with personalization
const aiChatSettings: InkeepAIChatSettings = {
// ...
aiAssistantName: 'Atlas Assistant',
chatSubjectName: 'MongoDB Atlas',
placeholder: 'How do I get started?',
introMessage: `How can I help you today?`,
aiAssistantAvatar: '/assets/assistant-light.png',
userAvatar: userProfile.avatarUrl,
exampleQuestions: [
'How do I connect to my cluster?',
'What are the instance sizes?',
'How do I enable backups?'
],
disclaimerSettings: {
isEnabled: true,
label: 'AI Assistant',
tooltip: 'Responses are AI-generated and may require verification.'
},
toolbarButtonLabels: {
clear: 'Start Over',
share: 'Share Chat',
getHelp: 'Get Help',
stop: 'Stop',
copyChat: 'Copy Chat'
}
}
```
## AI Assistant Settings
Configure the AI assistant's personality and appearance:
| Option | Type | Required | Description |
| ------------------- | ------------------------------------------- | -------- | --------------------------------------------------- |
| `aiAssistantName` | `string` | No | Display name for the AI assistant |
| `chatSubjectName` | `string` | No | Topic/product the assistant specializes in |
| `placeholder` | `string` | No | Input field placeholder text |
| `introMessage` | `string` | No | Welcome message (supports markdown) |
| `aiAssistantAvatar` | `string \| { light: string, dark: string }` | No | URL for AI assistant's avatar (40x40px recommended) |
| `userAvatar` | `string` | No | URL for user's avatar image |
```typescript
const aiChatSettings: InkeepAIChatSettings = {
// ...
aiAssistantName: "Atlas Assistant",
chatSubjectName: "MongoDB Atlas",
placeholder: "Ask me about MongoDB Atlas...",
introMessage: `Welcome back ${userName}! How can I help you today?`,
aiAssistantAvatar: {
light: "/assets/assistant-light.png",
dark: "/assets/assistant-dark.png",
},
userAvatar: userProfile.avatarUrl,
};
```
## Example Questions
Configure suggested questions for users to quickly start conversations:
| Option | Type | Required | Description |
| ----------------------------------- | ---------- | -------- | ------------------------------------------------------------------------------ |
| `exampleQuestions` | `string[]` | No | Pre-defined questions for quick access |
| `exampleQuestionsLabel` | `string` | No | Custom heading for example questions section |
| `isFirstExampleQuestionHighlighted` | `boolean` | No | Emphasize the first question; useful for highlighting the most common question |
```typescript
const aiChatSettings: InkeepAIChatSettings = {
// ...
exampleQuestions: [
"How do I connect to my cluster?",
"What are the instance sizes?",
"How do I enable backups?",
],
exampleQuestionsLabel: "Popular Questions",
isFirstExampleQuestionHighlighted: true,
};
```
## Chat Features
Control chat sharing and interaction options:
| Option | Type | Required | Description |
| ------------------------- | --------- | -------- | --------------------------------- |
| `isShareButtonVisible` | `boolean` | No | Enable chat sharing functionality |
| `shareChatUrlBasePath` | `string` | No | Base URL for shared chats |
| `isCopyChatButtonVisible` | `boolean` | No | Show copy chat button |
| `shouldOpenLinksInNewTab` | `boolean` | No | Open links in new tab |
| `isViewOnly` | `boolean` | No | Prevent sending new messages |
| `chatId` | `string` | No | Load specific chat session |
```typescript
const aiChatSettings: InkeepAIChatSettings = {
// ...
isShareButtonVisible: true,
shareChatUrlBasePath: "/shared-chats",
isCopyChatButtonVisible: true,
shouldOpenLinksInNewTab: true,
};
```
## Disclaimer Settings
Configure AI usage disclaimers:
| Option | Type | Required | Description |
| -------------------- | -------------------------- | -------- | --------------------------------- |
| `disclaimerSettings` | `AIChatDisclaimerSettings` | No | AI usage disclaimer configuration |
```typescript
const aiChatSettings: InkeepAIChatSettings = {
// ...
disclaimerSettings: {
isEnabled: true,
label: "AI Assistant",
tooltip: "Responses are AI-generated and may require verification.",
},
};
```
## Help Actions
You can display buttons or links that lead to your desired support channels at the bottom right of the chat experience:
These can be used to open a link, trigger a create ticket form, or transfer to live chat.
| Option | Type | Required | Description |
| ---------------- | ----------------- | -------- | --------------------------------------------------------------------------------------------------------- |
| `getHelpOptions` | `GetHelpOption[]` | No | Configuration for the possible support channels and the actions that they trigger when clicked by a user. |
### Open Link
You can open a link by using the `open_link` action.
```typescript
const aiChatSettings: InkeepAIChatSettings = {
// ...
getHelpOptions: [
{
icon: { builtIn: "FaEnvelope" },
name: "Contact Us",
isPinnedToToolbar: true,
action: {
type: "open_link",
url: "mailto:support@example.com?subject=Support Request",
},
},
{
icon: { builtIn: "FaDiscord" },
name: "Ask on Discord",
action: {
type: "open_link",
url: "https://discord.gg/your-discord-invite",
},
},
],
};
```
### Open Form
You can also open a support form by using the `open_form` action. More details on how to create a form can be found on the [form settings page](/ui-components/customization-guides/embed-form-in-chat).
```typescript
const aiChatSettings: InkeepAIChatSettings = {
// ...
getHelpOptions: [
{
icon: { builtIn: "FaDiscord" },
name: "Create Support Ticket",
action: {
type: "open_form",
formSettings: {
// ... form settings
},
},
},
],
};
```
### Invoke Callback
Use a javascript callback to trigger any other action like opening your own support form or opening your live chat.
```typescript
const aiChatSettings: InkeepAIChatSettings = {
// ...
getHelpOptions: [
{
icon: { builtIn: "FaEnvelope" },
name: "Contact Us",
type: "invoke_callback",
callback: ({ conversation }) => {
console.log("Chat conversation:", conversation);
// Handle callback
},
shouldCloseModal: true, // Optional: controls whether to close the modal after callback
},
],
};
```
See [Actions](/ui-components/common-settings/actions#support-actions) for complete examples.
If you want to pin a certain getHelpOption to always display as a standalone button in the toolbar, set `isPinnedToToolbar` to `true`.
## Tools
Configure custom tools for the AI assistant:
| Option | Type | Required | Description |
| ------------ | --------------------------------------------------------------------------------------------------------- | -------- | -------------------------------------------------------- |
| `getTools` | `getTools: (ctx: ToolContext) => ToolFunction[]` | No | Custom tools for the AI assistant |
| `onToolCall` | `(toolCall: FunctionToolCallArgumentsDoneEvent, ctx: ToolContext) => void \| unknown \| Promise` | No | Callback function triggered whenever the AI uses a tool. |
See [Tools](/ui-components/tools/overview) for more details on tools
## Tool Bar Button Labels
Customize the buttons displayed in the bottom right of the AI chat:
| Option | Type | Required | Description |
| --------------------- | --------------------------- | -------- | ------------------------ |
| `toolbarButtonLabels` | `AIChatToolbarButtonLabels` | No | Custom button label text |
```typescript
const aiChatSettings: InkeepAIChatSettings = {
// ...
toolbarButtonLabels: {
clear: "Start Over",
share: "Share Chat",
getHelp: "Get Help",
stop: "Stop",
copyChat: "Copy Chat",
},
};
```
## Prompts
Provide additional context or instructions for the AI assistant. `prompts` apply to the entire chat session, not just the first message.
| Option | Type | Required | Description |
| --------- | ---------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `prompts` | `string[]` | No | System-level instructions that guide the AI's behavior and responses. Use these to define the assistant's personality, knowledge boundaries, and response style. |
### Add user context
Contextual prompts can be used to provide additional details about the user that might be helpful information for the AI assistant to consider while answering.
Often, this is used to dynamically provide information about the user that can be inferred by their account (if authenticated to your application) or based on the page they are currently viewing.
**Examples**
For providing context based on the user:
```
`The user is currently viewing documentation page ${url}.`
```
```
"The user is new to the platform." // (for user life cycle stages)
```
For providing context based on a product:
```
`The question is about ${product}.` // (for teams with multiple products)
```
```
"The user is using the cloud hosted version of the application." // (for teams with multiple versions or pricing tiers)
```
### Add custom rules
Prompts can be used to customize or guide the behavior of the AI assistant using instructions in natural langauge.
By default, the AI assistanth has sensible defaults for staying on topic, brand-protection, faithfulness to the source content, and other guardrails.
However, prompts can be useful to further customizing tone, having the assistant ask more clarifying questions, adding topics it should refuse to answer, or otherwise customizing the exact experience to your scenario.
See [Rules & Prompts](/projects/rules-and-prompts) for our recommendations and examples around how to prompt LLMs.
***
title: Actions
description: Use actions to add custom behavior to the UI Components.
keywords: UI actions, custom behavior, action types, URL actions, callback actions, form actions, support actions, action implementation, UI interaction, form handling, action configuration, support integration, action examples, UI customization
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Actions allows you to define interactive flows in your chat interface, such as opening a link, opening an embeded form, or executing custom JavaScript. These actions can be triggered by users, when they click on buttons, or the AI assistant.
## Action Types
### Open URL Action
Opens a URL in a new tab or the current window:
```typescript
const urlAction: OpenUrlAction = {
type: "open_link",
url: "https://example.com/docs",
};
```
### Invoke Callback Action
Executes a callback function with optional modal control:
```typescript
const callbackAction: InvokeCallbackAction = {
type: "invoke_callback",
callback: ({ conversation }) => {
console.log("Chat conversation:", conversation);
// Handle callback
},
shouldCloseModal: true, // Optional: controls whether to close the modal after callback
};
```
### Open Form Action
Opens a form dialog with configurable fields and success view:
```typescript
const formAction: OpenFormAction = {
type: "open_form",
formSettings: {
heading: "Contact Support",
description: "Please fill out the form below",
fields: [
{
name: "email",
label: "Email Address",
inputType: "email",
isRequired: true,
placeholder: "Enter your email",
},
{
name: "description",
label: "Issue Description",
inputType: "textarea",
isRequired: true,
placeholder: "Describe your issue",
},
{
name: "priority",
label: "Priority Level",
inputType: "select",
items: [
{ label: "Low", value: "low" },
{ label: "Medium", value: "medium" },
{ label: "High", value: "high" },
],
isRequired: true,
},
],
buttons: {
submit: {
label: "Submit Ticket",
onSubmit: async ({ values, conversation }) => {
// Handle form submission
await submitTicket(values);
},
},
close: {
action: "return_to_chat",
},
},
successView: {
heading: "Ticket Submitted",
message: "We will get back to you shortly",
doneButton: {
label: "Back to Chat",
action: "return_to_chat",
},
},
},
};
```
See [Form Settings](/ui-components/customization-guides/embed-form-in-chat) for a full reference on what can be configured in the form.
## Support Action Examples
Below are some examples of common actions used to hand off to your support channels.
### Open Support Page
```typescript
const supportPageAction = {
icon: { builtIn: "FaQuestionCircle" },
name: "Contact Support",
action: {
type: "open_link",
url: "/support",
},
};
```
### Email Support
```typescript
const emailSupportAction = {
icon: { builtIn: "FaEnvelope" },
name: "Email",
action: {
type: "open_link",
url: "mailto:support@example.com?subject=Support Request",
},
};
```
### Open Support Ticket Form
```typescript
const contactFormAction = {
icon: { builtIn: "LuUsers" },
name: "Create Support Ticket",
action: {
type: "open_form",
formSettings: {
heading: "Contact Support",
description: "We'll help you resolve your issue.",
fields: [
{
label: "Email",
name: "email",
inputType: "email",
isRequired: true,
},
{
label: "Description",
name: "description",
inputType: "textarea",
isRequired: true,
},
{
_type: "include_chat_session",
label: "Include chat history",
defaultValue: true,
name: "include_chat_session",
},
],
buttons: {
submit: {
label: "Submit Request",
onSubmit: async ({ values, conversation }) => {
// Submit support request
await submitSupportRequest(values);
},
},
},
successView: {
heading: "Request Submitted",
message: "We'll respond to your inquiry shortly.",
doneButton: {
label: "Continue Chatting",
action: "return_to_chat",
},
},
},
},
};
```
### Transfer to Live Chat
```typescript
const liveChatAction = {
icon: { builtIn: "FaComment" },
name: "Talk to support",
action: {
type: "invoke_callback",
callback: ({ conversation }) => {
// Switch to live chat. Implementation depends on your live chat provider.
switchToLiveChat(conversation);
},
},
};
```
### Slack Community
```typescript
const SlackAction = {
icon: { builtIn: "FaSlack" },
name: "Slack Community",
action: {
type: "open_link",
url: "https://join.slack.com/t/your-workspace/shared_invite/your-invite-code",
},
};
```
### Discord Community
```typescript
const discordAction = {
icon: { builtIn: "FaDiscord" },
name: "Discord Community",
action: {
type: "open_link",
url: "https://discord.gg/your-invite-code",
},
};
```
***
title: Style Components
description: Customize the appearance of Inkeep's UI components.
keywords: UI styling, component customization, visual customization, theme configuration, CSS customization, design customization, UI appearance, style configuration, component theming, visual design, UI customization, component styling
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The style configuration provides comprehensive settings for customizing the appearance of Inkeep widgets. This includes theming, typography, spacing, and component-specific styles.
## Theme Configuration
The theme configuration is defined through the `UserTheme` interface which extends `Partial`. This allows for deep customization of the widget's appearance.
```typescript
import { type InkeepBaseSettings } from "@inkeep/cxkit-types";
const baseSettings: InkeepBaseSettings = {
theme: {
// Basic color customization
primaryColors: {
primary: "#26D6FF",
secondary: "#6366F1",
},
// Syntax highlighter themes
syntaxHighlighter: {
lightTheme: themes.github,
darkTheme: themes.dracula,
},
// Custom styles injection
styles: [
{
key: "google-fonts",
type: "link",
value:
"https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap",
},
{
key: "custom-theme",
type: "style",
value: `
.ikp-ai-chat-message {
border-radius: 8px;
padding: 12px;
}
[data-theme='dark'] .ikp-ai-chat-message {
background: #2D3748;
}
`,
},
],
// CSS variables container class name
varsClassName: "ikp-variables",
// Disable loading the default font for the widgets
disableLoadingDefaultFont: true,
},
};
```
### Theme Properties
#### Primary Colors
The `primaryColors` property allows you to define the color variations used throughout the widget. It accepts the following color options:
```typescript
primaryColors: {
textBold?: string // Bold text color
textSubtle?: string // Subtle text color
lighter?: string // Lightest shade
light?: string // Light shade
lightSubtle?: string // Subtle light shade
medium?: string // Medium shade
mediumSubtle?: string // Subtle medium shade
strong?: string // Strong shade
stronger?: string // Stronger shade
textColorOnPrimary?: string // Text color on primary background
}
```
All colors should be provided as valid CSS color values (hex, rgb, hsl, etc). Each property is optional, allowing you to customize only the specific color variations you need.
#### Syntax Highlighter Theme
The `syntaxHighlighter` property lets you configure different themes for code blocks in light and dark modes.
By default, the Prism syntax highlighting theme we use is [oneLight](https://github.com/FormidableLabs/prism-react-renderer/blob/master/packages/prism-react-renderer/src/themes/oneLight.ts) in light mode and [vsDark](https://github.com/FormidableLabs/prism-react-renderer/blob/master/packages/prism-react-renderer/src/themes/vsDark.ts) in dark mode. To use a different theme, you can provide it in the theme.syntaxHighlighter prop.
```typescript
syntaxHighlighter: {
lightTheme: themes.github, // Theme for light mode
darkTheme: themes.dracula // Theme for dark mode
}
```
You can use published Prism themes or [create your own](https://github.com/PrismJS/prism-themes).
#### Custom Styles
The `styles` property allows injection of custom styles through two methods:
1. External Resources (type: 'link'):
```typescript
{
key: 'google-fonts',
type: 'link',
value: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap'
}
```
2. Inline CSS (type: 'style'):
```typescript
{
key: 'custom-theme',
type: 'style',
value: `
.ikp-ai-chat-message {
border-radius: 8px;
padding: 12px;
}
`
}
```
Each style entry requires:
* `key`: A unique identifier to prevent duplicates and enable updates
* `type`: Either 'link' for external resources or 'style' for inline CSS
* `value`: The style content (URL for links or CSS code for styles)
#### Variables Class Name
The `varsClassName` property specifies the class name for the container that holds CSS variables:
```typescript
varsClassName: "ikp-variables"; // Default value
```
This class is added to a wrapper div that provides theming context.
## Color Mode Configuration
The color mode configuration allows you to control how the widget handles light and dark modes. This is configured through the `colorMode` property in the base settings:
```typescript
const baseSettings: InkeepBaseSettings = {
colorMode: {
// Force a specific color mode
forcedColorMode?: string,
// Enable system color mode detection
enableSystem?: boolean,
// Sync with external element
sync?: {
// Element to watch for color mode changes
target: HTMLElement | string,
// Attributes to monitor
attributes: string[],
// Function to determine dark mode
isDarkMode: (attributes: Record) => boolean,
// Optional callback for color mode changes
onChange?: (colorMode: string) => void
}
}
}
```
### Color Mode Properties
#### Forced Color Mode
Use `forcedColorMode` to explicitly set the color mode for the current page:
```typescript
colorMode: {
forcedColorMode: "dark"; // Forces dark mode
}
```
#### System Color Mode
Enable `enableSystem` to automatically switch between dark and light modes based on the user's system preferences:
```typescript
colorMode: {
enableSystem: true; // Follows system preference
}
```
#### Color Mode Sync
The `sync` property allows you to synchronize the widget's color mode with your application's theme:
```typescript
colorMode: {
sync: {
// Watch the document root for theme changes
target: document.documentElement,
// Monitor the data-theme attribute
attributes: ['data-theme'],
// Determine dark mode based on attribute value
isDarkMode: (attrs) => attrs['data-theme'] === 'dark',
// Optional: Handle color mode changes
onChange: (mode) => console.log(`Color mode changed to: ${mode}`)
}
}
```
Common sync configurations:
1. **Data Attribute Sync**:
```typescript
{
target: document.documentElement,
attributes: ['data-theme'],
isDarkMode: (attrs) => attrs['data-theme'] === 'dark'
}
```
2. **Class-based Sync**:
```typescript
{
target: document.documentElement,
attributes: ['class'],
isDarkMode: (attrs) => attrs['class']?.includes('dark-mode')
}
```
## Using CSS Variables
Inkeep provides a set of CSS variables that you can use to customize the widget's appearance. These variables are prefixed with `--ikp-` and are available within the scope of the widget.
### Basic Usage
You can use Inkeep CSS variables within your stylesheets to customize elements. For example:
```css
.ikp-chat-button__button {
background: var(--ikp-colors-inkeep-primary-medium);
}
```
### Dark Mode Styling
To apply specific styles for dark mode, use the `[data-theme='dark']` attribute selector:
```css
[data-theme="dark"] .ikp-chat-button__button {
background: #353e52;
}
```
## Style Recipes
Here are some common style recipes to help you get started with customizing the Inkeep components. These styles can be added to your custom CSS file or injected directly into the widget using the `styles` property in the `theme` configuration.
### Responsive Search Bar
When space is tight on small screens, this will turn your full search bar into a simple search icon β perfect for navigation bars.
```css
@media (max-width: 33em) {
.ikp-search-bar__button {
padding-inline: 7px;
}
.ikp-search-bar__text {
display: none;
}
.ikp-search-bar__kbd-wrapper {
display: none;
}
}
```
### Emphasized search bar
Make your search bar stand out and feel more noticeable β perfect for when search is central to your app.
```css
.ikp-search-bar__button {
box-shadow: 0px 2px 4px rgba(23, 23, 23, 0.1);
height: 3rem;
padding-inline: 1rem;
}
.ikp-search-bar__kbd-wrapper {
border-width: 1px;
border-radius: 0.375rem;
padding: 0.25rem 0.5rem;
border-bottom-width: 3px;
}
```
### Non-floating chat button
Places the chat button directly in your app's layout β like a navbar or sidebar β instead of fixed and floating.
```css
/* make the chat button not floating */
.ikp-chat-button__container {
position: relative;
bottom: unset;
right: unset;
}
/* make the button smaller / more subtle */
.ikp-chat-button__button {
background: transparent;
border-width: 1px;
color: var(--ikp-color-gray-800);
border-radius: 6px;
box-shadow: none;
padding: 6px 12px;
font-size: 14px;
flex-direction: row-reverse;
}
.ikp-chat-button__button:hover {
transform: none !important;
background: var(--ikp-color-gray-50);
}
.ikp-chat-button__avatar-content {
margin-right: 6px !important;
margin-left: 0 !important;
}
.ikp-chat-button__avatar-content > svg {
width: 16px;
height: 16px;
--start-color: var(--ikp-color-inkeep-expanded-primary-300) !important;
--end-color: var(--ikp-color-inkeep-expanded-primary-700) !important;
}
[data-theme="dark"] .ikp-chat-button__button {
color: var(--ikp-color-gray-dark-50);
background: transparent;
}
[data-theme="dark"] .ikp-chat-button__button:hover {
background: var(--ikp-color-white-alpha-200);
}
[data-theme="dark"] .ikp-chat-button__avatar-content > svg {
--start-color: var(--ikp-color-inkeep-expanded-primary-50) !important;
--end-color: var(--ikp-color-inkeep-expanded-primary-300) !important;
}
```
### Changing the chat button background color
```css
.ikp-chat-button__button {
background: var(--ikp-color-inkeep-expanded-primary-600);
}
/* For dark mode */
[data-theme="dark"] .ikp-chat-button__button {
background: var(--ikp-color-inkeep-expanded-primary-400);
}
```
### Subtle sources
Make the sources less prominent and in row format.
```css
.ikp-ai-chat-message-sources__list {
flex-direction: row;
gap: 0.5rem;
flex-wrap: wrap;
}
.ikp-ai-chat-message-source-item {
padding: 0rem 0.5rem;
width: auto;
display: flex;
height: 1.5rem;
border-radius: 6px;
}
.ikp-ai-chat-message-source-item__breadcrumbs {
display: none;
}
.ikp-ai-chat-message-source-item__title {
font-size: 12px;
}
.ikp-ai-chat-message-source-item__indicator {
display: none !important;
}
.ikp-ai-chat-message-source-item__tag {
display: none;
}
.ikp-ai-chat-message-source-item__icon {
flex-shrink: 0;
font-size: 12px;
}
```
### Chat Bubble
Here is an example of how you can create a chat bubble like experience (similar to Zendesk or Intercom).
#### Chat bubble without a header
In this example, when the chat bubble is open, the chat button turns into a close button.
```tsx
'use client'
import { InkeepEmbeddedChat, type InkeepEmbeddedChatProps } from '@inkeep/cxkit-react'
import { useState } from 'react'
import { Sparkles, X } from 'lucide-react'
// these can be moved to a separate css file
const styles = `
.chat-button {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 10;
background-color: #191919;
color: white;
border: none;
padding: 12px;
border-radius: 1000px;
box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px,
rgba(0, 0, 0, 0) 0px 0px 0px 0px,
rgba(0, 0, 0, 0.25) 0px 25px 50px -12px;
cursor: pointer;
font-size: 16px;
font-weight: 500;
}
.chat-button-text {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 8px;
padding: 0 8px;
}
.chat-wrapper {
position: fixed;
bottom: 84px;
right: 20px;
height: 100%;
z-index: 10;
width: 400px;
max-height: min(500px, calc(100% - 104px));
}
/* mobile styles */
@media (max-width: 450px) {
.chat-wrapper {
width: 100vw;
max-height: 100vh;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
border-radius: 0px;
}
}
.chat-wrapper-close-button {
position: absolute;
top: 10px;
right: 10px;
z-index: 10;
cursor: pointer;
color: gray;
background-color: #ffffffb8;
border-radius: 8px;
padding: 4px;
display: none;
@media (max-width: 450px){
display: block;
}
}
`
const styleOverrides = `
.ikp-ai-chat-wrapper{
max-height: 100% !important;
height: 100%;
}
`
const chatProps: InkeepEmbeddedChatProps = {
baseSettings: {
// rest of the base settings
theme: {
styles: [
{
key: 'ikp-style-overrides',
type: 'style',
value: styleOverrides,
},
],
},
},
// optional ai chat settings
}
export function ChatBubble() {
const [isHidden, setIsHidden] = useState(true)
const toggleChat = () => setIsHidden((h) => !h)
return (
<>
{/* you can move the styles to a separate css file instead of using an inline style tag */}
{isHidden ? (
Ask AI
) : (
)}
>
)
}
```
#### Chat bubble with header
In this example, the chat bubble includes a header with a close button and when the chat bubble is open, the chat button trigger is hidden
```tsx
'use client'
import { InkeepEmbeddedChat, type InkeepEmbeddedChatProps } from '@inkeep/cxkit-react'
import { useState } from 'react'
import { Sparkles, X } from 'lucide-react'
// these can be moved to a separate css file
const styles = `
.chat-button {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 10;
background-color: #191919;
color: white;
border: none;
padding: 12px;
border-radius: 1000px;
box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px,
rgba(0, 0, 0, 0) 0px 0px 0px 0px,
rgba(0, 0, 0, 0.25) 0px 25px 50px -12px;
cursor: pointer;
font-size: 16px;
font-weight: 500;
}
.chat-button-text {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 8px;
padding: 0 8px;
}
.chat-wrapper {
position: fixed;
bottom: 20px;
right: 20px;
height: 100%;
z-index: 10;
width: 400px;
max-height: min(500px, calc(100% - 40px));
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
border-radius: 6px;
}
/* mobile styles */
@media (max-width: 450px) {
.chat-wrapper {
width: 100vw;
max-height: 100vh;
height: 100%;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
border-radius: 0px;
}
}
.chat-wrapper-header {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 8px 16px 8px 20px;
background-color: white;
color: gray;
position: relative;
font-size: 14px;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
}
[data-theme="dark"] .chat-wrapper-header{
background-color: #191919;
}
.chat-wrapper-header::after{
content: '';
position: absolute;
left: 0;
background: linear-gradient(to bottom, white, transparent);
width: 100%;
bottom: 0px;
height: 12px;
transform: translateY(100%);
z-index: 1;
pointer-events: none;
}
[data-theme="dark"] .chat-wrapper-header::after{
background: linear-gradient(to bottom, #191919, transparent);
}
.chat-wrapper-close-button {
cursor: pointer;
color: gray;
padding: 4px;
background-color: transparent;
}
`
const styleOverrides = `
.ikp-ai-chat-wrapper{
max-height: 100% !important;
height: calc(100% - 40px) !important;
box-shadow: none !important;
}
`
const chatProps: InkeepEmbeddedChatProps = {
baseSettings: {
// rest of the base settings
theme: {
styles: [
{
key: 'ikp-style-overrides',
type: 'style',
value: styleOverrides,
},
],
},
},
// optional ai chat settings
}
export function ChatBubble() {
const [isHidden, setIsHidden] = useState(true)
const toggleChat = () => setIsHidden((h) => !h)
return (
<>
{/* you can move the styles to a separate css file */}
{isHidden ? (
Ask AI
) : null}
>
)
}
```
## Customizing Icons
### AI Assistant Avatar
The AI assistant avatar can be customized through the `aiChatSettings` using the `aiAssistantAvatar` property:
it's either a string URL or an object to specify light and dark mode avatars:
```typescript
aiAssistantAvatar: {
light: string;
dark?: string;
}
```
### User Avatar
The user avatar can be customized using the `userAvatar` property in the `aiChatSettings`.
```typescript
import { type InkeepAIChatSettings } from "@inkeep/cxkit-react";
export const aiChatSettings: InkeepAIChatSettings = {
aiAssistantAvatar: "http://example.com/assistant-avatar.png",
userAvatar: "http://example.com/user-avatar.png",
// ...rest of aiChatSettings
};
```
### Custom Icons
You can customize various icons throughout the widget by providing a `customIcons` dictionary in the `baseSettings`. Each icon can be either a built-in icon or a custom SVG/image.
#### Available Icons
| Icon Name | Description |
| ------------------- | -------------------------------------------------------------------------------------------- |
| search | Search icon in search bar |
| thumbsUp | Thumbs up icon |
| thumbsDown | Thumbs down icon |
| messageCopy | Copy message icon |
| codeCopy | Copy code icon in code header |
| openLinkInNewTab | Used on hover in chat citations and search results (when `shouldOpenLinksInNewTab` is true) |
| openLinkInSameTab | Used on hover in chat citations and search results (when `shouldOpenLinksInNewTab` is false) |
| breadcrumbSeparator | Breadcrumb separator icon |
| switchToSearch | Switch to search icon |
| switchToChat | Switch to chat icon |
| chatSubmit | Chat submit icon |
| close | Close icon |
| info | Info icon next to the disclaimer and chat mode toggle |
| command | Command icon in search bar |
#### Example Configuration
```typescript
import { type InkeepBaseSettings } from "@inkeep/cxkit-react";
export const baseSettings: InkeepBaseSettings = {
customIcons: {
// Using a built-in icon
search: {
builtIn: "IoSearch",
},
// Using custom SVG/image URLs
thumbsUp: {
custom: "/path/to/thumbs-up.svg",
},
thumbsDown: {
custom: "/path/to/thumbs-down.svg",
},
messageCopy: {
custom: "/path/to/message-copy.svg",
},
codeCopy: {
custom: "/path/to/code-copy.svg",
},
openLinkInNewTab: {
custom: "path/to/open-link-in-new-tab.svg",
},
openLinkInSameTab: {
custom: "path/to/open-link-in-same-tab.svg",
},
breadcrumbSeparator: {
custom: "path/to/breadcrumb-separator.svg",
},
switchToSearch: {
custom: "/path/to/switch-to-search.svg",
},
switchToChat: {
custom: "/path/to/switch-to-chat.svg",
},
chatSubmit: {
custom: "/path/to/chat-submit.svg",
},
close: {
custom: "/path/to/close.svg",
},
info: {
custom: "/path/to/info.svg",
},
command: {
custom: "/path/to/command.svg",
},
},
// ...rest of baseSettings
};
```
> If the url for a `custom` icon is a `.svg` file it will be rendered as an ``, all other file types will be rendered using an ` ` tag.
## Default Theme
The default theme includes these core settings:
### Typography
```typescript
fontFamily: {
heading: "'Space Grotesk', system-ui, sans-serif",
body: "'Inter', system-ui, sans-serif",
mono: "'Fira Code', monospace",
},
fontSize: {
'3xs': '0.45rem',
'2xs': '0.625rem',
xs: '0.75rem',
sm: '0.875rem',
md: '1rem',
lg: '1.125rem',
xl: '1.25rem',
'2xl': '1.5rem',
'3xl': '1.875rem',
'4xl': '2.25rem',
'5xl': '3rem',
'6xl': '3.75rem',
'7xl': '4.5rem',
'8xl': '6rem',
'9xl': '8rem',
}
```
### Z-Index
```typescript
zIndex: {
hide: -1,
auto: 'auto',
base: 0,
docked: 10,
dropdown: 1000,
sticky: 1100,
banner: 1200,
overlay: 1300,
modal: 1400,
popover: 1500,
skipLink: 1600,
toast: 1700,
tooltip: 1800,
}
```
## Component Class Names
All component class names are prefixed with `ikp-`. Here's the complete list of available class names:
### Search Components
```css
ikp-ai-search-wrapper
ikp-ai-search-root
ikp-ai-search-content
ikp-ai-search-input-group
ikp-ai-search-input-icon
ikp-ai-search-input
ikp-ai-search-loading
ikp-ai-ask-ai-trigger
ikp-ai-ask-ai-trigger__icon
ikp-ai-ask-ai-trigger__label
ikp-ai-ask-ai-trigger__query
ikp-ai-ask-ai-trigger__indicator
ikp-ai-ask-ai-trigger__indicator-text
ikp-ai-search-results
ikp-ai-search-results__loading
ikp-ai-search-results__empty
ikp-ai-search-results__tab-list
ikp-ai-search-results__tab
ikp-ai-search-results__content
ikp-ai-search-results__scroll-area
ikp-ai-search-results__scroll-area-viewport
ikp-ai-search-results__list
ikp-ai-search-results__item
ikp-ai-search-results__item-icon
ikp-ai-search-results__item-breadcrumbs
ikp-ai-search-results__item-breadcrumb-icon
ikp-ai-search-results__item-title
ikp-ai-search-results__item-tag
ikp-ai-search-results__item-description
ikp-ai-search-results__item-description-part
ikp-ai-search-results__item-indicator
ikp-ai-search-results__item-preview
ikp-ai-search-results__item-preview__header
ikp-ai-search-results__item-preview__heading
ikp-ai-search-results__item-preview__title
ikp-ai-search-results__item-preview__title__link-icon
ikp-ai-search-results__item-preview__breadcrumbs
ikp-ai-search-results__item-preview__breadcrumb-icon
ikp-ai-search-results__item-preview__body
ikp-ai-search-results__item-preview__outline
ikp-ai-search-results__item-preview__outline__title
ikp-ai-search-results__item-preview__outline__list
ikp-ai-search-results__item-preview__outline__item
ikp-ai-search-results__item-preview__outline__item-icon
ikp-ai-search-results__item-preview__outline__item-text
ikp-ai-search-results__item-preview__outline__item-link-icon
ikp-ai-search-results__scroll-area-scrollbar
ikp-ai-search-results__scroll-area-thumb
ikp-ai-search-results__scroll-area-corner
ikp-ai-search-footer
ikp-ai-search-tagline__container
ikp-ai-search-tagline__text
ikp-ai-search-tagline__logo
ikp-ai-search-tagline__brand-name
```
### Chat Components
```css
ikp-ai-chat-wrapper
ikp-ai-chat-conversation-loading
ikp-ai-chat-root
ikp-ai-chat-header
ikp-ai-chat-header__toolbar
ikp-ai-chat-header__toolbar-header
ikp-ai-chat-header__toolbar-header-wrapper
ikp-ai-chat-content
ikp-ai-chat-content-scroll-area
ikp-ai-chat-content-scroll-area__viewport
ikp-ai-chat-content-scroll-area__scrollbar
ikp-ai-chat-content-scroll-area__thumb
ikp-ai-chat-content-scroll-area__corner
ikp-ai-chat-disclaimer
ikp-ai-chat-disclaimer-label
ikp-ai-chat-disclaimer-trigger
ikp-ai-chat-disclaimer-content
ikp-ai-chat-disclaimer-text
ikp-ai-chat-disclaimer-arrow
ikp-ai-chat-example-questions
ikp-ai-chat-example-questions-label
ikp-ai-chat-example-questions-list
ikp-ai-chat-example-question
ikp-ai-chat-example-question-button
ikp-ai-chat-workflows
ikp-ai-chat-workflows-label
ikp-ai-chat-workflows-list
ikp-ai-chat-workflow
ikp-ai-chat-workflow__icon
ikp-ai-chat-messages
ikp-ai-chat-message-wrapper
ikp-ai-chat-message-header
ikp-ai-chat-message-loading
ikp-ai-chat-message-avatar
ikp-ai-chat-message-avatar-fallback
ikp-ai-chat-message-avatar-image
ikp-ai-chat-message-avatar-content
ikp-ai-chat-message-name
ikp-ai-chat-message-content-wrapper
ikp-ai-chat-message-content
ikp-ai-chat-message-attachments
ikp-ai-chat-message-attachments__list
ikp-ai-chat-message-attachments__item
ikp-ai-chat-message-attachments__item-icon
ikp-ai-chat-message-attachments__item-title
ikp-ai-chat-message-attachments-preview
ikp-ai-chat-message-attachments-preview__overlay
ikp-ai-chat-message-attachments-preview__content
ikp-ai-chat-message-attachments-preview__header
ikp-ai-chat-message-attachments-preview__close
ikp-ai-chat-message-attachments-preview__body
ikp-ai-chat-message
ikp-ai-chat-message-toolbar
ikp-ai-chat-message-tool-actions
ikp-ai-chat-message-tool-action
ikp-ai-chat-message-action
ikp-ai-chat-message-sources
ikp-ai-chat-message-sources__header
ikp-ai-chat-message-sources__list
ikp-ai-chat-message-source-item
ikp-ai-chat-message-source-item__icon
ikp-ai-chat-message-source-item__breadcrumbs
ikp-ai-chat-message-source-item__breadcrumb
ikp-ai-chat-message-source-item__breadcrumb-icon
ikp-ai-chat-message-source-item__title
ikp-ai-chat-message-source-item__tag
ikp-ai-chat-message-source-item__description
ikp-ai-chat-message-source-item__description-part
ikp-ai-chat-message-source-item__indicator
ikp-ai-chat-footer
ikp-ai-chat-input__fieldset
ikp-ai-chat-input__group
ikp-ai-chat-input
ikp-ai-chat-input__send-button
ikp-ai-chat-input__send-button-icon
ikp-ai-chat-attachments-bar
ikp-ai-chat-attachments-bar__list
ikp-ai-chat-attachments-bar__attachment
ikp-ai-chat-attachments-bar__attachment-icon
ikp-ai-chat-attachments-bar__attachment-title
ikp-ai-chat-attachments-bar__attachment-delete
ikp-ai-chat-attachments-bar__actions
ikp-ai-chat-attachments-bar__info-tip
ikp-ai-chat-attachments-bar__info-tip-icon
ikp-ai-chat-attachments-bar__info-tip-arrow
ikp-ai-chat-attachments-bar__info-tip-text
ikp-ai-chat-attachments-bar__inputs
ikp-ai-chat-attachments-bar__input
ikp-ai-chat-attachments-bar__input-icon
ikp-ai-chat-attachments-bar__modal
ikp-ai-chat-attachments-bar__modal-overlay
ikp-ai-chat-attachments-bar__modal-content
ikp-ai-chat-attachments-bar__modal-header
ikp-ai-chat-attachments-bar__modal-close
ikp-ai-chat-attachments-bar__modal-body
ikp-ai-chat-attachments-bar__modal-heading
ikp-ai-chat-attachments-bar__modal-description
ikp-ai-chat-attachments-bar__modal-help
ikp-ai-chat-attachments-bar__form
ikp-ai-chat-attachments-bar__form-title
ikp-ai-chat-attachments-bar__form-title-label
ikp-ai-chat-attachments-bar__form-title-input
ikp-ai-chat-attachments-bar__form-title-error
ikp-ai-chat-attachments-bar__form-content
ikp-ai-chat-attachments-bar__form-content-label
ikp-ai-chat-attachments-bar__form-content-input
ikp-ai-chat-attachments-bar__form-content-error
ikp-ai-chat-attachments-bar__form-submit-button
ikp-ai-chat-action-bar
ikp-ai-chat__chat-actions
ikp-ai-chat__chat-action
ikp-ai-chat__chat-action-label
ikp-ai-chat__chat-action-feeback
ikp-ai-chat-help-actions
ikp-ai-chat-help-action
ikp-ai-chat-help-actions__trigger
ikp-ai-chat-help-actions__menu
ikp-ai-chat-help-actions__menu-arrow
ikp-ai-chat-help-actions__menu-item
ikp-ai-chat-help-actions_menu-item-icon
ikp-ai-chat-tagline__container
ikp-ai-chat-tagline__text
ikp-ai-chat-tagline__logo
ikp-ai-chat-tagline__brand-name
ikp-ai-chat-feedback-modal
ikp-ai-chat-feedback-modal__overlay
ikp-ai-chat-feedback-modal__content
ikp-ai-chat-feedback-modal__header
ikp-ai-chat-feedback-modal__close
ikp-ai-chat-feedback-modal__body
ikp-ai-chat-feedback-form
ikp-ai-chat-feedback-item
ikp-ai-chat-feedback-item__checkbox
ikp-ai-chat-feedback-item__checkbox-indicator
ikp-ai-chat-feedback-item__label
ikp-ai-chat-feedback-item__description
ikp-ai-chat-feedback-form__submit-button
ikp-ai-chat-form__wrapper
ikp-ai-chat-form
ikp-ai-chat-form__close
ikp-ai-chat-form__header
ikp-ai-chat-form__heading
ikp-ai-chat-form__description
ikp-ai-chat-form__content
ikp-ai-chat-form__field
ikp-ai-chat-form__field-label
ikp-ai-chat-form__field-text
ikp-ai-chat-form__field-email
ikp-ai-chat-form__field-file
ikp-ai-chat-form__field-text-area
ikp-ai-chat-form__field-checkbox
ikp-ai-chat-form__field-checkbox-indicator
ikp-ai-chat-form__field-select
ikp-ai-chat-form__field-select__trigger
ikp-ai-chat-form__field-select__value
ikp-ai-chat-form__field-select__icon
ikp-ai-chat-form__field-select__content
ikp-ai-chat-form__field-select__viewport
ikp-ai-chat-form__field-select__item
ikp-ai-chat-form__field-select__item-indicator
ikp-ai-chat-form__field-select__item-text
ikp-ai-chat-form__field-error
ikp-ai-chat-form__error
ikp-ai-chat-form__footer
ikp-ai-chat-form__cancel
ikp-ai-chat-form__submit
ikp-ai-chat-form__success
ikp-ai-chat-form__success-heading
ikp-ai-chat-form__success-message
ikp-ai-chat-form__success-button
ikp-ai-chat-link
```
### Markdown Components
```css
ikp-codeblock-container
ikp-codeblock-header
ikp-codeblock-header-language
ikp-codeblock-copy-button
ikp-codeblock-highlighter-wrapper
ikp-codeblock-highlighter
ikp-codeblock-code
ikp-markdown-h1
ikp-markdown-h2
ikp-markdown-p
ikp-markdown-li
ikp-markdown-ul
ikp-markdown-ol
ikp-markdown-link
ikp-markdown-source-link
ikp-markdown-table
ikp-markdown-th
ikp-markdown-td
ikp-markdown-code
ikp-markdown-input
```
### Form Components
```css
ikp-intelligent-form__root
ikp-intelligent-form__heading
ikp-intelligent-form__content
ikp-intelligent-form__content__scroll-area
ikp-intelligent-form__content__scroll-area-viewport
ikp-intelligent-form__content__scroll-area-scrollbar
ikp-intelligent-form__content__scroll-area-thumb
ikp-intelligent-form__content__scroll-area-corner
ikp-intelligent-form__success
ikp-intelligent-form__success-icon
ikp-intelligent-form__success-heading
ikp-intelligent-form__success-message
ikp-intelligent-form__primary-form
ikp-intelligent-form__primary-form__description
ikp-intelligent-form__primary-form-fields
ikp-intelligent-form__primary-form-submit
ikp-intelligent-form__field
ikp-intelligent-form__field-label
ikp-intelligent-form__field-text
ikp-intelligent-form__field-email
ikp-intelligent-form__field-file
ikp-intelligent-form__field-text-area
ikp-intelligent-form__field-checkbox
ikp-intelligent-form__field-checkbox-indicator
ikp-intelligent-form__field-select
ikp-intelligent-form__field-select__trigger
ikp-intelligent-form__field-select__value
ikp-intelligent-form__field-select__icon
ikp-intelligent-form__field-select__content
ikp-intelligent-form__field-select__viewport
ikp-intelligent-form__field-select__item
ikp-intelligent-form__field-select__item-indicator
ikp-intelligent-form__field-select__item-text
ikp-intelligent-form__field-error
ikp-intelligent-form__bot-heading
ikp-intelligent-form__bot-heading__icon
ikp-intelligent-form__bot-heading__name
ikp-intelligent-form__loading
ikp-intelligent-form__confident-response
ikp-intelligent-form__confident-answer
ikp-intelligent-form__confident-response-button
ikp-intelligent-form__confident-response-button__icon
ikp-intelligent-form__confident-response-button__label
ikp-intelligent-form__secondary-form
ikp-intelligent-form__secondary-form__description
ikp-intelligent-form__secondary-form-fields
ikp-intelligent-form__secondary-form-submit
ikp-intelligent-form__error
ikp-intelligent-form__sources
ikp-intelligent-form__sources-caption
ikp-intelligent-form__sources-list
ikp-intelligent-form__source
ikp-intelligent-form__source-icon
ikp-intelligent-form__source-title
```
### Search Bar Components
```css
ikp-search-bar__container
ikp-search-bar__button
ikp-search-bar__content-wrapper
ikp-search-bar__text
ikp-search-bar__icon
ikp-search-bar__kbd-wrapper
ikp-search-bar__cmd-icon
ikp-search-bar__ctrl
ikp-search-bar__kbd-shortcut-key
```
### Modal Components
```css
ikp-modal
ikp-modal__overlay
ikp-modal__content
ikp-modal__close
```
### Chat Button Components
```css
ikp-chat-button__text
ikp-chat-button__button
ikp-chat-button__container
ikp-chat-button__avatar-image
ikp-chat-button__avatar-content
```
### Miscellaneous Components
```css
ikp-icon
ikp-loading-indicator__text
ikp-loading-indicator__dots
ikp-loading-indicator__dot
ikp-view_toggle
ikp-view_toggle_button
ikp-view_toggle_icon
```
***
title: Add your own analytics
description: Use our callback function to log events from the search and chat widgets to your own analytics tool.
keywords: custom analytics, event tracking, analytics integration, user tracking, event logging, analytics implementation, callback functions, user properties, privacy settings, analytics configuration, event filtering, analytics tools, data tracking, analytics customization
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Scenario
To understand how usage of the Inkeep search or chat affects your business, you may want to log events from the search and chat widgets to your own analytics tool. This could be Mixpanel, Posthog, Amplitude, Segment or other analytics or CDP tools.
We expose all the events that we log to our own analytics suite through a callback function called `onEvent` that can be configured in the [baseSettings](/ui-components/common-settings/base) configuration.
Below is an example of how to use `onEvent` to log events related to the `assistant_message_received` event to your analytics tool. You can check out the full reference of events by inspecting the `InkeepCallbackEvent` type in the npm package.
We recommend you only log the events and properties on the events that you find relevant.
## Implementation Examples
### Basic Implementation
```typescript
import { type InkeepCallbackEvent } from "@inkeep/cxkit-types";
const baseSettings = {
onEvent: (event: InkeepCallbackEvent) => {
// Check if the event type is 'assistant_message_received'
if (event.eventName === "assistant_message_received") {
const { conversation } = event.properties;
// Log to your own analytics tool or CDP.
console.log("Response: ", conversation.at(-1).content);
}
},
};
```
Find the interface for conversation in the [Get Conversation API](/analytics-api/conversation/get-conversation) doc.
### Advanced Implementation with Event Filtering
```typescript
const baseSettings = {
onEvent: (event: InkeepCallbackEvent) => {
const { eventName, properties, userProperties } = event;
// Only track specific events
const eventsToTrack = [
"assistant_message_received",
"user_message_submitted",
"search_query_submitted",
];
if (!eventsToTrack.includes(eventName)) {
return;
}
// Add custom properties
const enrichedProperties = {
...properties,
environment: process.env.NODE_ENV,
timestamp: new Date().toISOString(),
// Add user context if available
...(userProperties?.id && { userId: userProperties.id }),
...(userProperties?.teamId && { teamId: userProperties.teamId }),
};
// Track with your analytics tool
analytics.track(eventName, enrichedProperties);
},
};
```
### Implementation with Multiple Analytics Tools
```typescript
const baseSettings = {
onEvent: (event: InkeepCallbackEvent) => {
const { eventName, properties } = event;
// Track with Segment
segment.track(eventName, properties);
// Track with Mixpanel
mixpanel.track(eventName, properties);
},
};
```
## Common Properties
Every event includes a set of common properties that provide context about the widget and the interaction. These properties are automatically included in the `properties` object of every event:
| Property | Type | Description |
| ---------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `widgetLibraryVersion` | `string` | The version of the Inkeep widget library being used |
| `componentType` | `string` | The type of widget interaction. Possible values: `'ChatButton'`, `'CustomTrigger'`, `'SearchBar'`, `'EmbeddedChat'`, `'EmbeddedSearch'`, `'EmbeddedSearchAndChat'`, `'IntelligentForm'` |
| `tags` | `string[]` | Custom tags passed in the `baseSettings`. These can be used to categorize or filter events |
You can also pass additional properties to the analytics api by passing the `analyticsProperties` object in the `baseSettings`. These properties will be merged with the event properties.
### Example with Tags
```typescript
const baseSettings = {
tags: ["production", "docs-site"], // These tags will be included in all events
analyticsProperties: { // Additional properties to send to analytics, these will be merged with the event properties
url: window.location.href,
},
onEvent: (event: InkeepCallbackEvent) => {
const { eventName, properties } = event;
console.log(properties.tags); // ['production', 'docs-site']
console.log(properties.widgetLibraryVersion); // e.g., '1.2.3'
console.log(properties.componentType); // e.g., 'EmbeddedChat'
console.log(properties.url); // e.g., 'https://docs.inkeep.com'
analytics.track(eventName, properties);
},
};
```
### User Properties
User properties are exactly what you pass to the `userProperties` in baseSettings. These properties can be used to associate events with specific users or teams.
```typescript
const baseSettings = {
userProperties: {
id: "user-123",
teamId: "team-456",
role: "admin",
// Any other custom user properties
},
onEvent: (event: InkeepCallbackEvent) => {
const { eventName, properties, userProperties } = event;
analytics.track(eventName, {
...properties,
user: userProperties,
});
},
};
```
## Configuration Options
### Privacy Preferences
These settings are used to configure the analytics tracking for the widget; passed in the `baseSettings` configuration.
| Option | Type | Default | Description |
| ------------------------- | --------- | ------- | --------------------------------- |
| `optOutAnalyticalCookies` | `boolean` | `false` | Opt out of analytical cookies |
| `optOutAllAnalytics` | `boolean` | `false` | Opt out of all analytics tracking |
| `optOutFunctionalCookies` | `boolean` | `false` | Opt out of functional cookies |
## Events Reference
### Chat Events
| Event Name | Description | Properties |
| --------------------------------------- | --------------------------- | --------------------------------------------------------------------------------- |
| `assistant_message_received` | Assistant response received | `conversation` |
| `user_message_submitted` | User message submitted | `conversation` |
| `shared_chat_loaded` | Shared chat loaded | `conversation` |
| `assistant_positive_feedback_submitted` | Positive feedback given | `conversation`, `reasons` |
| `assistant_negative_feedback_submitted` | Negative feedback given | `conversation`, `reasons` |
| `get_help_option_clicked` | Help option selected | `getHelpOption`, `conversation` |
| `chat_clear_button_clicked` | Chat cleared | `conversation` |
| `chat_share_button_clicked` | Share button clicked | `sharedChatUrl`, `sharedConversationId`, `originalConversationId`, `conversation` |
| `assistant_message_copied` | Message copied | `conversation` |
| `assistant_code_block_copied` | Code block copied | `conversation`, `language`, `code` |
| `assistant_source_item_clicked` | Source item clicked | `conversation`, `link` |
| `assistant_message_inline_link_opened` | Message link opened | `title`, `url` |
### Search Events
| Event Name | Description | Properties |
| -------------------------------- | ----------------------- | ----------------------------- |
| `search_result_clicked` | Result clicked | `searchQuery`, `title`, `url` |
| `search_query_submitted` | Query submitted | `searchQuery` |
| `search_query_response_received` | Search results received | `searchQuery`, `totalResults` |
### Intelligent Form Events
| Event Name | Description | Properties |
| -------------------------------------------- | ------------------------- | ----------------------------------- |
| `intelligent_form_submitted` | Form submitted | `conversation`, `values` |
| `intelligent_form_primary_section_submitted` | Primary section submitted | `conversation` |
| `intelligent_form_ai_response_provided` | AI response provided | `conversation`, `recordsConsidered` |
### UI Component Events
| Event Name | Description | Properties |
| -------------- | ------------ | ---------- |
| `modal_opened` | Modal opened | |
| `modal_closed` | Modal closed | |
## Alternatives
Instead of logging events on the client, you can associate Inkeep usage to specific user IDs by providing user identifiers in the `baseSettings.userProperties` [properties](/ui-components/common-settings/base#user-properties). These identifiers can come from an authentication token if you have one, or a distinct ID from your analytics provider.
You can then use these IDs to query analytics data using the `query-conversations` endpoint in the [Analytics API](/analytics-api/query/query-conversations). You can then set up a CDC pipeline to export this data into your analytics system and join the information there. This is the recommended approach if you have many integrations across many touchpoints that you want to log to your analytics system.
***
title: Embed a form in chat
description: Add a form to collect information from users in the chat experience.
keywords: form embedding, chat forms, user input forms, form integration, chat customization, form implementation, user data collection, chat interface, form configuration, user interaction, form design, chat forms, interactive forms
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
You can embed a form directly within the Inkeep AI assistant chat UI. It can be triggered from a ["Contact support" button](/ui-components/common-settings/ai-chat#help-actions) in the bottom right of the chat or as a [dynamic button](/ui-components/tools/escalate-to-support#support-ticket-form) that appears when the AI assistant is not confident in its answer.
Use this to create a support ticket in your ticketing platform via a custom callback. The history of the conversation can be included.
An example `open_form` action looks like this:
```typescript
const formAction: OpenFormAction = {
type: "open_form",
formSettings: {
heading: "Contact Support",
description: "Please fill out the form below",
fields: [
{
name: "email",
label: "Email Address",
inputType: "email",
isRequired: true,
placeholder: "Enter your email",
},
{
name: "description",
label: "Issue Description",
inputType: "textarea",
isRequired: true,
placeholder: "Describe your issue",
},
{
name: "priority",
label: "Priority Level",
inputType: "select",
items: [
{ label: "Low", value: "low" },
{ label: "Medium", value: "medium" },
{ label: "High", value: "high" },
],
isRequired: true,
},
],
buttons: {
submit: {
label: "Submit Ticket",
onSubmit: async ({ values, conversation }) => {
// Handle form submission
await submitTicket(values);
},
},
close: {
action: "return_to_chat",
},
},
successView: {
heading: "Ticket Submitted",
message: "We will get back to you shortly",
doneButton: {
label: "Back to Chat",
action: "return_to_chat",
},
},
},
};
```
## FormSettings Reference
The `FormSettings` interface provides a comprehensive way to configure forms in your chat interface, through the `open_form` action type. Here's a detailed breakdown of all available options:
### Basic Properties
| Property | Type | Required | Description |
| ----------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------- |
| heading | string | No | The form's title displayed at the top |
| description | string | No | Explanatory text shown below the heading |
| fields | FormField\[] | Yes | Array of form field configurations |
| buttons | FormButtons | Yes | Configuration for form action buttons |
| successView | SuccessView | No | Configuration for the success confirmation page. If not provided, the form will close after submission. |
### Field Types
Forms support various field types through the `FormField` union type:
#### Base Field Properties
All field types inherit these base properties:
| Property | Type | Required | Description |
| ----------- | ------- | -------- | ------------------------------- |
| name | string | Yes | Unique identifier for the field |
| label | string | Yes | Display label for the field |
| isRequired | boolean | No | Whether the field is required |
| isHidden | boolean | No | Whether to hide the field |
| description | string | No | Help text shown below the field |
#### Text Field
```typescript
{
name: 'name',
label: 'Full Name',
inputType: 'text',
defaultValue?: string,
placeholder?: string
}
```
#### Email Field
```typescript
{
name: 'email',
label: 'Email Address',
inputType: 'email',
defaultValue?: string,
placeholder?: string
}
```
#### Textarea Field
```typescript
{
name: 'description',
label: 'Description',
inputType: 'textarea',
defaultValue?: string,
placeholder?: string
}
```
#### Checkbox Field
```typescript
{
name: 'subscribe',
label: 'Subscribe to newsletter',
inputType: 'checkbox',
defaultValue?: boolean
}
```
#### Select Field
```typescript
{
name: 'category',
label: 'Category',
inputType: 'select',
items: [
{ label: 'Option 1', value: 'opt1' },
{ label: 'Option 2', value: 'opt2' }
],
defaultValue?: string,
placeholder?: string
}
```
#### File Field
```typescript
{
name: 'attachment',
label: 'Attach File',
inputType: 'file'
}
```
When using a `file` field in your form, you may need to convert the files to Base64 before sending to your backend or an external API, this can be done by using the following snippet.
```typescript
function convertFilesToBase64(files: FileList) {
const filesArray = Array.from(files);
return Promise.all(
filesArray.map((file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event) => {
const result = (event.target as FileReader).result;
const base64Data = result.replace(/^data:.+;base64,/, "");
resolve({
data: base64Data,
fileName: file.name,
mimeType: file.type,
});
};
reader.onerror = (error) => reject(error);
reader.readAsDataURL(file);
});
})
);
}
```
#### Include Chat Session Field
Special field type to include chat history:
```typescript
{
_type: 'include_chat_session',
label?: string, // Defaults to "Include chat history"
defaultValue?: boolean,
isHidden?: boolean,
name: 'include_chat_session',
}
```
### Button Configuration
The `buttons` property requires configuration for submit and optional close buttons:
```typescript
{
buttons: {
submit: {
label?: string, // Optional custom label
onSubmit: async ({ values, conversation }) => {
// Handle form submission
// values: Record - form field values
// conversation: ConversationResponse | null
}
},
close?: {
action: 'return_to_chat' | 'close_modal'
}
}
}
```
### Success View Configuration
The `successView` property configures what's shown after successful submission, if not provided, the form will close after submission.
```typescript
{
successView: {
heading: string, // Success message heading
message: string, // Detailed success message
doneButton: {
label: string, // Button text
icon?: InkeepCustomIcon, // Optional icon
action: 'return_to_chat' | 'close_modal'
}
}
}
```
### Complete Example
Here's a comprehensive example showing all available configurations:
```typescript
const formSettings: FormSettings = {
heading: "Submit Support Request",
description: "Please provide details about your issue",
fields: [
{
name: "name",
label: "Full Name",
inputType: "text",
isRequired: true,
placeholder: "John Doe",
description: "Enter your full name as it appears on your account",
},
{
name: "email",
label: "Email Address",
inputType: "email",
isRequired: true,
placeholder: "john@example.com",
},
{
name: "priority",
label: "Priority Level",
inputType: "select",
isRequired: true,
items: [
{ label: "Low", value: "low" },
{ label: "Medium", value: "medium" },
{ label: "High", value: "high" },
],
description: "Select the urgency of your request",
},
{
name: "description",
label: "Issue Description",
inputType: "textarea",
isRequired: true,
placeholder: "Please describe your issue in detail...",
},
{
name: "terms",
label: "I agree to the terms of service",
inputType: "checkbox",
isRequired: true,
},
{
name: "attachments",
label: "Attachments",
inputType: "file",
description: "Attach any relevant screenshots or files",
},
{
_type: "include_chat_session",
name: "include_chat_session",
label: "Include our conversation history",
defaultValue: true,
},
],
buttons: {
submit: {
label: "Submit Request",
onSubmit: async ({ values, conversation }) => {
try {
// Handle file conversion if needed
if (values.attachments) {
values.attachments = await convertFilesToBase64(values.attachments);
}
// Submit the form data
await submitSupportRequest({
...values,
chat_history: conversation?.messages,
});
} catch (error) {
throw new Error("Failed to submit support request");
}
},
},
close: {
action: "return_to_chat",
},
},
successView: {
heading: "Request Submitted Successfully",
message:
"We have received your support request and will respond within 24 hours.",
doneButton: {
label: "Return to Chat",
icon: { builtIn: "FaArrowLeft" },
action: "return_to_chat",
},
},
};
```
***
title: Custom Instructions
description: Add custom instructions to guide the AI assistant's responses.
keywords: AI instructions, response customization, AI guidance, custom prompts, AI behavior, instruction configuration, response patterns, AI customization, conversation guidance, instruction implementation
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sometimes, you want to pass in user information for the AI assistant to consider or provide instructions for the AI assistant to follow.
When using the `@inkeep/cxkit-react` components, you can pass this information using `prompts` as part of the [aiChatSettings](/ui-components/common-settings/ai-chat) configuration.
You can make these prompts dynamic based on user specific information (e.g. for logged in users) or based on the information from your CRM, application logic, or other sources.
`prompts` apply to the entire chat session, not just the first message.
### Add user context
Contextual prompts can be used to provide additional details about the user that might be helpful information for the AI assistant to consider while answering.
Often, this is used to dynamically provide information about the user that can be inferred by their account (if authenticated to your application) or based on the page they are currently viewing.
**Examples**
For providing context based on the user:
```
`The user is currently viewing documentation page ${url}.`
```
```
"The user is new to the platform." // (for user life cycle stages)
```
For providing context based on a product:
```
`The question is about ${product}.` // (for teams with multiple products)
```
```
"The user is using the cloud hosted version of the application." // (for teams with multiple versions or pricing tiers)
```
### Add custom rules
Prompts can be used to customize or guide the behavior of the AI assistant using instructions in natural langauge.
By default, the AI assistanth has sensible defaults for staying on topic, brand-protection, faithfulness to the source content, and other guardrails.
However, prompts can be useful to further customizing tone, having the assistant ask more clarifying questions, adding topics it should refuse to answer, or otherwise customizing the exact experience to your scenario.
See [Rules & Prompts](/projects/rules-and-prompts) for our recommendations and examples around how to prompt LLMs.
***
title: Authenticate Users and add Permissions
sidebarTitle: Authenticate Users
keywords: user authentication, access control, authentication implementation, security setup, user verification, auth configuration, authentication methods, user access, security implementation, authentication flow, user validation
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sometimes, you may want to authenticate users accessing your search or chat service.
This is typically applicable if you'd like to:
* Restrict answers of the assistant to content that a user has access to. Typically applicable for products with private, gated documentation that is only available to users with certain permissions.
* Provide context (information) about the user or apply source filters in a way that cannot be tampered with by the end-user.
* Implement your own CAPTCHA, throttling, or anti-bot security measures and use a JWT to verify that the user has passed it.
## Generate verification keys
Generate a private and public key pair using `openssl` or the method of your choice.
```bash
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private_key.pem -out public_key.pem
```
The *private* key will be used by your backend service to mint JWT tokens that are sent to the Inkeep search and chat service. It should not be shared with any other service or third party.
## Configure the integration
In your Inkeep Integration, configure the following under **Advanced Settings**:
* **Require user authentication**: set to `true`
* **Public key**: provide the value of `public_key.pem`
* **Issuer**: the value we should ensure matches the `iss` claim in the authentication token. Example: `https://auth.mydomain.com`. This is just a string URI so can be arbitrary. It just needs to uniquely identify your service.
We will use the public key to validate the token that is provided to our service was created ('minted') by your service. We check the signature of the token and the `iss`, `exp`, `aud` and other standard claims.
## Generating a token in your backend
You need a Microservice to create a JWT token every time a user is looking to make a search or chat.
Here is an example of how to generate a token in Node.js:
```typescript
import fs from "fs";
import jwt from "jsonwebtoken";
interface TokenConfiguration {
iss: string;
aud: string;
filters?: {
// optional
attributes: {
$and: Array<{
[key: string]: string | { $in: string[] };
}>;
};
};
userAttributes?: {
// optional
[key: string]: string | number | string[];
};
expirationOffsetHours?: number;
}
const generateToken = ({
iss,
aud,
integrationId,
filters,
userAttributes,
expirationOffsetHours = 24,
}: TokenConfiguration): string => {
const privateKey = fs.readFileSync("private_key.pem", "utf8"); // your private key
const payload = {
iss,
aud: "https://api.inkeep.com",
integrationId,
filters,
userAttributes,
exp: Math.floor(Date.now() / 1000) + expirationOffsetHours * 60 * 60,
};
const token = jwt.sign(payload, privateKey, { algorithm: "RS256" });
return token;
};
const exampleConfiguration: TokenConfiguration = {
iss: "https://auth.mydomain.com",
filters: {
attributes: {
$and: [
{
env: "dev",
},
{
modules: {
$in: ["module1", "module2"],
},
},
],
},
},
userAttributes: {
userId: "123456789",
userEmail: "me@inkeep.com",
userCohorts: [`group1`, `group2`],
},
expirationOffsetHours: 24,
};
const token = generateToken(exampleConfiguration);
```
The token should include the following claims:
* `iss`: The issuer of the token. Example `https://auth.mydomain.com`.
* `aud`: The audience of the token. It should always be `https://api.inkeep.com`.
* `integrationId`: The ID of the integration. This must match the integration ID in the body of the request.
* `filters` (optional): Same as documented in the (Filters)\[/ui-components/customization-guides/filters] guide. You can use filters as a way to dynamically scope down the sources that are considered specifically to the sources that the users have permission to access.
* `userAttributes` (optional): Same as documented in the [Start new chat](/inkeep-api/create-new-chat-session#newsessionchatresultinput) request body. Takes precedence over the `userAttributes` value provided in the request body.
* `exp`: The expiration time of the token, in seconds since the epoch.
## Add the token to chat or search requests
### When using the Inkeep widgets
Pass in the token you mint to the widget configuration as `baseSettings.userToken`. See [here](/ui-components/common-settings/base).
### When using the Inkeep API
Make sure to include these two headers:
* `Authorization` : `Bearer {integrationApiKey}` (must still be present in all requests)
* `User-Token`: `{JWT_TOKEN_SIGNED_BY_YOUR_BACKEND}`
***
title: Sharable Chats
description: Enable users to share their chat conversations.
keywords: chat sharing, conversation sharing, share functionality, chat links, conversation links, share implementation, chat features, user collaboration, chat history, share configuration, chat accessibility
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Enable the **Share** button in your Inkeep components.
When clicked, it generates a link to a chat so a user can share with other users.
We first need to create a page where the share links will lead to (e.g. `https://inkeep.com/ask-ai`). This should be a
page in your documentation, app, or marketing site that contains the Inkeep Embedded Chat component.
Reference:
* [React](/ui-components/react/in-page/embedded-chat)
* [JavaScript](/ui-components/js-snippet/in-page/embedded-chat)
Examples:
* [Next.js](/integrations/nextjs/embedded-chat)
* [Webflow](/integrations/webflow/embedded-chat)
The Embedded Chat automatically displays any conversation based on if a `?chatId=` query parameter is present in the URL of the loading the page it's embedded in.
Set the value of `aiChatSettings.shareChatUrlBasePath` to the URL from the previous step for all Inkeep components you want to enable the **Share** button for. This can include any Search Bar, Chat Button, or Custom Trigger you use in any site or application.
When clicked, it'll copy a link to the user's clipboard in the format of `https://{shareChatUrlBasePath}?chatId={sharedChatId}`.
Also set `aiChatSettings.isShareButtonVisible` to `true`.
## Example
```typescript
import { type InkeepAIChatSettings } from "@inkeep/cxkit-react";
const inkeepAIChatSettings: InkeepAIChatSettings = {
//... rest of inkeepAIChatSettings
isShareButtonVisible: true,
shareChatUrlBasePath: "https://mydomain.com/ask-ai",
};
```
***
title: Source Transformation
description: Transform source content before it's used by the AI assistant.
keywords: content transformation, source modification, content processing, data transformation, content formatting, source handling, content preparation, data processing, content adaptation, source customization, content optimization
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Scenario
In this guide, we'll explore how to customize the display of source information. This includes modifying source icons, titles, URLs, breadcrumbs, the tabs where search results appear, and other metadata for search results and chat references.
## Type Signature
The `transformSource` function is defined in the `InkeepBaseSettings` interface and allows you to modify how source information appears in different contexts:
| Parameter | Type | Description |
| --------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `source` | `SourceItem` | The original source data containing title, URL, description, etc. |
| `type` | `'chatSourceItem' \| 'searchResultItem' \| 'intelligentFormSource'` | Context where the source is being displayed |
| `opts` | `{ organizationDisplayName?: string; tabs?: (string \| SearchTab)[] }` | Additional options including organization name and configured tabs |
The function should return a `TransformedSource` object that defines how the source should be displayed. This gives you control over:
* Title and description formatting
* URL modifications and parameters
* Breadcrumb trails
* Tab categorization
* Icons and visual elements
* Link behavior (new tab vs same window)
* Additional metadata and tags
Common use cases include:
* Adding organization branding to titles
* Truncating long descriptions
* Categorizing content into tabs
* Adding tracking parameters to URLs
* Customizing navigation behavior
* Setting context-specific icons
```typescript
type TransformSource = (
source: SourceItem,
type: TransformSourceType,
opts?: TransformSourceOptions
) => TransformedSource;
interface SourceItem {
id?: string;
title: string | undefined;
url: string;
description: string | undefined;
breadcrumbs: string[];
type: `${SourceItemType}`;
contentType?: string;
tag?: string;
tabs?: (SourceTab | string)[];
}
interface TransformedSource {
id?: string;
title: string;
url: string;
description?: string;
breadcrumbs?: string[];
tabs?: (string | [string, { breadcrumbs: string[] }])[];
icon: InkeepCustomIcon;
shouldOpenInNewTab?: boolean;
appendToUrl?: object;
type: string;
tag?: string;
}
```
## Examples
### Basic source transformation
This example sets the title of all sources to include the organization name, and uses the book icon for all sources.
```typescript
// Basic source transformation
const baseSettings: InkeepBaseSettings = {
// ...
transformSource: (source, type) => ({
...source,
title: `${source.title} - My Site`,
icon: { builtIn: "LuBookOpen" },
}),
};
```
### Advanced source transformation
This example shows how to transform the source data based on whether the source is a search result or a chat source.
```typescript
// Advanced source transformation
const enterpriseSettings: InkeepBaseSettings = {
// ...
transformSource: (source, type, opts) => {
// Transform based on source type
if (type === "searchResultItem") {
return {
...source,
title: `${opts?.organizationDisplayName} - ${source.title}`,
description: source.description?.slice(0, 150) + "...",
breadcrumbs: [...(source.breadcrumbs || []), "Documentation"],
tabs: ["Docs", ["API", { breadcrumbs: ["API", "Reference"] }]],
icon: { builtIn: "LuBookOpen" },
shouldOpenInNewTab: true,
appendToUrl: { source: type },
};
}
// Different transformation for chat sources
if (type === "chatSourceItem") {
return {
...source,
icon: { custom: "https://assets.example.com/chat-icon.svg" },
shouldOpenInNewTab: false,
};
}
return source;
},
};
```
### Add a documentation tab
Let's have a "Documentation" tab that shows the sources that come from your docs. Assuming you have other sources aside docs.
You'd first one to define a `Documentation` tab:
```typescript
const searchSettings: InkeepSearchSettings = {
// ...
tabs: ["Documentation", ...otherTabs],
};
```
More info on tabs can be found in the [Search and Chat](/ui-components/common-settings/search#search-tabs) guide.
Then you'd need to update the `transformSource` function to add qualifying sources to the `Documentation` tab:
```typescript
// Basic source transformation
const baseSettings: InkeepBaseSettings = {
// ...
transformSource: (source, type) => {
const tabs = source.tabs || [];
// Do desired check here
if (source.type === "documentation" || source.url.includes("mydocs.com")) {
tabs.push("Documentation");
}
return {
...source,
tabs,
};
},
};
```
### Hide breadcrumb in matching tab.
Say you're in a Blog tab, and a blog post has a breadcrumb of `Blog > Announcement > My Post`. You may want to hide the `Blog` breadcrumb when the user is in the `Blog` tab.
Well when setting a tab for a source, you can also decide the breadcrumbs to show in that tab for that source.
```typescript
// Basic source transformation
const baseSettings: InkeepBaseSettings = {
// ...
transformSource: (source, type) => ({
...source,
tabs: [
[
"Blog",
{
breadcrumbs:
source.breadcrumbs[0] === "Blog"
? source.breadcrumbs.slice(1)
: source.breadcrumbs,
},
],
...otherTabs,
],
}),
};
```
***
title: Filter or scope down sources available to the assistant
sidebarTitle: Filters & Permissions
description: Filter content based on user context.
keywords: content filtering, user context, filter implementation, content customization, dynamic filtering, context-based filtering, filter configuration, content scoping, user-specific content, filtering options, content relevance
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Scenario
In this guide, we'll explore how to filter the search and chat results using custom tags and attributes. This allows you to tailor the search experience based on specific criteria, such as product versions or SDKs. By using filters, you can ensure that users only see relevant results based on their current context or preferences.
## Filters
Filters can be defined using the `filters` property of the `InkeepBaseSettings` interface. These filters will apply to both the search and chat experiences. Alternatively you can also define filters in the `InkeepSearchSettings` and `InkeepChatSettings` interfaces to apply them only to the search or chat experience respectively.
```typescript
export interface SearchAndChatFilters {
attributes?: {
[key: string]: any;
};
}
```
### Supported Operators
Comparison Operators: `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`\
Array Operators: `$in`, `$nin`\
Boolean Operators: `$exists`\
Logical Operators: `$and`, `$or`
### Filter by custom tags and attributes
A common filter scenario is you have docs that covers many products, versions, and SDKs.
The first part to setting up filters is to add ` ` tags prefixed with `inkeep:` to each page. For example:
```html
```
Then to filter the search and chat with your custom tags `version` and `sdk`:
```typescript
const baseSettings: InkeepBaseSettings = {
// ...
filters: {
attributes: {
$and: [
{ version: { $in: ["latest"] } },
{ sdk: { $in: ["react", "vue"] } },
],
},
},
};
```
Filters can be dynamically generated based on the page the user is on, giving full control over the search and chat experience.
### Filter by source id
You can also filter by source id. This is useful if you want to show only specific sources in the search and chat results. You can find the source id in the [Inkeep Dashboard](https://portal.inkeep.com/) by going to the **Sources** tab, then selecting the particular source you would like to get the id for.
```typescript
const baseSettings: InkeepBaseSettings = {
// ...
filters: {
attributes: {
source_id: sourceId,
},
},
};
```
To filter by multiple source ids, you can use the `$or` operator like so:
```typescript
const baseSettings: InkeepBaseSettings = {
// ...
filters: {
attributes: {
$or: [
{
source_id: sourceId1,
},
{
source_id: sourceId2,
},
],
},
},
};
```
***
title: Content Security Policy
description: Configure CSP for Inkeep's UI components.
keywords: content security policy, CSP configuration, security settings, web security, script security, CSP directives, security implementation, security headers, CSP setup, security configuration, web application security
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
### Allowlisting request endpoints
If your app or website has a strict Content Security Policy, you may need to allowlist the following domains:
* `https://api.inkeep.com`
* `https://api.io.inkeep.com`
Alternatively, you can set up a proxy instead using the `chatApiProxyDomain` and `analyticsApiProxyDomain`, see [here](/ui-components/common-settings/base) for more details.
### Allowlisting the script source
If you are loading the widget via a [JS Snippet](/ui-components/js-snippet/chat-button) you may also need to allowlist:
* `https://cdn.jsdelivr.net` or `https://uikit.inkeep.com`
### Self hosting the JS file
If you would like to host the JS file yourself, you can do so by downloading the file from [here](https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js) and hosting it on your own server.
1. Navigate [here](https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/embed.js)
2. Right click and save as `inkeep-cxkit-{version}.js`, you can find the version of the package [here](https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5/dist/)
3. Add the file to your project
4. Replace the url in the script tag with the path to your file:
```html
```
5. Note that if you need to update the package version, you will need to download the new version and replace the file in your project and update the script tag accordingly.
***
title: API keys for Public Assistants
sidebarTitle: Public API Keys
keywords: API key security, public clients, web security, API authentication, security best practices, referrer URL validation, development environments, staging environments, proxy configuration, rate limiting, security measures, API protection, client security, API key management, security configuration
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Public clients
When you embed your AI assistant in websites where the user is not authenticated, like in your public docs, help center, or marketing site, the web browser is considered a "public client". Since many of these clients often don't have a backend, the most practical way to use the AI assistant is for UI components to talk directly to the Inkeep service.
While it is up to your company's own policies and best practices, in these scenarios, the Inkeep API key is generally ok to be included in the source code of your web page that is exposed in the browser. This is similar to how [Algolia's search service](https://support.algolia.com/hc/en-us/articles/18966776061329-Can-the-search-API-key-be-public) or [Sentry's error logging](https://forum.sentry.io/t/how-does-sentry-prevent-spammers/8188) works.
## Default security
To prevent misuse of your public API key, Inkeep by default:
* Implements IP and client level throttling and monitoring
* Monitors for abusive or spam-like behavior
* Uses other security mechanisms
* Blocks access to malicious clients
Additionally, the API key is tied to the Inkeep chat service, so it's only useful for answering questions about your product. It's *not* a general purpose API key like an API key to OpenAI or general LLM provider would be.
## Content security
We recommend **not** using private content like support tickets or internal Slack conversations in your customer-facing assistants. They are typically only used in employee-facing AI [Inkeep Copilot](/support-tools/agent-copilot/overview) or internal [Slack bot](/integrations/slack/internal-team). Private vs public projects and sources are labeled in the Inkeep dashboard to help make it clear. Check the **Sources** tab in a project to see what sources are enabled for a project.
## Referrer URL
For **Web** integration types, we recommend:
1. Specifying the root URL of your webpage in the **URL** field
2. Ensuring the **Enforce referrer URL** option is enabled for your production API keys
3. Registering a different integration for at minimum every domain/site you add Inkeep to.
As one of many security measures, this enables our chat service to check that API requests are coming from browsers navigating your website.
### Local development
For local environments, we recommend *creating a separate Web integration* so you can have a different API key than your production one. You can disable **Enforce referrer URL** for this purpose. Keep this API key secure.
### Staging environments
Similarly, we recommend creating another **Web** integration for your staging environments with a different URL and API key. You can leave **Enforce referrer URL** enabled.
Creating separate API keys also helps keep real vs test usage separated in your analytics.
## Advanced security
If you would like to implement your own protection mechanisms or keep the API key private, you can have traffic routed through a private proxy. Your proxy is then responsible for rate limiting mechanisms or other security measures like CAPTCHA services. In this scenario, you can use an **API** integration type instead of a **Web** type and have your proxy insert the API key in the forwarded requests. This is because the communication now happens between your proxy server and Inkeep's server.
Alternatively, you can require a user to authenticate with your application before accessing the assistant. You can optionally have the Inkeep chat service validate a JWT token to check that the user should have access.
Contact [support](mailto:support@inkeep.com?subject=Implement%20protection%20mechanisms) for details on either of these approaches.
***
title: Overview
description: Add custom behavior to the Inkeep Assistant UI
keywords: AI tools, custom functions, tool integration, chat interactions, message buttons, action triggers, tool schemas, function definitions, UI customization, tool callbacks, tool implementation, chat automation, tool configuration, custom actions, tool events
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Tools allow you to define custom functions that can be called by the AI assistant during chat interactions. These tools enable the AI to trigger actions in your application or the chat experience.
For example, you can use tools to escalate the conversation to a support channel or embed a sales call to action from within the experience.
{" "}
Tools are available for the Enterprise tier. Please contact
[sales@inkeep.com](mailto:sales@inkeep.com?subject=Enterprise%20Plan%20-%20Tools%20Access)
for details.{" "}
## Overview
Tools are defined in the `getTools` function of the [AI chat settings](/ui-components/common-settings/ai-chat#tools).
Each tool has a `type`, `function` definition, and a `renderMessageButtons` callback which determines which **Message Buttons** to display.
Message Buttons, if displayed, are shown in the bottom left of the assistant message and can trigger a variety of different [actions](/ui-components/common-settings/actions) when clicked by the user.
| Action Type | Description | Use Case |
| ----------------- | ------------------------------------------ | ---------------------------------------------------------------- |
| `open_link` | Opens a URL in a new tab or current window | Link to documentation, external resources, or contact pages |
| `invoke_callback` | Executes a JavaScript callback function | Trigger custom logic in your application, like showing a modal |
| `open_form` | Displays a configurable form dialog | Collect user information for support tickets or contact requests |
Currently, tools are invoked after the AI assistant has responded with its main message.
You can define tool schemas using `zod` and `zod-to-json-schema` or directly with a JSON Object Schema.
```ts
const aiChatSettings: InkeepAIChatSettings = {
// ... other chat settings
getTools: (ctx: ToolContext) => {
return [
{
type: "function",
function: {
name: "callme",
description: "Call this function every time",
parameters: {
// JSON Object Schema
},
},
renderMessageButtons: ({ args }) => {
return [
{
label: "My Button",
action: {
type: "open_link",
url: "https://mydomain.com/page",
},
},
];
},
},
];
},
};
```
## `onToolCall`
The `onToolCall` callback function is triggered whenever the AI uses a tool.
```ts
const aiChatSettings: InkeepAIChatSettings = {
// ... other chat settings
onToolCall: (
toolCall: FunctionToolCallArgumentsDoneEvent,
ctx: ToolContext
) => {
console.log(toolCall.name);
console.log(toolCall.arguments);
console.log(ctx.conversation);
},
};
```
## Common Tool Use Cases
Here are a few common use cases:
* [Escalate to Support](/ui-components/tools/escalate-to-support) - Show a button that allows a user to escalate to support or hand off to other support channels.
* [Detect Sales Intent](/ui-components/tools/detect-sales-signals) - Identify when a user is expressing buying intent and have a sales call to action.
* [Label Answers](/ui-components/tools/label-answers) - Log question-answer data and annotations to your analytics system.
For common tool schema definitions, see [Common Tools](/ui-components/tools/common-tool-schemas).
***
title: Escalate to Support
description: Dynamically direct users to support as needed
icon: LuHeartHandshake
keywords: support escalation, customer support, support automation, support workflow, ticket creation, live chat integration, support form, support routing, AI confidence, support options, support tools, support integration, support handoff, support automation tools
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
You can use tools to identify when the AI assistant can't fully address a user's question and provide appropriate support options.
A button can be shown in the assistant message that can use actions to:
* Link to a support page
* Have the user fill out a support form
* Transfer to live chat
{" "}
Tools are available for the Enterprise tier. Please contact
[sales@inkeep.com](mailto:sales@inkeep.com?subject=Enterprise%20Plan%20-%20Tools%20Access)
for details.{" "}
## Answer Confidence Tool
This example uses the `provideAnswerConfidenceSchema` from [Common Tools](/ui-components/tools/common-tool-schemas) to determine the AI assistant's confidence level. You can define your own classifications or logic for the escelation paths you prefer.
When the answer is not confident, we can show a dynamic button to escalate to support.
## Link to Support Page
```typescript
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
import type { ToolFunction } from "@inkeep/cxkit-react";
import { provideAnswerConfidenceSchema } from "./common-tool-schemas.ts";
const aiChatSettings = {
getTools: () => [
{
type: "function",
function: {
name: "provideAnswerConfidence",
description:
"Determine how confident the AI assistant was and whether or not to escalate to humans.",
parameters: zodToJsonSchema(provideAnswerConfidenceSchema),
},
renderMessageButtons: ({ args }) => {
const confidence = args.answerConfidence;
if (["not_confident", "no_sources", "other"].includes(confidence)) {
return [
{
label: "Contact Support",
icon: { builtIn: "IoHelpBuoyOutline" },
action: {
type: "open_link",
url: "/support",
},
},
];
}
return [];
},
} as ToolFunction<{
answerConfidence: string;
explanation: string;
}>,
],
};
```
### Support Ticket Form
This example embeds a form for creating support tickets directly within the chat interface:
```typescript
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
import { provideAnswerConfidenceSchema } from "./common-tool-schemas.ts";
const aiChatSettings = {
getTools: () => [
{
type: "function",
function: {
name: "provideAnswerConfidence",
description:
"Determine how confident the AI assistant was and whether or not to escalate to humans.",
parameters: zodToJsonSchema(provideAnswerConfidenceSchema),
},
renderMessageButtons: ({ args }) => {
const confidence = args.answerConfidence;
if (["not_confident", "no_sources", "other"].includes(confidence)) {
return [
{
label: "Create Ticket",
icon: { builtIn: "LuUsers" },
action: {
type: "open_form",
formSettings: {
heading: "Contact Support",
description: "We'll help you resolve your issue.",
fields: [
{
label: "Email",
name: "email",
inputType: "email",
isRequired: true,
},
{
label: "Description",
name: "description",
inputType: "textarea",
isRequired: true,
},
{
_type: "include_chat_session",
name: "include_chat_session",
label: "Include chat history",
defaultValue: true,
},
],
buttons: {
submit: {
label: "Submit Request",
onSubmit: async ({ values, conversation }) => {
// Create support ticket in your support platform
await submitSupportRequest(values);
},
},
close: {
action: "return_to_chat",
},
},
successView: {
heading: "Request Submitted",
message: "We'll get back to you shortly.",
doneButton: {
label: "Close",
action: "return_to_chat",
},
},
},
},
},
];
}
return [];
},
},
],
};
```
### Transfer to Live Chat
```typescript
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
import { provideAnswerConfidenceSchema } from "./common-tool-schemas.ts";
const aiChatSettings = {
getTools: () => [
{
type: "function",
function: {
name: "provideAnswerConfidence",
description:
"Determine how confident the AI assistant was and whether or not to escalate to humans.",
parameters: zodToJsonSchema(provideAnswerConfidenceSchema),
},
renderMessageButtons: ({ args }) => {
const confidence = args.answerConfidence;
if (["not_confident", "no_sources", "other"].includes(confidence)) {
return [
{
label: "Talk to Support",
icon: { builtIn: "IoChatbubblesOutline" },
action: {
type: "invoke_callback",
callback: ({ conversation }) => {
// Switch to live chat. Implementation depends on your live chat provider.
switchToLiveChat(conversation);
},
},
},
];
}
return [];
},
},
],
};
```
***
title: Detect Sales Signals
description: Identify and respond to purchasing signals in user questions
icon: LuLightbulb
keywords: sales detection, purchasing signals, sales automation, sales tools, sales integration, sales workflow, sales triggers, sales response, sales actions, sales routing, sales opportunities, sales conversion, sales automation tools, sales implementation
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
The "Detect Sales Signals" tool pattern helps identify when users express potential interest in making a purchasing or action related to sales. This is useful for embedding call to actions to:
* Schedule a sales meeting
* Triggering in-app logic to make an upgrade
* Guiding users to relevant pricing or sales content
{" "}
Tools are available for the Enterprise tier. Please contact
[sales@inkeep.com](mailto:sales@inkeep.com?subject=Enterprise%20Plan%20-%20Tools%20Access)
for details.{" "}
## Book a meeting
This example provides a demo scheduling link when a sales signal is detected.
```typescript
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
import type { ToolFunction } from "@inkeep/cxkit-react";
import { salesSignalType, detectedSalesSignal } from "./common-tool-schemas.ts";
const validSalesSignalTypes: string[] = salesSignalType.options.map(
(option) => option.value
);
const aiChatSettings = {
getTools: () => [
{
type: "function",
function: {
name: "detectSalesSignal",
description:
"Identify when users express interest in potentially purchasing a product.",
parameters: zodToJsonSchema(detectedSalesSignal),
},
renderMessageButtons: ({ args }) => {
// If any valid sales signal is detected, show a demo scheduling option
if (args.type && validSalesSignalTypes.includes(args.type)) {
return [
{
label: "Schedule a Demo",
icon: { builtIn: "LuCalendar" },
action: {
type: "open_link",
url: "/schedule-demo",
},
},
];
}
return [];
},
} as ToolFunction<{ type: string }>,
],
};
```
Use the following styles if you would like to make the button larger and on it's own line:
```typescript
import type { InkeepBaseSettings } from "@inkeep/cxkit-react";
const baseSettings: InkeepBaseSettings = {
// ...rest of baseSettings
theme: {
styles: [
{
key: "custom-style",
type: "style",
value: `
.ikp-ai-chat-message-toolbar {
flex-wrap: wrap;
justify-content: flex-end;
}
.ikp-ai-chat-message-tool-actions {
width: 100%;
}
.ikp-ai-chat-message-tool-action {
background: var(--ikp-color-gray-950);
color: white;
font-size: 15px;
border: none;
margin: 0px auto;
margin-bottom: 8px;
padding: 12px 24px;
gap: 12px;
display: flex;
height: auto;
}
.ikp-ai-chat-message-tool-action > .ikp-icon {
font-size: 18px;
}
.ikp-ai-chat-message-tool-action:hover:not([disabled]) {
background: var(--ikp-color-gray-800);
color: white;
}
[data-theme="dark"] .ikp-ai-chat-message-tool-action {
background: var(--ikp-color-inkeep-expanded-primary-400);
color: var(--ikp-color-gray-950);
}
[data-theme="dark"] .ikp-ai-chat-message-tool-action:hover:not([disabled]) {
background: var(--ikp-color-inkeep-expanded-primary-200);
color: var(--ikp-color-gray-950);
}
`,
},
],
},
};
```
## Signal-Based Actions
This example provides different actions based on the specific type of sales signal detected.
```typescript
import { z } from "zod";
import type { InkeepAIChatSettings, ToolFunction } from "@inkeep/cxkit-react";
import { zodToJsonSchema } from "zod-to-json-schema";
import { detectedSalesSignal } from "./common-tool-schemas.ts";
const aiChatSettings: InkeepAIChatSettings = {
getTools: () => [
{
type: "function",
function: {
name: "detectSalesSignal",
description:
"Identify when users express interest in potentially purchasing a product.",
parameters: zodToJsonSchema(detectedSalesSignal),
},
renderMessageButtons: ({ args }) => {
const signalType = args.type;
// Different actions based on specific signal type
if (
[
"requested_sales_contact",
"enterprise_features",
"implementation_services",
].includes(signalType)
) {
return [
{
label: "Talk to Sales",
icon: { builtIn: "FaUserTie" },
action: {
type: "open_link",
url: "/contact-sales",
},
},
];
}
if (signalType === "pricing_inquiry") {
return [
{
label: "View Pricing",
icon: { builtIn: "FaTag" },
action: {
type: "open_link",
url: "/pricing",
},
},
];
}
if (signalType === "upgrade_inquiry") {
return [
{
label: "Upgrade Account",
icon: { builtIn: "LuSparkles" },
action: {
type: "invoke_callback",
callback: ({ conversation }) => {
// Custom logic to show an upgrade modal in your application
showUpgradeModal();
},
},
},
];
}
return [];
},
} as ToolFunction<{ type: string }>,
],
};
```
***
title: Label answers and add to your own analytics system
sidebarTitle: Label answers
description: Log question-answer data and annotations to your analytics system
icon: LuTag
keywords: answer labeling, analytics integration, data logging, question-answer pairs, conversation tracking, data annotation, analytics tools, conversation analytics, answer quality, content analysis, data collection, conversation metrics, analytics implementation, data tracking
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
The "Label Answers" tool pattern allows you to annotate question-answer pairs and log the data to your own analytics system. This is useful for:
* Building a labeled dataset of user questions and AI responses
* Tracking conversation quality metrics
* Identifying content gaps in your knowledge base
* Analyzing user sentiment and question patterns
{" "}
Tools are available for the Enterprise tier. Please contact
[sales@inkeep.com](mailto:sales@inkeep.com?subject=Enterprise%20Plan%20-%20Tools%20Access)
for details.{" "}
## Basic Implementation
This example uses the `annotationSchema` from [Common Tools](/ui-components/tools/common-tool-schemas) to classify and log information about each question-answer pair to your analytics system.
```typescript
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
import { annotationSchema } from "./common-tool-schemas.ts";
import myAnalyticsSdk from "./my-analytics-sdk";
const aiChatSettings = {
getTools: () => [
{
type: "function",
function: {
name: "annotateQuestion",
description:
"Analyze and annotate this question-answer pair for quality tracking and analytics.",
parameters: zodToJsonSchema(annotationSchema),
},
// No buttons needed as this is just for logging
renderMessageButtons: () => [],
},
],
// Log the tool call data to your analytics system
onToolCall: (toolCall, ctx) => {
if (toolCall.name === "annotateQuestion") {
const annotations = toolCall.arguments;
const { conversation } = ctx;
// Get the latest user question and AI response
const userQuestion = conversation.messages
.filter((msg) => msg.role === "user")
.pop();
const aiResponse = conversation.messages
.filter((msg) => msg.role === "assistant" && !msg.tool_calls)
.pop();
// Log to your analytics system
myAnalyticsSdk.logEvent("question_answer_annotated", {
questionText: userQuestion?.content,
answerText: aiResponse?.content,
annotations,
conversationId: conversation.id,
timestamp: new Date().toISOString(),
});
}
},
};
```
***
sidebarTitle: Common Tools
title: Common Tool Schema Definitions
icon: LuShapes
keywords: tool schemas, schema definitions, TypeScript schemas, Zod schemas, tool configuration, answer confidence, sales detection, data annotation, schema implementation, tool parameters, schema examples, tool definitions, schema patterns, tool customization
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Custom tool definitions can be passed into the [AI API](/ai-api/chat-completions-api) or [`cxkit` UI components](/ui-components/tools/overview).
The below are examples for a few common scenarios. You can adjust the exact descriptions, possible values, and exact schemas to adhere to your own business logic.
These examples use `zod` TypeScript library, but these can be defined using other serialization libraries or a plain JSON Object Schema.
To covert these Zod definitions to a JSON schema, use:
```ts
import { zodToJsonSchema } from "zod-to-json-schema";
const jsonSchema = zodToJsonSchema(yourZodSchema);
```
If using Webflow or other app platforms, ask Claude or ChatGPT to give you the JSON Object Schema equivalent of the below.
### Answer Confidence Tool
Use this schema as the parameters for a `provideAnswerConfidence` tool to determine how confident the AI assistant was and whether or not to escelate to humans.
```ts common-tool-schemas.ts.ts
/* example classifiers for answer confidence */
const answerConfidence = z
.union([
z.literal("very_confident").describe(`
The AI Assistant provided a complete and direct answer to all parts of the User Question.
The answer fully resolved the issue without requiring any further action from the User.
Every part of the answer was cited from the information sources.
The assistant did not ask for more information or provide options requiring User action.
This is the highest Answer Confidence level and should be used sparingly.
`),
z.literal("somewhat_confident").describe(`
The AI Assistant provided a complete and direct answer to the User Question, but the answer contained minor caveats or uncertainties.
Examples:
β’ The AI Assistant asked follow-up questions to the User
β’ The AI Assistant requested additional information from the User
β’ The AI Assistant suggested uncertainty in the answer
β’ The AI Assistant answered the question but mentioned potential exceptions
`),
z.literal("not_confident").describe(`
The AI Assistant tried to answer the User Question but did not fully resolve it.
The assistant provided options requiring further action from the User, asked for more information, showed uncertainty,
suggested the user contact support or provided contact information, or provided an indirect or incomplete answer.
This is the most common Answer Confidence level.
Examples:
β’ The AI Assistant provided a general answer not directly related to the User Question
β’ The AI Assistant said to reach out to support or provided an email address or contact information
β’ The AI Assistant provided options that require further action from the User to resolve the issue
`),
z.literal("no_sources").describe(`
The AI Assistant did not use or cite any sources from the information sources to answer the User Question.
`),
z.literal("other").describe(`
The User Question is unclear or unrelated to the subject matter.
`),
])
.describe(
"A measure of how confidently the AI Assistant completely and directly answered the User Question."
);
const provideAnswerConfidenceSchema = z.object({
explanation: z
.string()
.describe(
"A brief few word justification of why a specific confidence level was chosen."
),
answerConfidence,
});
```
### Sales Signals Tool
Use this schema as the parameters for a `detectSalesSignal` tool to identify sales signals. Leverage this to link them to a sign up flow, talk to sales, or perform an upgrade.
```ts common-tool-schemas.ts.ts
const salesSignalType = z
.union([
z.literal("requested_sales_contact").describe(`
The user has explicitly asked to speak with a sales representative or sales team.
Examples:
β’ "Can I talk to someone from sales?"
β’ "How do I contact your sales team?"
β’ "I'd like to schedule a call with a sales rep"
β’ "Is there someone I can talk to about purchasing?"
`),
z.literal("pricing_inquiry").describe(`
The user has asked about pricing, costs, billing, or payment options.
Examples:
β’ "How much does this service cost?"
β’ "What's the pricing for the enterprise plan?"
β’ "Do you offer annual billing discounts?"
β’ "What would it cost for our team of 50 people?"
`),
z.literal("enterprise_features").describe(`
The user has inquired about enterprise-specific features, capabilities, or requirements.
Examples:
β’ "Do you support SSO integration?"
β’ "What security certifications do you have?"
β’ "Is there an on-premise deployment option?"
β’ "Do you have custom SLAs for enterprise customers?"
`),
z.literal("upgrade_inquiry").describe(`
The user has asked about upgrading their current plan or moving to a higher tier.
Examples:
β’ "How do I upgrade to the Pro plan?"
β’ "What's involved in moving from Basic to Enterprise?"
β’ "I'm hitting limits on my current plan and need to upgrade"
β’ "What additional features do I get if I upgrade?"
`),
z.literal("implementation_services").describe(`
The user has asked about professional services, implementation support, or consulting.
Examples:
β’ "Do you offer implementation services?"
β’ "Can you help us migrate our data?"
β’ "Do you have consultants who can help us set this up?"
β’ "What kind of onboarding support do you provide?"
`),
z.literal("comparison_competitive").describe(`
The user is comparing the product with competitors or alternatives.
Examples:
β’ "How do you compare to [Competitor]?"
β’ "What makes your solution better than [Alternative]?"
β’ "Why should we choose you instead of [Competitor]?"
β’ "What's your advantage over other solutions?"
`),
z.literal("trial_demo_request").describe(`
The user has requested a product demo or trial.
Examples:
β’ "Can I get a demo of your product?"
β’ "How do I sign up for a trial?"
β’ "I'd like to see the product in action"
β’ "Do you offer proof of concept engagements?"
`),
])
.describe("Specific type of sales signal detected in the user's question");
const detectedSalesSignal = z.object({
explanation: z
.string()
.describe(
"A brief few word justification of why a specific sales signal was chosen."
),
type: salesSignalType,
});
```
### Annotation Tool
Use this schema as the parameters for an `annotateQuestion` tool to classify user questions and analyze AI responses. These annotations can help improve your AI system by identifying content gaps, sentiment patterns, and question types.
```ts custom-annotations-schema.ts
/* Basic sentiment classification */
const sentimentEnum = z
.enum(["positive", "negative", "neutral"])
.describe(
"The user's expressed sentiment in their question or message. Keep to neutral unless clearly negative or positive. A user factually stating their bug or issue is not negative."
);
/* Enhanced question type classification */
const questionTypeEnum = z
.enum([
"how_to",
"troubleshooting",
"feature_request",
"comparison",
"pricing",
"billing",
"support_request",
"account_issue",
"other",
])
.describe(
"The general category or intent of the user's question. Consider whether the question relates to your product or third-party integrations."
);
/* Content gap classification using yes/no/not applicable */
const yesNoNaEnum = z
.enum(["yes", "no", "n/a"])
.describe(
"Use n/a if it doesn't seem like the classifier is applicable or relevant to the question-answer pair."
);
/* Main annotation schema combining all classifiers */
const annotationSchema = z.object({
/* Sentiment analysis */
sentiment: sentimentEnum,
/* Question classification */
questionType: questionTypeEnum,
/* Content gap analysis */
isDocumented: yesNoNaEnum.describe(
"Whether an answer to the user's question is fully and explicitly documented in available sources. Use 'yes' only if complete information was found in documentation."
),
isFeatureSupported: yesNoNaEnum.describe(
"Whether a feature or capability the user is asking about is directly supported. Use 'no' if it's only partially supported or requires workarounds."
),
});
/* Example usage in a tool definition */
const annotateQuestionSchema = z.object({
annotation: annotationSchema,
});
```
***
title: UI Components Release Notes
sidebarTitle: Release notes
keywords: UI components changelog, release history, version updates, bug fixes, feature releases, npm packages, JavaScript components, React components, UI updates, component library, integration updates, SDK versions, UI improvements, component versioning, package updates
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Release notes
### Version 0.5.91
* Add prop to theme to disable loading the default font `disableLoadingDefaultFont`.
```bash
npm install @inkeep/cxkit-react@0.5.91
```
```html
```
```html
```
***
### Version 0.5.90
* Improve Mintlify integration.
```bash
npm install @inkeep/cxkit-react@0.5.90
```
```html
```
```html
```
***
### Version 0.5.89
* Add missing alt tag to chat button icon image.
* Support markdown in the form description.
* Make `successView` prop optional in `FormSettings`.
* Bug fix for button label not being applied to the submit button.
```bash
npm install @inkeep/cxkit-react@0.5.89
```
```html
```
```html
```
***
### Version 0.5.88
* Bug fix for Fern integration.
```bash
npm install @inkeep/cxkit-react@0.5.88
```
```html
```
```html
```
***
### Version 0.5.87
```bash
npm install @inkeep/cxkit-react@0.5.87
```
```html
```
```html
```
***
### Version 0.5.86
* Add close button to the [Sidebar Chat](/ui-components/js-snippet/sidebar-chat) component.
```bash
npm install @inkeep/cxkit-react@0.5.86
```
```html
```
```html
```
***
### Version 0.5.83
* Add the ability to control the open state of the new [Sidebar Chat](/ui-components/js-snippet/sidebar-chat) component.
```bash
npm install @inkeep/cxkit-react@0.5.83
```
```html
```
```html
```
***
### Version 0.5.82
* Add a `triggerSelector` prop to the `modalSettings`, this allows you to specify a custom selector to trigger the modal without needing to implement your own `onOpenChange` handler or keep track of the open state.
```bash
npm install @inkeep/cxkit-react@0.5.82
```
```html
```
```html
```
***
### Version 0.5.81
* New `SidebarChat` component, see [Sidebar Chat](/ui-components/js-snippet/sidebar-chat) or [Sidebar Chat (React)](/ui-components/react/sidebar-chat) for more details.
```bash
npm install @inkeep/cxkit-react@0.5.81
```
```html
```
```html
```
***
### Version 0.5.80
* Pin `react-remove-scroll` to version `2.6.3` to fix an uncaught error in the latest version.
```bash
npm install @inkeep/cxkit-react@0.5.80
```
```html
```
```html
```
***
### Version 0.5.79
* Add global error boundary to all components
* Prevent errors from propagating to the parent
```bash
npm install @inkeep/cxkit-react@0.5.79
```
```html
```
```html
```
***
### Version 0.5.78
* Small style fix for conflict with Tailwind version 4
```bash
npm install @inkeep/cxkit-react@0.5.78
```
```html
```
```html
```
***
### Version 0.5.77
* Fix bug with events in shared chats
```bash
npm install @inkeep/cxkit-react@0.5.77
```
```html
```
```html
```
***
### Version 0.5.76
* Add `analyticsProperties` to `baseSettings` to allow for custom properties to be sent to analytics
* Update `UserProperties` type to allow for custom properties
```bash
npm install @inkeep/cxkit-react@0.5.76
```
```html
```
```html
```
***
### Version 0.5.75
* Remove `react-icons` dependency
* Add `data-has-message-buttons` attribute to the message container when message buttons are rendered as a result of a tool call
```bash
npm install @inkeep/cxkit-react@0.5.75
```
```html
```
```html
```
***
### Version 0.5.73
* Add prop `askAICardLabel` to customize the label of the ask AI card separately from the ask AI toggle label
```bash
npm install @inkeep/cxkit-react@0.5.73
```
```html
```
```html
```
***
### Version 0.5.72
* Minor UI adjustments
```bash
npm install @inkeep/cxkit-react@0.5.72
```
```html
```
```html
```
***
### Version 0.5.71
* Ask ai query animation
```bash
npm install @inkeep/cxkit-react@0.5.71
```
```html
```
```html
```
***
### Version 0.5.70
* Add toolcalls to events
```bash
npm install @inkeep/cxkit-react@0.5.70
```
```html
```
```html
```
***
### Version 0.5.69
* Support copying as html
```bash
npm install @inkeep/cxkit-react@0.5.69
```
```html
```
```html
```
***
### Version 0.5.66
* Fix bug with `shouldAutoFocusInput` prop not working as expected
* Release new Fern integration package `@inkeep/cxkit-fern`, see [here](/integrations/fern) for details
```bash
npm install @inkeep/cxkit-react@0.5.66
```
```html
```
```html
```
***
### Version 0.5.64
* Add events for `modal_opened` and `modal_closed`
* Tweak dual pane search ui spacing
```bash
npm install @inkeep/cxkit-react@0.5.64
```
```html
```
```html
```
***
### Version 0.5.63
* Add styles to collapse the search bar for small screens to the docusaurus package
```bash
npm install @inkeep/cxkit-react@0.5.63
```
```html
```
```html
```
***
### Version 0.5.62
* Fix incompatible deps
* Decrease animation time when opening modal
```bash
npm install @inkeep/cxkit-react@0.5.62
```
```html
```
```html
```
***
### Version 0.5.59
* Improve prompting for the intelligent form
* Small bug fix
```bash
npm install @inkeep/cxkit-react@0.5.59
```
```html
```
```html
```
***
### Version 0.5.58
* Fix prefilling in the intelligent form
```bash
npm install @inkeep/cxkit-react@0.5.58
```
```html
```
```html
```
***
### Version 0.5.57
* Small bug fix search breadcrumbs casing
```bash
npm install @inkeep/cxkit-react@0.5.57
```
```html
```
```html
```
***
### Version 0.5.56
* Add default z-index to chat button
```bash
npm install @inkeep/cxkit-react@0.5.56
```
```html
```
```html
```
***
### Version 0.5.55
* Accessibility improvements
```bash
npm install @inkeep/cxkit-react@0.5.55
```
```html
```
```html
```
***
### Version 0.5.52
* Small style bug fix
```bash
npm install @inkeep/cxkit-react@0.5.52
```
```html
```
```html
```
***
### Version 0.5.51
* Add more built-in icons
```bash
npm install @inkeep/cxkit-react@0.5.51
```
```html
```
```html
```
***
### Version 0.5.50
* Bug fix for event logging
```bash
npm install @inkeep/cxkit-react@0.5.50
```
```html
```
```html
```
***
### Version 0.5.49
* Implement focus trap for modal
```bash
npm install @inkeep/cxkit-react@0.5.49
```
```html
```
```html
```
***
### Version 0.5.48
* Bug fix
```bash
npm install @inkeep/cxkit-react@0.5.48
```
```html
```
```html
```
***
### Version 0.5.47
* Bug fix
```bash
npm install @inkeep/cxkit-react@0.5.47
```
```html
```
```html
```
***
### Version 0.5.46
* Fix for disclaimer tooltip on mobile
```bash
npm install @inkeep/cxkit-react@0.5.46
```
```html
```
```html
```
***
### Version 0.5.45
* Bug fix
```bash
npm install @inkeep/cxkit-react@0.5.45
```
```html
```
```html
```
***
### Version 0.5.44
* Add conversation context to onToolCall
```bash
npm install @inkeep/cxkit-react@0.5.44
```
```html
```
```html
```
***
### Version 0.5.43
* Add `onToolCall` callback
```bash
npm install @inkeep/cxkit-react@0.5.43
```
```html
```
```html
```
***
### Version 0.5.42
* Bundle cxkit-js package into cxkit-mintlify
```bash
npm install @inkeep/cxkit-react@0.5.42
```
```html
```
```html
```
***
### Version 0.5.40
* Add new Mintlify integration package `@inkeep/cxkit-mintlify`, see [here](/integrations/mintlify) for details
```bash
npm install @inkeep/cxkit-react@0.5.40
```
```html
```
***
### Version 0.5.39
* Improve search result rendering
```bash
npm install @inkeep/cxkit-react@0.5.39
```
```html
```
***
### Version 0.5.37
* Add support for tool calls see [here](/ui-components/tools/overview) for details
```bash
npm install @inkeep/cxkit-react@0.5.37
```
```html
```
***
### Version 0.5.36
* Small bug fix
```bash
npm install @inkeep/cxkit-react@0.5.36
```
```html
```
***
### Version 0.5.35
* Small bug fix
```bash
npm install @inkeep/cxkit-react@0.5.35
```
```html
```
***
### Version 0.5.34
* Add js package types to `@inkeep/cxkit-types`
```bash
npm install @inkeep/cxkit-react@0.5.34
```
```html
```
***
### Version 0.5.33
* Tweak dual pane search styles
```bash
npm install @inkeep/cxkit-react@0.5.33
```
```html
```
***
### Version 0.5.32
* Fix search result item previews in dual-pane search
```bash
npm install @inkeep/cxkit-react@0.5.32
```
```html
```
***
### Version 0.5.31
* Add a new prop to search settings called `view` which can be `single-pane` (default) or `dual-pane`, this prop determines whether to render the search results in a single list or a two pane view with a list of results on the left and a preview of the content on the right
```bash
npm install @inkeep/cxkit-react@0.5.31
```
```html
```
***
### Version 0.5.30
* Small bug fix for message id generation
```bash
npm install @inkeep/cxkit-react@0.5.30
```
```html
```
***
### Version 0.5.20
* Bug fix for duplicate breadcrumb keys
```bash
npm install @inkeep/cxkit-react@0.5.20
```
```html
```
***
### Version 0.5.18
* Fix id collision in the js package
```bash
npm install @inkeep/cxkit-react@0.5.18
```
```html
```
***
### Version 0.5.17
* Use first tab as default tab
```bash
npm install @inkeep/cxkit-react@0.5.17
```
```html
```
***
### Version 0.5.16
* Bundle types
```bash
npm install @inkeep/cxkit-react@0.5.16
```
```html
```
***
### Version 0.5.15
* Configure Webpack to resolve JavaScript modules
```bash
npm install @inkeep/cxkit-react@0.5.15
```
```html
```
***
### Version 0.5.11 `@inkeep/cxkit-react`
#### Breaking changes
#### [Base Settings](/ui-components/common-settings/base)
**Removed:**
* `integrationId`
* `organizationId`
* `userType`
* `remoteErrorLogsLevel`
* `consoleDebugLevel`
* `customCardSettings` (use [transformSource](/ui-components/common-settings/base#source-transformation) instead)
* `breadcrumbRules` (use [transformSource](/ui-components/common-settings/base#source-transformation) instead)
* `stringReplacementRules` (use [transformSource](/ui-components/common-settings/base#source-transformation) instead)
**Changed:**
* `userId`, `userEmail`, `userName` were renamed and are now under `userProperties`:
```ts
userProperties: {
id: "user-456",
email: "jane@enterprise.com",
name: "Jane Smith",
cohorts: ["admin", "engineering"],
}
```
* `userToken` -> `userAuthToken`
* The `logEventCallback` was renamed to `onEvent` and the `InkeepCallbackEvent` type has changed, see [here](/ui-components/common-settings/base#event-handling) for details
* The event names and structure have also changed, see [here](/ui-components/customization-guides/use-your-own-analytics#events-reference) for details
* `optOutAnalyticalCookies`, `optOutAllAnalytics`, `optOutFunctionalCookies` are now under `privacyPreferences`:
```ts
privacyPreferences: {
optOutAnalyticalCookies: false,
optOutAllAnalytics: false,
optOutFunctionalCookies: false,
}
```
* `chatApiProxyDomain` -> `aiApiBaseUrl`
* `analyticsApiProxyDomain` -> `analyticsApiBaseUrl`
* `env` options are now lower case: `"development" | "production"`
* `appendQueryParamsToUrls` -> `urlQueryParamsToAppend`
* `colorMode` now allows for more robust synchronization, see [here](/ui-components/common-settings/base#color-mode) for details
* `stylesheets` and `stylesheetUrls` were renamed to `styles` see [here](/ui-components/customization-guides/style-components#custom-styles) for details
* Updated classnames can be found [here](/ui-components/customization-guides/style-components#component-class-names)
#### [AI Chat Settings](/ui-components/common-settings/ai-chat)
**Removed:**
* `isControlledMessage`
* `includeAIAnnotations` (equivalent functionality coming soon)
* `aiAnnotationPolicies` (equivalent functionality coming soon)
**Changed:**
* `botName` -> `aiAssistantName`
* `botAvatarSrcUrl` -> `aiAssistantAvatar`
* `botAvatarDarkSrcUrl` -> can be configured by passing an object with `light` and `dark` URLs for different theme modes:
```typescript
// Single URL
aiAssistantAvatar: "/assets/assistant.png"
// Or light/dark mode URLs
aiAssistantAvatar: {
light: "/assets/assistant-light.png",
dark: "/assets/assistant-dark.png"
}
```
* `userAvatarSrcUrl` -> `userAvatar`
* `quickQuestions` -> `exampleQuestions`
* `quickQuestionsLabel` -> `exampleQuestionsLabel`
* `shouldHighlightFirstQuickQuestion` -> `isFirstExampleQuestionHighlighted`
* `disclaimerSettings` properties were renamed:
```ts
disclaimerSettings: {
isEnabled: true,
label: "AI Assistant",
tooltip: "Responses are AI-generated and may require verification.",
},
```
* `handleMessageChange` -> `onInputMessageChange`
* `getHelpCallToActions` -> `getHelpOptions` types and form configurations have changed, see [here](/ui-components/common-settings/actions) for details
* The `FormConfig` type was renamed to `AIChatFormSettings` has and the configuration has changed, see [here](/ui-components/common-settings/actions#formconfig-reference) for details.
* `isChatSharingEnabled` -> `isShareButtonVisible`
* `shouldShowCopyChatButton` -> `isCopyChatButtonVisible`
* `actionButtonLabels` -> `toolbarButtonLabels`
* Within `toolbarButtonLabels`:
* `clearButtonLabel` -> `clear`
* `shareButtonLabel` -> `share`
* `getHelpButtonLabel` -> `getHelp`
* `stopButtonLabel` -> `stop`
* `copyChatButtonLabel` -> `copyChat`
* `context` use `prompts` instead, see [here](/ui-components/customization-guides/custom-instructions) for details
* `guidance` use `prompts` instead, see [here](/ui-components/customization-guides/custom-instructions) for details
#### [Search Settings](/ui-components/common-settings/search)
**Removed:**
* `isControlledSearchQuery`
**Changed:**
* `prefilledQuery` -> `defaultQuery`
* `handleSearchQueryChange` -> `onQueryChange`
* `tabSettings` -> `tabs` and type has changed, see [here](/ui-components/common-settings/search#search-tabs) for details
* `shouldShowAskAICard` was moved to be a top level prop
* `maximumHitsLimit` -> `maxResults`
* `debounceTime` -> `debounceTimeMs`
#### Modal Settings
**Removed:**
* `isShortcutKeyEnabled` pass `shortcutKey` as `null` to disable the shortcut key or pass a key to enable it
* `isAlignedToTop`
* `isAlignedToRight`
* `onShortcutKeyPressed`
**Changed:**
* `openShortcutKey` -> `shortcutKey`
* `askAILabel` was moved to be a top level prop
* `switchToSearchMessage` -> `searchLabel` and was moved to be a top level prop
* `isModeSwitchingEnabled` -> `canToggleView` and was moved to be a top level prop
* `forceInitialDefaultView` -> `forceDefaultView` and was moved to be a top level prop
#### Chat Button
**Removed:**
* `chatButtonType`
* `chatButtonBgColor` can be change via css using this className `.ikp-chat-button__button`
* `chatButtonBgColorDarkMode` can be change via css using this className `[data-theme='dark'] .ikp-chat-button__button`
* `isPositionFixed` can be change via css by setting `position: relative;` on this className `.ikp-chat-button__container`
* `fixedPositionXOffset` can be change via css by setting `right: 0;` on this className `.ikp-chat-button__container`
* `fixedPositionYOffset` can be change via css by setting `bottom: 0;` on this className `.ikp-chat-button__container`
**Changed:**
* `chatButtonText` -> `label`
#### Custom Trigger
**Changed:**
* This component was renamed to `ModalSearchAndChat` for both search and chat functionality or `ModalSearch` for just search functionality or `ModalChat` for just chat functionality see [here](/ui-components/react/custom-modal-trigger) for details.
* `isOpen` was moved inside `modalSettings`
* `onOpen` -> `onOpenChange` (moved inside `modalSettings`)
* `onClose` -> can utilize `onOpenChange` (moved inside `modalSettings`)
#### JS Snippet
* The interface for using the js snippet has changed, see [here](/ui-components/js-snippet) for details
#### Docusaurus
* The interface for adding and configuring the Docusaurus plugin has changed, see [here](/integrations/docusaurus/chat-button-and-search-bar) for details.
### API keys
* Production API keys for web integrations are now required to have `Enforce referrer URL` enabled for additional security, see [here](/ui-components/public-api-keys#referrer-url) for details. API keys without this setting will be severely rate limited.
#### New
* Intelligent form component see [here](/ui-components/common-settings/form) for details
* Embedded search component see [here](/ui-components/react/in-page/embedded-search) for details
* Embedded search and chat component see [here](/ui-components/react/in-page/embedded-search-and-chat) for details
```bash
npm install @inkeep/cxkit-react@0.5.11
```
```html
```
***
### Version 0.3.19
* Minor bug fix for search result titles.
```bash
npm install @inkeep/uikit@0.3.19
```
```html
```
***
### Version 0.3.18
* Minor bug fixes.
```bash
npm install @inkeep/uikit@0.3.18
```
```html
```
***
### Version 0.3.17
* Fix bug with modal closing unexpectedly in mobile view.
```bash
npm install @inkeep/uikit@0.3.17
```
```html
```
***
### Version 0.3.16
* Added `name` property to `get_help_option_clicked` event.
```bash
npm install @inkeep/uikit@0.3.16
```
```html
```
***
### Version 0.3.15
* Added `pinToToolbar` prop on `GetHelpCallToAction`. See [here](/ui-components/common-settings/ai-chat#gethelpcalltoaction) for more details.
* Minor bug fixes.
```bash
npm install @inkeep/uikit@0.3.15
```
```html
```
***
### Version 0.3.14
* Fix list style bug.
```bash
npm install @inkeep/uikit@0.3.14
```
```html
```
***
### Version 0.3.13
* Added a prop `forceInitialDefaultView` to `modalSettings` to allow modal to open in a certain view, regardless of which view was last opened. See [modalSettings](/ui-components/common-settings/modal#inkeepmodalsettings) for more details.
```bash
npm install @inkeep/uikit@0.3.13
```
```html
```
***
### Version 0.3.12
* Fix export for `InkeepEvent` types.
```bash
npm install @inkeep/uikit@0.3.12
```
```html
```
***
### Version 0.3.11
* Added optional `searchQueryParamKey` prop to `searchSettings`.
* Added event logging for search result clicks.
* Made the default placeholder text 'Search...' for small screens.
```bash
npm install @inkeep/uikit@0.3.11
```
```html
```
***
### Version 0.3.10
* Exposed the `SearchFunctions` in the embed js package.
* Fixed `targetElement` being marked as required for `ChatButton` and `CustomTrigger` component types in the embed js package.
```bash
npm install @inkeep/uikit@0.3.10
```
```html
```
***
### Version 0.3.9
* Added a prop called `shouldShowCopyChatButton` to `aiChatSettings`, when enabled this will show a button to allow users to copy their entire conversation as markdown.
* Added `messages` and `chatSessionId` as arguments to the `InvokeCallbackAction` for `GetHelpCallToAction` and `ShowEscalateToSupportButtonAction`.
* Added analytics events for when a user clicks a get help menu item or support button.
* Minor UI / bug fixes.
```bash
npm install @inkeep/uikit@0.3.9
```
```html
```
***
### Version 0.3.8
* Added `SELECT` field type to support form. See [here](/ui-components/customization-guides/embedded-support-form#formfield) for details.
* Added support for markdown strings in the `message` prop of the `SuccessConfirmationPageProps`. See [here](/ui-components/customization-guides/embedded-support-form#successconfirmationpageprops) for details.
```bash
npm install @inkeep/uikit@0.3.8
```
```html
```
***
### Version 0.3.7
* Small bug fix.
```bash
npm install @inkeep/uikit@0.3.7
```
```html
```
***
### Version 0.3.6
* Small style fix.
```bash
npm install @inkeep/uikit@0.3.6
```
```html
```
***
### Version 0.3.5
* Update license field.
* Small style tweak.
```bash
npm install @inkeep/uikit@0.3.5
```
```html
```
***
### Version 0.3.4
* Minor UI improvements.
```bash
npm install @inkeep/uikit@0.3.4
```
```html
```
***
### Version 0.3.1
* Minor UI improvements.
```bash
npm install @inkeep/uikit@0.3.1
```
```html
```
***
### Version 0.3.0 `@inkeep/uikit`
* We have renamed the `@inkeep/widgets` and `@inkeep/widgets-embed` packages to `@inkeep/uikit` and `@inkeep/uikit-js` respectively. Links to new packages can be found here: [uikit](https://www.npmjs.com/package/@inkeep/uikit) / [uikit-js](https://www.npmjs.com/package/@inkeep/uikit-js).
* This new package contains a significant change to the search ui, moving from a two pane search result view to a single pane view with support for keyboard navigation.
**Additions**
* New prop in `searchSettings` `shouldShowAskAICard` to control whether or not to show the `Ask AI ""` card in the search results. Default `true`.
#### Breaking changes
* Renamed the following options for `chatButtonType`: `ICON_TEXT` is now `PILL` and `ICON_TEXT_SHORTCUT` is now `RECTANGLE_SHORTCUT`.
* Renamed the type `InkeepWidgetBaseSettings` to `InkeepBaseSettings`.
* Consolidated `chatButtonPillText` and `chatButtonCommandText` into a single prop `chatButtonText`.
* Moved `stylesheets` and `stylesheetUrls` props into `theme` (within `baseSettings`).
* `switchToChatMessage` is now `askAILabel` and will apply to both the `Ask AI ""` card in the search results and to the toggle to switch to chat.
* `submitOnEnterOnly` prop was removed from `searchSettings`.
* Removed support for passing `colorMode` in the `theme` (which was deprecated in version `0.2.247`), `colorMode` will only be supported in `baseSettings`.
* Removed support for passing `highlighterTheme` in `baseSettings` (which was deprecated in version `0.2.247`), `syntaxHighlighter` will only be supported in the `theme`.
* Removed no longer used `CustomIcons`: `linkIndicator`, `newLine`, and `enter`.
* Removed `shouldAnimateSwitchToChatButton` prop, the animation was removed since button was changed to a toggle.
* Updated and removed some classnames to match ui changes.
**Added**:
* `.ikp-ask-ai-card`
* `.ikp-search-result-line__first`
* `.ikp-search-result-line__second`
**Removed**:
* `.ikp-switch-to-chat-button`
* `.ikp-switch-to-chat-button__shortcut`
* `.ikp-enter-icon`
* `.ikp-heading-tree__title`
* `.ikp-heading-tree__list`
* `.ikp-heading-tree__item`
* `.ikp-heading-tree__heading`
* `.ikp-new-line-icon`
* `.ikp-preview-content-header__heading`
* `.ikp-preview-content-header__title`
* `.ikp-link-indicator-icon`
```bash
npm install @inkeep/uikit@0.3.0
```
```html
```
***
### Version 0.2.289
* Update license.
* Fix bug with duplicate titles in mobile view.
```bash
npm i @inkeep/widgets@0.2.289
```
```html
```
***
### Version 0.2.286
* Allow users to pass in query params to append to documentation links. See `appendQueryParamsToUrls` in [baseSettings](/ui-components/common-settings/base) for more details.
***
### Version 0.2.285
* Fix small style bug.
***
### Version 0.2.284
* Allow users to pass in their own instance of Prism js to avoid conflicts in the global namespace.
***
### Version 0.2.282
* Fix being able to style the switch to chat button with custom css.
***
### Version 0.2.281
* Fixes to support for react 19.
***
### Version 0.2.280
* Remove apollo dev tools console message.
***
### Version 0.2.279
* Bug fix to improve multi language support.
***
### Version 0.2.278
* Bug fixes.
***
### Version 0.2.276
* Fallback to default bot avatar if user provided bot avatar doesn't load.
* Improve styling for docs search preview.
***
### Version 0.2.275
* Added a file input type to the support form.
***
### Version 0.2.274
* Added a prop to change the chat button color. See [here](/ui-components/react/chat-button#properties) for more details.
***
### Version 0.2.272
* Add workflowId to `chat_message_submitted` and `chat_message_bot_response_received` events.
***
### Version 0.2.271
* Add info tooltip for workflow attachments.
***
### Version 0.2.270
* Minor style tweak.
***
### Version 0.2.269
* Exposed the `AIChatFunctions` in the embed js package.
* Added `openForm` to `AIChatFunctions` so it can be triggered from outside the widget. See [here](/ui-components/common-settings/ai-chat#aichatfunctions) for more details.
* Added `closeFormAction` to `FormConfig`. See [here](/ui-components/customization-guides/embedded-support-form#formconfig) for more details.
#### Breaking changes
* Removed `backToChatButtonLabel` from `SuccessConfirmationPageProps` and replaced with `SuccessConfirmationButton`. See [here](/ui-components/customization-guides/embedded-support-form#successconfirmationbutton) for more details.
***
### Version 0.2.268
* Add switch to chat and submit hot key (cmd + enter)
* Fix bug with prefilled query not showing in search bar
* Fix low chroma primary color derivatives calculations
* Use filled sparkles for default icon in chat component
***
### Version 0.2.267
* Adding additional class names for stylization.
***
### Version 0.2.266
* Minor bug fixes
***
### Version 0.2.265
* Edit default disclaimer copy.
***
### Version 0.2.264
* Added support for `CustomIcons`. Refer to [custom icons](/ui-components/customization-guides/style-components#custom-icons) for details.
***
### Version 0.2.263
* Added support for a new `GetHelpCallToAction` and `ShowEscalateToSupportButtonAction`. Refer to [get help call to actions](/ui-components/common-settings/ai-chat#gethelpcalltoactioninvokecallback) and [support workflows](/ui-components/customization-guides/embedded-support-form#invokecallbackaction) for details.
* Fix for highlighting search text in dark mode.
***
### Version 0.2.262
* Minor UI improvements.
***
### Version 0.2.261
* Added support workflows feature. Refer to [Support workflows](/ui-components/customization-guides/workflows) for details.
* Minor UI improvements.
***
### Version 0.2.260
* Minor bug fixes.
***
### Version 0.2.259
* Adding `context` and `guidance` to `AIChatSettings` for providing dynamic information and instructions to the bot.
***
### Version 0.2.258
* Fix copy button tooltip.
* Add default targetElement for the `ChatButton` and `CustomTrigger` in the js snippet.
* Add `colorModeSync` logic to the js snippet.
***
### Version 0.2.256
* Fix to close modal if clicking on a search result link within the same page and `shouldOpenLinksInNewTab` is `false`.
***
### Version 0.2.254
* Fix bug with loading stylesheets.
***
### Version 0.2.253
* Deep merge properties in the `widgets-embed` package to improve devx.
* Add fallback targetEl in the `widgets-embed` package.
***
### Version 0.2.252
* Update default AI assistant avatar.
***
### Version 0.2.250
* Add `data-state="active"` to the thumbs up and thumbs down buttons after the relative feedback has been submitted, by default they will have `data-state="inactive"`. This can be used to style the buttons differently after feedback submission.
***
### Version 0.2.249
* Fix bug with chat button `fixedPositionXOffset` and `fixedPositionYOffset` props not being applied.
* Add `shrink` size variant for the `SearchBarTrigger` component, this variant will shrink the search bar to just the search icon for the smallest screen sizes.
***
### Version 0.2.248
#### Breaking changes
* Changed the prop `areOpenHotKeysDisabled` to `isShortcutKeyEnabled` in `modalSettings`
* By default `isShortcutKeyEnabled` is `false` for all `InkeepChatButton` variants except `ICON_TEXT_SHORTCUT`, (it is `true` by default for the `InkeepSearchBar` and `InkeepCustomTrigger` components).
* By default the `openShortcutKey` is `/` for the `InkeepChatButton` component (it is still `k` for the `InkeepSearchBar` and `InkeepCustomTrigger` components).
***
### Version 0.2.247
* Added support for passing `colorMode` in `baseSettings`, passing in `colorMode` in `theme` is still supported but is deprecated.
* Added support for passing `syntaxHighlighter` in `theme`, passing in `baseSettings` (as `highlighterTheme`) is still supported but is deprecated.
* Changed the default `chatButtonType` to `ICON_TEXT`.
***
### Version 0.2.246
* Added loading state for AI chat when passing in the chatId prop.
***
### Version 0.2.245
* Added support for customizing the chat action button labels and switch to search button label.
***
### Version 0.2.244
* Added a prop to `SearchSettings` called `submitOnEnterOnly` which will submit search query on enter instead of onChange. Default is `false`.
***
### Version 0.2.243
* Added a prop to `AIChatSettings` called `chatId` which will load the chat corresponding to the id.
***
### Version 0.2.242
* Bumped dependencies to address vulnerability in `vite@4.4.11`.
***
### Version 0.2.241
* Fixed a bug where chat actions were only shown for most recent message.
***
### Version 0.2.238
* Added a prop to `ModalSettings` called `shouldAnimateSwitchToChatButton` which determines whether to animate the switch to chat button on first load. Default is `true`.
* Added a variant to the theme for the `SwitchToChat` button, example:
```js
const inkeepBaseSettings: InkeepBaseSettings = {
theme: {
components: {
SwitchToChat: {
defaultProps: {
variant: "subtle", // options are 'primary' or 'subtle'
},
},
},
},
};
```
***
title: Migrating to @inkeep/cxkit Overview
sidebarTitle: Overview
keywords: migration guide, cxkit migration, package migration, React migration, JavaScript migration, UI toolkit, customer experience toolkit, version upgrade, package update, migration process, component migration, SDK migration, library migration, package transition
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
With version 0.5.x, we've renamed our packages from `@inkeep/uikit` to `@inkeep/cxkit` to better reflect their purpose as customer experience toolkits.
## Choose Your Migration Path
Depending on how you're currently using Inkeep, you'll need to follow one of these migration guides:
### [React Migration Guide](/ui-components/migrate-to-cxkit/react)
If you're using React components from `@inkeep/uikit`, follow this guide to migrate to `@inkeep/cxkit-react`.
### [JavaScript Migration Guide](/ui-components/migrate-to-cxkit/javascript)
If you're using JavaScript snippets from `@inkeep/uikit-js`, follow this guide to migrate to `@inkeep/cxkit-js`.
## Need Help?
If you encounter any issues during migration, please [contact our support team](https://inkeep.com/contact) for assistance.
***
title: Migrating from @inkeep/uikit-js to @inkeep/cxkit-js
sidebarTitle: To @inkeep/cxkit-js
keywords: JavaScript migration, cxkit migration, JavaScript SDK, package migration, breaking changes, API updates, configuration changes, component initialization, JavaScript integration, migration guide, code updates, SDK migration, JavaScript toolkit, package transition, API migration
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
This guide will help you migrate your JavaScript snippets from using `@inkeep/uikit-js` to the new `@inkeep/cxkit-js` package. The new package includes several breaking changes but offers improved functionality and a more consistent API.
## Overview
With version 0.5.x, we've renamed our package from `@inkeep/uikit-js` to `@inkeep/cxkit-js` to better reflect its purpose as a customer experience toolkit. This change comes with several API improvements and breaking changes that require updates to your code.
## Installation
Update your script tag to use the new package:
```html
```
## Breaking Changes
### Component Initialization Changes
The way components are initialized has changed:
```javascript
// Old
const inkeepWidget = Inkeep().embed({
componentType: "ChatButton",
// ...
});
// New
const inkeepWidget = Inkeep.ChatButton({
// ...
});
```
### Configuration Structure Changes
The configuration structure has been simplified:
```javascript
// Old
const config = {
componentType: "ChatButton",
properties: {
chatButtonType: "PILL",
baseSettings: {
// ...
},
aiChatSettings: {
// ...
},
// ...
},
};
// New
const config = {
// Top-level properties
baseSettings: {
// ...
},
aiChatSettings: {
// ...
},
// ...
};
```
### Base Settings Changes
#### Removed Properties
##### `integrationId`
The `integrationId` property has been removed as it's no longer required for authentication. The API key now contains all the necessary information to identify your integration.
```javascript
// Old
baseSettings: {
apiKey: "your-api-key",
integrationId: "your-integration-id",
// ...
}
// New
baseSettings: {
apiKey: "your-api-key",
// No integrationId needed
}
```
##### `organizationId`
The `organizationId` property has been removed as it's no longer required for authentication. The API key now contains all the necessary information to identify your organization.
```javascript
// Old
baseSettings: {
apiKey: "your-api-key",
organizationId: "your-organization-id",
// ...
}
// New
baseSettings: {
apiKey: "your-api-key",
// No organizationId needed
}
```
##### `userType`
The `userType` property has been removed in favor of the more flexible `userProperties.cohorts` array, which allows you to specify multiple user types or roles.
```javascript
// Old
baseSettings: {
userType: "admin",
// ...
}
// New
baseSettings: {
userProperties: {
cohorts: ["admin", "engineering"],
// ...
},
// ...
}
```
##### `remoteErrorLogsLevel`
The `remoteErrorLogsLevel` property has been removed as error logging is now handled internally with improved defaults. If you need custom error handling, use the `onError` callback.
##### `consoleDebugLevel`
The `consoleDebugLevel` property has been removed as debugging is now handled internally with improved defaults. For development debugging, use the browser's developer tools.
##### `customCardSettings`
The `customCardSettings` property has been removed in favor of the more powerful and flexible `transformSource` function, which allows for more comprehensive customization of search results.
```javascript
// Old
baseSettings: {
customCardSettings: {
// Custom card settings
},
// ...
}
// New
baseSettings: {
transformSource: (source) => {
// Transform source data
return {
...source,
tabs: [] // Transform tabs
};
},
// ...
}
```
See [Source Transformation](/ui-components/customization-guides/source-transformation) for more details.
##### `breadcrumbRules`
The `breadcrumbRules` property has been removed in favor of the more powerful and flexible `transformSource` function, which allows for more comprehensive customization of breadcrumbs.
```javascript
// Old
baseSettings: {
breadcrumbRules: [
// Breadcrumb rules
],
// ...
}
// New
baseSettings: {
transformSource: (source) => {
// Transform breadcrumbs
return {
...source,
breadcrumbs: []
};
},
// ...
}
```
See [Source Transformation](/ui-components/customization-guides/source-transformation) for more details.
##### `stringReplacementRules`
The `stringReplacementRules` property has been removed in favor of the more powerful and flexible `transformSource` function, which allows for more comprehensive string transformations.
```javascript
// Old
baseSettings: {
stringReplacementRules: [
// String replacement rules
],
// ...
}
// New
baseSettings: {
transformSource: (source) => {
// Transform source data
return {
...source,
breadcrumbs: []
};
},
// ...
}
```
See [Source Transformation](/ui-components/customization-guides/source-transformation) for more details.
#### Renamed Properties
##### User Properties
User properties are now grouped under `userProperties`:
```javascript
// Old
baseSettings: {
userId: "user-456",
userEmail: "jane@enterprise.com",
userName: "Jane Smith",
// ...
}
// New
baseSettings: {
userProperties: {
id: "user-456",
email: "jane@enterprise.com",
name: "Jane Smith",
cohorts: ["admin", "engineering"],
},
// ...
}
```
##### Authentication Token
`userToken` β `userAuthToken`
```javascript
// Old
baseSettings: {
userToken: "jwt-token-for-user-authentication",
// ...
}
// New
baseSettings: {
userAuthToken: "jwt-token-for-user-authentication",
// ...
}
```
##### Event Handling
`logEventCallback` β `onEvent` (with updated event structure)
```javascript
// Old
baseSettings: {
logEventCallback: (event) => {
// Handle event
console.log(event);
},
// ...
}
// New
baseSettings: {
onEvent: (event) => {
// Handle event
console.log(event);
},
// ...
}
```
##### Privacy Preferences
Privacy preferences are now grouped:
```javascript
// Old
baseSettings: {
optOutAnalyticalCookies: false,
optOutAllAnalytics: false,
optOutFunctionalCookies: false,
// ...
}
// New
baseSettings: {
privacyPreferences: {
optOutAnalyticalCookies: false,
optOutAllAnalytics: false,
optOutFunctionalCookies: false,
},
// ...
}
```
##### API Endpoints
* `chatApiProxyDomain` β `aiApiBaseUrl`
* `analyticsApiProxyDomain` β `analyticsApiBaseUrl`
```javascript
// Old
baseSettings: {
chatApiProxyDomain: "https://api.inkeep.com/chat",
analyticsApiProxyDomain: "https://api.example.com/analytics",
// ...
}
// New
baseSettings: {
aiApiBaseUrl: "https://api.inkeep.com/chat",
analyticsApiBaseUrl: "https://api.example.com/analytics",
// ...
}
```
##### Environment Configuration
`env` options are now lowercase: `"development" | "production"`
```javascript
// Old
baseSettings: {
env: "DEVELOPMENT",
// ...
}
// New
baseSettings: {
env: "development",
// ...
}
```
##### URL Parameters
`appendQueryParamsToUrls` β `urlQueryParamsToAppend`
```javascript
// Old
baseSettings: {
appendQueryParamsToUrls: { utm_source: "docs" },
// ...
}
// New
baseSettings: {
urlQueryParamsToAppend: { utm_source: "docs" },
// ...
}
```
##### Styling
`stylesheets` and `stylesheetUrls` β `styles`
```javascript
// Old
baseSettings: {
stylesheets: ["custom-styles.css"],
stylesheetUrls: ["https://example.com/styles.css"],
// ...
}
// New
baseSettings: {
styles: [
{
key: "google-fonts",
type: "link",
value: "https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap",
},
{
key: "custom-theme",
type: "style",
value: `
.ikp-ai-chat-message {
border-radius: 8px;
padding: 12px;
}
[data-theme='dark'] .ikp-ai-chat-message {
background: #2D3748;
}
`,
},
],
// ...
}
```
### Color Mode Synchronization
The color mode synchronization has been updated:
```javascript
// Old
colorModeSync: {
observedElement: document.documentElement,
isDarkModeCallback: (el) => {
return el.classList.contains("dark");
},
colorModeAttribute: "class",
}
// New
baseSettings: {
colorMode: {
sync: {
target: document.documentElement,
attributes: ["data-theme"],
isDarkMode: (attributes) => attributes["data-theme"] === "dark",
}
}
}
```
### AI Chat Settings Changes
#### Removed Properties
##### `isControlledMessage`
The `isControlledMessage` property has been removed as the component now uses a more intuitive controlled/uncontrolled pattern. Use the `defaultMessage` prop for uncontrolled behavior or the `message` and `onInputMessageChange` props for controlled behavior.
##### `includeAIAnnotations`
The `includeAIAnnotations` property has been removed as annotations are now handled internally with improved defaults. Equivalent functionality will be available in a future release.
##### `aiAnnotationPolicies`
The `aiAnnotationPolicies` property has been removed as annotation policies are now handled internally with improved defaults. Equivalent functionality will be available in a future release.
#### Renamed Properties
##### Assistant Name and Avatar
* `botName` β `aiAssistantName`
* `botAvatarSrcUrl` β `aiAssistantAvatar`
* `botAvatarDarkSrcUrl` β can be configured by changing `aiAssistantAvatar` to an object:
```javascript
// Old
aiChatSettings: {
botAvatarSrcUrl: "/assets/assistant.png",
botAvatarDarkSrcUrl: "/assets/assistant-dark.png",
// ...
}
// New
aiChatSettings: {
aiAssistantAvatar: {
light: "/assets/assistant-light.png",
dark: "/assets/assistant-dark.png"
},
// ...
}
```
##### User Avatar
* `userAvatarSrcUrl` β `userAvatar`
```javascript
// Old
aiChatSettings: {
userAvatarSrcUrl: userProfile.avatarUrl,
// ...
}
// New
aiChatSettings: {
userAvatar: userProfile.avatarUrl,
// ...
}
```
##### Example Questions
* `quickQuestions` β `exampleQuestions`
* `quickQuestionsLabel` β `exampleQuestionsTitle`
* `shouldHighlightFirstQuickQuestion` β `isFirstExampleQuestionHighlighted`
```javascript
// Old
aiChatSettings: {
quickQuestions: ["What is the capital of France?", "What is the capital of Germany?"],
quickQuestionsLabel: "Example Questions",
shouldHighlightFirstQuickQuestion: true,
// ...
}
// New
aiChatSettings: {
exampleQuestions: ["What is the capital of France?", "What is the capital of Germany?"],
exampleQuestionsTitle: "Example Questions",
isFirstExampleQuestionHighlighted: true,
// ...
}
```
##### Disclaimer Settings
Disclaimer settings properties have been renamed:
```javascript
// Old
aiChatSettings: {
disclaimerSettings: {
isDisclaimerEnabled: true,
disclaimerLabel: "Usage policy",
disclaimerTooltip: "Information provided by AI is not guaranteed to be accurate.",
},
// ...
}
// New
aiChatSettings: {
disclaimerSettings: {
isEnabled: true,
label: "Usage policy",
tooltip: "Information provided by AI is not guaranteed to be accurate.",
},
// ...
}
```
##### Input Handling
* `handleMessageChange` β `onInputMessageChange`
```javascript
// Old
aiChatSettings: {
handleMessageChange: (message) => {
// Handle message change
console.log(message);
},
// ...
}
// New
aiChatSettings: {
onInputMessageChange: (message) => {
// Handle message change
console.log(message);
},
// ...
}
```
##### Help Options
* `getHelpCallToActions` β `getHelpOptions`
```javascript
// Old
aiChatSettings: {
getHelpCallToActions: () => {
// Get help call to actions
return [
{
icon: { builtIn: 'FaDiscord' },
name: 'Discord',
url: 'https://inkeep.com/',
},
];
},
// ...
}
// New
aiChatSettings: {
getHelpOptions: () => {
// Get help options
return [
{
name: 'Discord',
icon: {
builtIn: 'FaDiscord',
},
action: {
type: 'open_link',
url: 'https://inkeep.com/',
},
},
];
},
// ...
}
```
##### Form Configuration
Form configuration has been updated with improved structuring. See [Form Settings](/ui-components/common-settings/form) for details:
```javascript
// Old
aiChatSettings: {
formConfig: {
// Basic form configuration
fields: [
{
type: "text",
name: "name",
label: "Name",
},
],
},
// ...
}
// New
aiChatSettings: {
formSettings: {
// Improved form settings structure
fields: [
{
type: "text",
name: "name",
label: "Name",
validation: {
required: true,
minLength: 2,
},
},
],
submitButton: {
label: "Submit",
},
onSubmit: (data) => {
console.log("Form submitted:", data);
},
},
// ...
}
```
##### Sharing and Toolbar
* `isChatSharingEnabled` β `isShareButtonVisible`
* `shouldShowCopyChatButton` β `isCopyChatButtonVisible`
* `actionButtonLabels` β `toolbarButtonLabels`
```javascript
// Old
aiChatSettings: {
isChatSharingEnabled: true,
shouldShowCopyChatButton: true,
actionButtonLabels: {
copy: "Copy Chat",
share: "Share Chat",
// ...
},
// ...
}
// New
aiChatSettings: {
isShareButtonVisible: true,
isCopyChatButtonVisible: true,
toolbarButtonLabels: {
copy: "Copy Chat",
share: "Share Chat",
// ...
},
// ...
}
```
##### Prompts
* `context` and `guidance` β use `prompts` instead
```javascript
// Old
aiChatSettings: {
context: "The user is new to the product.",
guidance: "Be concise.",
// ...
}
// New
aiChatSettings: {
prompts: [
"The user is new to the product.",
"Be concise."
],
// ...
}
```
### Search Settings Changes
#### Removed Properties
##### `isControlledSearchQuery`
The `isControlledSearchQuery` property has been removed as the component now uses a more intuitive controlled/uncontrolled pattern. Use the `defaultQuery` prop for uncontrolled behavior or the `query` and `onQueryChange` props for controlled behavior.
#### Renamed Properties
##### `prefilledQuery`
The `prefilledQuery` property has been renamed to `defaultQuery` for improved clarity and consistency:
```javascript
// Old
searchSettings: {
prefilledQuery: "How to get started",
// ...
}
// New
searchSettings: {
defaultQuery: "How to get started",
// ...
}
```
##### `handleSearchQueryChange`
The `handleSearchQueryChange` property has been renamed to `onQueryChange` for improved clarity:
```javascript
// Old
searchSettings: {
handleSearchQueryChange: (query) => {
// Handle query change
console.log(query);
},
// ...
}
// New
searchSettings: {
onQueryChange: (query) => {
// Handle query change
console.log(query);
},
// ...
}
```
##### `tabSettings`
The `tabSettings` property has been renamed to `tabs` for improved clarity and simplicity. See docs [here](/ui-components/common-settings/search#search-tabs) for more details:
```javascript
// Old
searchSettings: {
tabSettings: {
isAllTabEnabled: true,
rootBreadcrumbsToUseAsTabs: ['Docs'],
tabOrderByLabel: ['Resources', 'Blog', 'Solutions'],
disabledDefaultTabs: undefined, // string[] | undefined
alwaysDisplayedTabs: ['Blog'],
},
// ...
}
// New
searchSettings: {
// Basic tabs
tabs: ["All", "Publications", "GitHub", "Forums"],
// With always visible option
tabs: [
"All",
"Publications",
["GitHub", { isAlwaysVisible: true }],
"Forums",
],
// Hide "All" tab, show only Publications and GitHub
tabs: ["Publications", "GitHub"],
// No tabs (just show all results)
tabs: [],
// ...
}
```
##### `maximumHitsLimit`
The `maximumHitsLimit` property has been renamed to `maxResults` for improved clarity:
```javascript
// Old
searchSettings: {
maximumHitsLimit: 10,
// ...
}
// New
searchSettings: {
maxResults: 10,
// ...
}
```
##### `debounceTime`
The `debounceTime` property has been renamed to `debounceTimeMs` for improved clarity:
```javascript
// Old
searchSettings: {
debounceTime: 500,
// ...
}
// New
searchSettings: {
debounceTimeMs: 500,
// ...
}
```
##### `shouldShowAskAICard`
The `shouldShowAskAICard` property has been elevated to a top-level property:
```javascript
// Old
searchSettings: {
shouldShowAskAICard: true,
// ...
}
// New
shouldShowAskAICard: true, // Now a top-level property
```
### Modal Settings Changes
#### Removed Properties
##### `isShortcutKeyEnabled`
The `isShortcutKeyEnabled` property has been removed. To disable the shortcut key, pass `shortcutKey` as `null`, or pass a key to enable it:
```javascript
// Old
modalSettings: {
isShortcutKeyEnabled: false,
// ...
}
// New
modalSettings: {
shortcutKey: null, // Disables the shortcut key
// ...
}
```
##### `isAlignedToTop`
The `isAlignedToTop` property has been removed as modal positioning is now handled through CSS.
##### `isAlignedToRight`
The `isAlignedToRight` property has been removed as modal positioning is now handled through CSS.
##### `onShortcutKeyPressed`
The `onShortcutKeyPressed` property has been removed as shortcut key handling is now managed internally.
#### Renamed Properties
##### `openShortcutKey`
The `openShortcutKey` property has been renamed to `shortcutKey` for improved clarity:
```javascript
// Old
modalSettings: {
openShortcutKey: "k",
// ...
}
// New
modalSettings: {
shortcutKey: "k",
// ...
}
```
##### `askAILabel`
The `askAILabel` property has been moved to be a top-level property:
```javascript
// Old
modalSettings: {
askAILabel: "Ask AI",
// ...
}
// New
askAILabel: "Ask AI", // Now a top-level property
```
##### `switchToSearchMessage`
The `switchToSearchMessage` property has been renamed to `searchLabel` and moved to be a top-level property:
```javascript
// Old
modalSettings: {
switchToSearchMessage: "Search Documentation",
// ...
}
// New
searchLabel: "Search Documentation", // Now a top-level property
```
##### `isModeSwitchingEnabled`
The `isModeSwitchingEnabled` property has been renamed to `canToggleView` and moved to be a top-level property:
```javascript
// Old
modalSettings: {
isModeSwitchingEnabled: true,
// ...
}
// New
canToggleView: true, // Now a top-level property
```
##### `forceInitialDefaultView`
The `forceInitialDefaultView` property has been renamed to `forceDefaultView` and moved to be a top-level property:
```javascript
// Old
modalSettings: {
forceInitialDefaultView: "search",
// ...
}
// New
forceDefaultView: "search", // Now a top-level property
```
### Chat Button Changes
#### Removed Properties
##### `chatButtonType`
The `chatButtonType` property has been removed as the button appearance can now be customized via CSS using the provided class names.
##### `chatButtonBgColor`
The `chatButtonBgColor` property has been removed as the button background color can now be customized via CSS using the `.ikp-chat-button__button` class.
```css
.ikp-chat-button__button {
background-color: #4a5568;
}
```
##### `chatButtonBgColorDarkMode`
The `chatButtonBgColorDarkMode` property has been removed as the button background color in dark mode can now be customized via CSS using the `[data-theme='dark'] .ikp-chat-button__button` selector.
```css
[data-theme="dark"] .ikp-chat-button__button {
background-color: #2d3748;
}
```
##### `isPositionFixed`
The `isPositionFixed` property has been removed as the button positioning can now be customized via CSS by setting `position: relative;` on the `.ikp-chat-button__container` class.
```css
.ikp-chat-button__container {
position: relative;
}
```
##### `fixedPositionXOffset`
The `fixedPositionXOffset` property has been removed as the button horizontal positioning can now be customized via CSS by setting `right: 0;` on the `.ikp-chat-button__container` class.
```css
.ikp-chat-button__container {
right: 0;
}
```
##### `fixedPositionYOffset`
The `fixedPositionYOffset` property has been removed as the button vertical positioning can now be customized via CSS by setting `bottom: 0;` on the `.ikp-chat-button__container` class.
```css
.ikp-chat-button__container {
bottom: 0;
}
```
#### Renamed Properties
##### Button Label
* `chatButtonText` β `label`
```javascript
// Old
chatButtonSettings: {
chatButtonText: "Chat with AI",
// ...
}
// New
chatButtonSettings: {
label: "Chat with AI",
// ...
}
```
## Example Migration
### Before (with @inkeep/uikit-js)
```html
```
### After (with @inkeep/cxkit-js)
```html
```
## API Keys
Production API keys for web integrations now require `Enforce referrer URL` to be enabled for additional security. API keys without this setting will be severely rate limited. See [Public API Keys](/ui-components/common-settings/base#public-api-keys) for more details.
## New Features
The new package includes several new features:
* Intelligent form component - See [Form Settings](/ui-components/common-settings/form)
* Embedded search component - See [Embedded Search](/ui-components/js-snippet/in-page/embedded-search)
* Embedded search and chat component - See [Embedded Search and Chat](/ui-components/js-snippet/in-page/embedded-search-and-chat)
## Need Help?
If you encounter any issues during migration, please [contact our support team](https://inkeep.com/contact) for assistance.
***
title: Migrating from @inkeep/uikit to @inkeep/cxkit-react
sidebarTitle: To @inkeep/cxkit-react
keywords: React migration, cxkit migration, React SDK, package migration, breaking changes, API updates, configuration changes, component migration, React integration, migration guide, code updates, SDK migration, React toolkit, package transition, API migration
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
This guide will help you migrate your application from using `@inkeep/uikit` to the new `@inkeep/cxkit-react` package. The new package includes several breaking changes but offers improved functionality and a more consistent API.
## Overview
With version 0.5.x, we've renamed our package from `@inkeep/uikit` to `@inkeep/cxkit-react` to better reflect its purpose as a customer experience toolkit. This change comes with several API improvements and breaking changes that require updates to your code.
## Installation
First, you'll need to update your package dependency:
```bash
npm uninstall @inkeep/uikit npm install @inkeep/cxkit-react
```
```bash
yarn remove @inkeep/uikit yarn add @inkeep/cxkit-react
```
```bash
pnpm remove @inkeep/uikit pnpm add @inkeep/cxkit-react
```
## Breaking Changes
### Package Import Changes
Update your imports from:
```typescript
import { InkeepChatButton } from "@inkeep/uikit";
```
To:
```typescript
import { InkeepChatButton } from "@inkeep/cxkit-react";
```
### Base Settings Changes
Several properties in the base settings have been removed or renamed:
#### Removed Properties
##### `integrationId`
The `integrationId` property has been removed as it's no longer required for authentication. The API key now contains all the necessary information to identify your integration.
```typescript
// Old
baseSettings: {
apiKey: "your-api-key",
integrationId: "your-integration-id",
// ...
}
// New
baseSettings: {
apiKey: "your-api-key",
// No integrationId needed
}
```
##### `organizationId`
The `organizationId` property has been removed as it's no longer required for authentication. The API key now contains all the necessary information to identify your organization.
```typescript
// Old
baseSettings: {
apiKey: "your-api-key",
organizationId: "your-organization-id",
// ...
}
// New
baseSettings: {
apiKey: "your-api-key",
// No organizationId needed
}
```
##### `userType`
The `userType` property has been removed in favor of the more flexible `userProperties.cohorts` array, which allows you to specify multiple user types or roles. See docs [here](/ui-components/common-settings/base#user-properties) for more details.
```typescript
// Old
baseSettings: {
userType: "admin",
// ...
}
// New
baseSettings: {
userProperties: {
cohorts: ["admin", "engineering"],
// ...
},
// ...
}
```
##### `remoteErrorLogsLevel`
The `remoteErrorLogsLevel` property has been removed as error logging is now handled internally with improved defaults.
##### `consoleDebugLevel`
The `consoleDebugLevel` property has been removed as debugging is now handled internally with improved defaults.
##### `customCardSettings`
The `customCardSettings` property has been removed in favor of the more powerful and flexible `transformSource` function, which allows for more comprehensive customization of search results and chat sources
```typescript
// Old
baseSettings: {
customCardSettings: {
// Custom card settings
},
// ...
}
// New
baseSettings: {
transformSource: (source) => {
// Transform source data
return {
...source,
tabs: [] // Transform tabs
};
},
// ...
}
```
See [Source Transformation](/ui-components/customization-guides/source-transformation) for more details.
##### `breadcrumbRules`
The `breadcrumbRules` property has been removed in favor of the more powerful and flexible `transformSource` function, which allows for more comprehensive customization of breadcrumbs.
```typescript
// Old
baseSettings: {
breadcrumbRules: [
// Breadcrumb rules
],
// ...
}
// New
baseSettings: {
transformSource: (source) => {
// Transform source data
return {
...source,
breadcrumbs: []
};
},
// ...
}
```
See [Source Transformation](/ui-components/customization-guides/source-transformation) for more details.
##### `stringReplacementRules`
The `stringReplacementRules` property has been removed in favor of the more powerful and flexible `transformSource` function, which allows for more comprehensive string transformations.
```typescript
// Old
baseSettings: {
stringReplacementRules: [
// String replacement rules
],
// ...
}
// New
baseSettings: {
transformSource: (source) => {
// Transform source data
return {
...source,
breadcrumbs: []
};
},
// ...
}
```
See [Source Transformation](/ui-components/customization-guides/source-transformation) for more details.
#### Renamed Properties
##### `userId`
##### `userEmail`
##### `userName`
User properties are now grouped under `userProperties`. See [User Properties](/ui-components/common-settings/base#user-properties) for more details.
```typescript
// Old
baseSettings: {
userId: "user-456",
userEmail: "jane@enterprise.com",
userName: "Jane Smith",
// ...
}
// New
baseSettings: {
userProperties: {
id: "user-456",
email: "jane@enterprise.com",
name: "Jane Smith",
cohorts: ["admin", "engineering"],
},
// ...
}
```
##### `userToken`
The `userToken` property has been renamed to `userAuthToken` to better reflect its purpose as an authentication token for the user. See [User Properties](/ui-components/common-settings/base#user-properties) for more details:
```typescript
// Old
baseSettings: {
userToken: "jwt-token-for-user-authentication",
// ...
}
// New
baseSettings: {
userAuthToken: "jwt-token-for-user-authentication",
// ...
}
```
##### `logEventCallback`
The `logEventCallback` property has been renamed to `onEvent` with an updated event structure for more consistent event handling. See [Event Handling](/ui-components/common-settings/base#event-handling) for more details:
```typescript
// Old
baseSettings: {
logEventCallback: (event) => {
// Handle event
console.log(event);
},
// ...
}
// New
baseSettings: {
onEvent: (event) => {
// Handle event
console.log(event);
},
// ...
}
```
##### `chatApiProxyDomain`
The `chatApiProxyDomain` property has been renamed to `aiApiBaseUrl` to better reflect its purpose as an API endpoint for AI chat functionality. See [Event Handling](/ui-components/common-settings/base#core-settings) for more details:
```typescript
// Old
baseSettings: {
chatApiProxyDomain: "https://api.inkeep.com/chat",
// ...
}
// New
baseSettings: {
aiApiBaseUrl: "https://api.inkeep.com/chat",
// ...
}
```
##### `analyticsApiProxyDomain`
The `analyticsApiProxyDomain` property has been renamed to `analyticsApiBaseUrl` to better reflect its purpose as an API endpoint for analytics functionality. See [Core Settings](/ui-components/common-settings/base#core-settings) for more details:
```typescript
// Old
baseSettings: {
analyticsApiProxyDomain: "https://api.example.com/analytics",
// ...
}
// New
baseSettings: {
analyticsApiBaseUrl: "https://api.example.com/analytics",
// ...
}
```
##### `appendQueryParamsToUrls`
The `appendQueryParamsToUrls` property has been renamed to `urlQueryParamsToAppend` for clarity. See [URL Parameters](/ui-components/common-settings/base#url-parameters) for more details:
```typescript
// Old
baseSettings: {
appendQueryParamsToUrls: { utm_source: "docs" },
// ...
}
// New
baseSettings: {
urlQueryParamsToAppend: { utm_source: "docs" },
// ...
}
```
##### `stylesheets`
##### `stylesheetUrls`
Stylesheet properties have been consolidated under a single `styles` property. Style strings can be passed directly. See [Theme Configuration](/ui-components/customization-guides/style-components#theme-configuration) for more details:
```typescript
// Old
baseSettings: {
stylesheets: ["custom-styles.css"],
stylesheetUrls: ["https://example.com/styles.css"],
// ...
}
// New
baseSettings: {
styles: [
{
key: "google-fonts",
type: "link",
value:
"https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap",
},
{
key: "custom-theme",
type: "style",
value: `
.ikp-ai-chat-message {
border-radius: 8px;
padding: 12px;
}
[data-theme='dark'] .ikp-ai-chat-message {
background: #2D3748;
}
`,
},
],
// ...
}
```
#### Modified properties
##### `env`
`env` options are now lowercase: `"development" | "production"`
```typescript
// Old
baseSettings: {
env: "DEVELOPMENT",
// ...
}
// New
baseSettings: {
env: "development",
// ...
}
```
### AI Chat Settings Changes
#### Removed Properties
##### `isControlledMessage`
The `isControlledMessage` property has been removed as the component now uses a more intuitive controlled/uncontrolled pattern. Use the `defaultMessage` prop for uncontrolled behavior or the `message` and `onInputMessageChange` props for controlled behavior.
##### `includeAIAnnotations`
The `includeAIAnnotations` property has been removed as annotations are now handled internally with improved defaults. Equivalent functionality will be available in a future release.
##### `aiAnnotationPolicies`
The `aiAnnotationPolicies` property has been removed as annotation policies are now handled internally with improved defaults. Equivalent functionality will be available in a future release.
#### Renamed Properties
##### `botName`
##### `botAvatarSrcUrl`
##### `botAvatarDarkSrcUrl`
* `botName` β `aiAssistantName`
* `botAvatarSrcUrl` β `aiAssistantAvatar`
* `botAvatarDarkSrcUrl` β can be configured by changing `aiAssistantAvatar` to an object:
```typescript
// Old
aiChatSettings: {
botAvatarSrcUrl: "/assets/assistant.png",
botAvatarDarkSrcUrl: "/assets/assistant-dark.png",
// ...
}
// New
aiChatSettings: {
aiAssistantAvatar: {
light: "/assets/assistant-light.png",
dark: "/assets/assistant-dark.png"
},
// ...
}
```
##### `userAvatarSrcUrl`
* `userAvatarSrcUrl` β `userAvatar`
```typescript
// Old
aiChatSettings: {
userAvatarSrcUrl: userProfile.avatarUrl,
// ...
}
// New
aiChatSettings: {
userAvatar: userProfile.avatarUrl,
// ...
}
```
##### `quickQuestions`
`quickQuestions` is now `exampleQuestions` for improved clarity:
```typescript
// Old
baseSettings: {
quickQuestions: ["What is the capital of France?", "What is the capital of Germany?"],
// ...
}
// New
baseSettings: {
exampleQuestions: ["What is the capital of France?", "What is the capital of Germany?"],
// ...
}
```
##### `exampleQuestionsLabel`
`exampleQuestionsLabel` is now `exampleQuestionsTitle` for improved clarity:
```typescript
// Old
baseSettings: {
exampleQuestionsLabel: "Example Questions",
// ...
}
// New
baseSettings: {
exampleQuestionsTitle: "Example Questions",
// ...
}
```
##### `shouldHighlightFirstQuickQuestion`
`shouldHighlightFirstQuickQuestion` is now `isFirstExampleQuestionHighlighted` for improved clarity:
```typescript
// Old
baseSettings: {
shouldHighlightFirstQuickQuestion: true,
// ...
}
// New
baseSettings: {
isFirstExampleQuestionHighlighted: true,
// ...
}
```
##### `disclaimerSettings`
`isDisclaimerEnabled` is now `isEnabled` and `disclaimerLabel` is now `label` and `disclaimerTooltip` is now `tooltip` within the `AIChatDisclaimerSettings` type.
```typescript
// Old
import {
type InkeepAIChatSettings,
type AIChatDisclaimerSettings,
} from "@inkeep/uikit";
const aiChatDisclaimerSettings: AIChatDisclaimerSettings = {
isDisclaimerEnabled: true,
disclaimerLabel: "Usage policy",
disclaimerTooltip:
"Information provided by {{botName || 'this AI assistant'}} is not guaranteed to be accurate or comprehensive. Please consult {{organizationDisplayName}}'s terms of service and privacy policy for details on how information is used.",
};
const inkeepAIChatSettings: InkeepAIChatSettings = {
//... rest of inkeepAIChatSettings
disclaimerSettings: aiChatDisclaimerSettings,
};
// New
import {
type InkeepAIChatSettings,
type AIChatDisclaimerSettings,
} from "@inkeep/cxkit-react";
const aiChatDisclaimerSettings: AIChatDisclaimerSettings = {
isEnabled: true,
label: "Usage policy",
tooltip:
"Information provided by {{botName || 'this AI assistant'}} is not guaranteed to be accurate or comprehensive. Please consult {{organizationDisplayName}}'s terms of service and privacy policy for details on how information is used.",
};
const inkeepAIChatSettings: InkeepAIChatSettings = {
//... rest of inkeepAIChatSettings
disclaimerSettings: aiChatDisclaimerSettings,
```
##### `handleMessageChange`
`handleMessageChange` is now `onInputMessageChange` for improved clarity:
```typescript
// Old
baseSettings: {
handleMessageChange: (message) => {
// Handle message change
console.log(message);
},
// ...
}
// New
baseSettings: {
onInputMessageChange: (message) => {
// Handle message change
console.log(message);
},
// ...
}
```
##### `getHelpCallToActions`
`getHelpCallToActions` is now `getHelpOptions` for improved clarity:
```typescript
// Old
baseSettings: {
getHelpCallToActions: () => {
// Get help call to actions
return [
{
icon: { builtIn: 'FaDiscord' },
name: 'Discord',
url: 'https://inkeep.com/',
},
];
},
// ...
}
// New
baseSettings: {
getHelpOptions: () => {
// Get help options
return [
{
name: 'Discord',
icon: {
builtIn: 'FaDiscord',
},
action: {
type: 'open_link',
url: 'https://inkeep.com/',
},
},
];
},
// ...
}
```
##### `FormConfig` type
`FormConfig` type is now `AIChatFormSettings` for improved clarity and the configuration has changed. See here for more details: [AIChatFormSettings](/ui-components/common-settings/actions#formconfig-reference)
##### `isChatSharingEnabled`
The `isChatSharingEnabled` property has been renamed to `isShareButtonVisible` for improved clarity:
```typescript
// Old
aiChatSettings: {
isChatSharingEnabled: true,
// ...
}
// New
aiChatSettings: {
isShareButtonVisible: true,
// ...
}
```
##### `shouldShowCopyChatButton`
The `shouldShowCopyChatButton` property has been renamed to `isCopyChatButtonVisible` for improved clarity and consistency with other visibility properties:
```typescript
// Old
aiChatSettings: {
shouldShowCopyChatButton: true,
// ...
}
// New
aiChatSettings: {
isCopyChatButtonVisible: true,
// ...
}
```
##### `actionButtonLabels`
The `actionButtonLabels` property has been renamed to `toolbarButtonLabels` to better reflect its purpose for configuring toolbar button text:
```typescript
// Old
aiChatSettings: {
actionButtonLabels: {
copy: "Copy Chat",
share: "Share Chat",
// ...
},
// ...
}
// New
aiChatSettings: {
toolbarButtonLabels: {
copy: "Copy Chat",
share: "Share Chat",
// ...
},
// ...
}
```
##### `context`
##### `guidance`
The `context` and `guidance` properties have been consolidated under the more flexible `prompts` property. The new prompts is an array of strings.
```typescript
// Old
aiChatSettings: {
context: "The user is new to the product.",
guidance: "Be concise.",
// ...
}
// New
aiChatSettings: {
prompts: [
"The user is new to the product.",
"Be concise."
],
// ...
}
```
### Search Settings Changes
#### Removed Properties
##### `isControlledSearchQuery`
The `isControlledSearchQuery` property has been removed as the component now uses a more intuitive controlled/uncontrolled pattern. Use the `defaultQuery` prop for uncontrolled behavior or the `query` and `onQueryChange` props for controlled behavior.
#### Renamed Properties
##### `prefilledQuery`
The `prefilledQuery` property has been renamed to `defaultQuery` for improved clarity and consistency with React patterns:
```typescript
// Old
searchSettings: {
prefilledQuery: "How to get started",
// ...
}
// New
searchSettings: {
defaultQuery: "How to get started",
// ...
}
```
##### `handleSearchQueryChange`
The `handleSearchQueryChange` property has been renamed to `onQueryChange` for improved clarity and consistency with React event handler naming conventions:
```typescript
// Old
searchSettings: {
handleSearchQueryChange: (query) => {
// Handle query change
console.log(query);
},
// ...
}
// New
searchSettings: {
onQueryChange: (query) => {
// Handle query change
console.log(query);
},
// ...
}
```
##### `tabSettings`
The `tabSettings` property has been renamed to `tabs` for improved clarity and simplicity. tabs definitions have been updated as well. See docs [here](/ui-components/common-settings/search#search-tabs) for more details.
```typescript
// Old
searchSettings: {
tabSettings: {
isAllTabEnabled: true,
rootBreadcrumbsToUseAsTabs: ['Docs'],
tabOrderByLabel: ['Resources', 'Blog', 'Solutions'],
disabledDefaultTabs: undefined, // string[] | undefined
alwaysDisplayedTabs: ['Blog'],
},
// ...
}
// New
const searchSettings: InkeepSearchSettings = {
// Basic tabs
tabs: ["All", "Publications", "GitHub", "Forums"],
// With always visible option
tabs: [
"All",
"Publications",
["GitHub", { isAlwaysVisible: true }],
"Forums",
],
// Hide "All" tab, show only Publications and GitHub
tabs: ["Publications", "GitHub"],
// No tabs (just show all results)
tabs: [],
// ...
};
```
##### `shouldShowAskAICard`
The `shouldShowAskAICard` property has been elevated to a top-level property:
```typescript
// Old
searchSettings: {
shouldShowAskAICard: true,
// ...
}
// New
shouldShowAskAICard: true, // Now a top-level property
```
##### `maximumHitsLimit`
The `maximumHitsLimit` property has been renamed to `maxResults` for improved clarity and simplicity:
```typescript
// Old
searchSettings: {
maximumHitsLimit: 10,
// ...
}
// New
searchSettings: {
maxResults: 10,
// ...
}
```
##### `debounceTime`
The `debounceTime` property has been renamed to `debounceTimeMs` for improved clarity on the unit of time:
```typescript
// Old
searchSettings: {
debounceTime: 500,
// ...
}
// New
searchSettings: {
debounceTimeMs: 500,
// ...
}
```
### Modal Settings Changes
#### Removed Properties
##### `isShortcutKeyEnabled`
The `isShortcutKeyEnabled` property has been removed. To disable the shortcut key, pass `shortcutKey` as `null`.
```typescript
// Old
modalSettings: {
isShortcutKeyEnabled: false,
// ...
}
// New
modalSettings: {
shortcutKey: null, // Disables the shortcut key
// ...
}
```
##### `isAlignedToTop`
The `isAlignedToTop` property has been removed as modal positioning is now handled through CSS.
##### `isAlignedToRight`
The `isAlignedToRight` property has been removed as modal positioning is now handled through CSS.
##### `onShortcutKeyPressed`
The `onShortcutKeyPressed` property has been removed as shortcut key handling is now managed internally.
#### Renamed Properties
##### `openShortcutKey`
The `openShortcutKey` property has been renamed to `shortcutKey` for improved clarity. It has a default value of `k`:
```typescript
// Old
modalSettings: {
openShortcutKey: "k",
// ...
}
// New
modalSettings: {
shortcutKey: "k",
// ...
}
```
##### `askAILabel`
The `askAILabel` property has been moved to be a top-level prop:
```typescript
// Old
modalSettings: {
askAILabel: "Ask AI",
// ...
}
// New
askAILabel: "Ask AI", // Now a top-level prop
```
##### `switchToSearchMessage`
The `switchToSearchMessage` property has been renamed to `searchLabel` and moved to be a top-level prop:
```typescript
// Old
modalSettings: {
switchToSearchMessage: "Search Documentation",
// ...
}
// New
searchLabel: "Search Documentation", // Now a top-level prop
```
##### `isModeSwitchingEnabled`
The `isModeSwitchingEnabled` property has been renamed to `canToggleView` and moved to be a top-level prop:
```typescript
// Old
modalSettings: {
isModeSwitchingEnabled: true,
// ...
}
// New
canToggleView: true, // Now a top-level prop
```
##### `forceInitialDefaultView`
The `forceInitialDefaultView` property has been renamed to `forceDefaultView` and moved to be a top-level prop:
```typescript
// Old
modalSettings: {
forceInitialDefaultView: "search",
// ...
}
// New
forceDefaultView: "search", // Now a top-level prop
```
### Chat Button Changes
#### Removed Properties
##### `chatButtonType`
The `chatButtonType` property has been removed as button styling is now handled through CSS.
##### `chatButtonBgColor`
The `chatButtonBgColor` property has been removed. You can change the background color via CSS using the `.ikp-chat-button__button` class:
```css
.ikp-chat-button__button {
background-color: #4a5568;
}
```
##### `chatButtonBgColorDarkMode`
The `chatButtonBgColorDarkMode` property has been removed. You can change the background color for dark mode via CSS using the `[data-theme='dark'] .ikp-chat-button__button` selector:
```css
[data-theme="dark"] .ikp-chat-button__button {
background-color: #2d3748;
}
```
##### `isPositionFixed`
The `isPositionFixed` property has been removed. You can change the positioning via CSS by setting `position: relative;` on the `.ikp-chat-button__container` class:
```css
.ikp-chat-button__container {
position: relative;
}
```
##### `fixedPositionXOffset`
The `fixedPositionXOffset` property has been removed. You can change the horizontal positioning via CSS by setting `right: 0;` on the `.ikp-chat-button__container` class:
```css
.ikp-chat-button__container {
right: 0;
}
```
##### `fixedPositionYOffset`
The `fixedPositionYOffset` property has been removed. You can change the vertical positioning via CSS by setting `bottom: 0;` on the `.ikp-chat-button__container` class:
```css
.ikp-chat-button__container {
bottom: 0;
}
```
#### Renamed Properties
##### `chatButtonText`
The `chatButtonText` property has been renamed to `label` for improved clarity and consistency:
```typescript
// Old
chatButtonSettings: {
chatButtonText: "Chat with AI",
// ...
}
// New
chatButtonSettings: {
label: "Chat with AI",
// ...
}
```
### Custom Trigger Changes
#### Renamed Component
The `CustomTrigger` component has been renamed to provide more specific functionality:
* `ModalSearchAndChat` - For both search and chat functionality
* `ModalSearch` - For just search functionality
* `ModalChat` - For just chat functionality
See [here](/ui-components/react/custom-modal-trigger) for more details.
#### Moved Properties
##### `isOpen`
The `isOpen` property has been moved inside `modalSettings`:
```typescript
// Old
// New
```
##### `onOpen`
The `onOpen` property has been renamed to `onOpenChange` and moved inside `modalSettings`:
```typescript
// Old
// New
```
##### `onClose`
The `onClose` property has been removed. You can now utilize `onOpenChange` (moved inside `modalSettings`) to handle both open and close events:
```typescript
// Old
// New
{
if (!isOpen) {
// Handle close
}
},
// ...
}}
// ...
/>
```
### API Keys
Production API keys for web integrations are now required to have `Enforce referrer URL` enabled for additional security. See [here](/ui-components/public-api-keys#referrer-url) for details. API keys without this setting will be severely rate limited.
### New Components
* **Intelligent Form Component**: See [here](/ui-components/common-settings/form) for details.
* **Embedded Search Component**: See [here](/ui-components/react/in-page/embedded-search) for details.
* **Embedded Search and Chat Component**: See [here](/ui-components/react/in-page/embedded-search-and-chat) for details.
***
sidebarTitle: Overview
title: Inkeep AI API Overview
icon: IoSparklesOutline
keywords: AI API, chat completions API, OpenAI compatibility, LLM integration, chatbot development, AI assistant, RAG implementation, API endpoints, model selection, API authentication, chat API, AI models, API documentation, developer tools, API integration, TypeScript SDK, Python SDK, API examples, API modes, API configuration
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Inkeep's AI API endpoints make it easy to develop chatbot or copilot experiences powered by your own knowledge base.
Because these endpoints are compatible with OpenAI's Chat Completion API format, so you can use most LLM application frameworks, libraries, or SDKs with zero code changes.
For example, you can build a:
* ChatGPT-like UI using the [Next.js Chatbot template](https://vercel.com/templates/next.js/nextjs-ai-chatbot)
* Product-specific copilot using the [Vercel AI SDK](https://sdk.vercel.ai/docs/introduction) or [LangChain](https://github.com/langchain-ai/langchainjs)
* An automation for replying to customer emails or as a plugin to your support platform using [OpenAI's TypeScript SDK](https://github.com/openai/openai-node).
Check out our [examples](https://github.com/inkeep/inkeep-chat-api-examples) for quickstarts for the various APIs.
## Available Models
We offer various APIs tailored for different use cases, we use the `model` concept to differentiate between the different scenarios and functionality.
| Model (API) Name | Description |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `inkeep-qa` | Provides sensible defaults for customer-facing support assistant or "question-answer" scenarios. Useful for auto-reply automations or custom chat experiences. |
| `inkeep-context` | A flexible "passthrough" proxy that injects Inkeep's RAG context into calls to underlying models from Anthropic or OpenAI. Fully compatible with all chat completion endpoint functionality including tool/function calling, JSON mode, and image inputs. Ideal for custom AI agents, LLM applications, or workflows requiring full output control while benefiting from a managed RAG system. Provides high flexibility but requires standard LLM application prompting and experimentation. |
| `inkeep-base` | A fast version of the `inkeep-context` mode that skips RAG and instead only injects a general overview of your product into calls to base models. Best for when you want the flexibility of the `inkeep-context` mode, but don't need the full comprehensive context. |
| `inkeep-rag` | Provides structured RAG chunks directly from your knowledge base. Returns chunks with URLs, excerpts from the original documents, and other source information. Ideal for custom implementations where you need direct access to the retrieved knowledge base content. You'd typically pass these chunks ('documents') to an LLM of your choice for any open-ended purpose. |
## Get an API key
1. Log in to the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Projects** section and select your project
3. Open the **Assistants** tab
4. Click **Create assistant** and choose **API** from the options
5. Enter a Name for your new API assistant.
6. Click on **Create**
7. A generated **API key** will appear that you can use to authenticate API requests.
## Using the API
To use with an OpenAI-compatible client, simply:
1. Customize the `baseURL` to `https://api.inkeep.com/v1` and use an Inkeep `apiKey`
2. Specify the mode by setting `model` to a value in the format of `{inkeep-mode}-{model}`
If you'd like to let Inkeep manage which model is used
* `inkeep-qa-expert`
* `inkeep-context-expert`
* `inkeep-base`
* `inkeep-rag`
If you'd like to pin the service against a preferred LLM model for the `qa` or `context` APIs, you can do so like this:
* `inkeep-qa-sonnet-4`
* `inkeep-qa-gpt-4o`
* `inkeep-qa-gpt-4-turbo`
* `inkeep-context-sonnet-4`
* `inkeep-context-gpt-4-turbo`
* `inkeep-context-gpt-4o`
### Calling the API
All modes use the OpenAI chat completion API format. You can use any OpenAI compatible SDK in any language to make requests to the API. If you don't need streaming, then a regular HTTP request works fine. If you use streaming, we recommend using one of the SDKs.
```typescript
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'YOUR_INKEEP_API_KEY',
baseURL: 'https://api.inkeep.com/v1'
});
const completion = await client.chat.completions.create({
model: 'inkeep-context-expert',
messages: [
{ role: 'user', content: 'How do I get started?' },
],
});
```
```typescript
import { generateText } from 'ai';
import { createOpenAI } from '@ai-sdk/openai';
// Create an OpenAI provider configured for Inkeep
const inkeep = createOpenAI({
apiKey: 'YOUR_INKEEP_API_KEY',
baseURL: 'https://api.inkeep.com/v1',
});
const { text } = await generateText({
model: inkeep('inkeep-context-expert'),
messages: [
{ role: 'user', content: 'How do I get started?' },
],
});
```
```python
from openai import OpenAI
client = OpenAI(
api_key="YOUR_INKEEP_API_KEY",
base_url="https://api.inkeep.com/v1"
)
completion = client.chat.completions.create(
model="inkeep-context-expert",
messages=[
{"role": "user", "content": "How do I get started?"},
],
)
```
```sh
curl https://api.inkeep.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer " \
-d '{
"model": "inkeep-context-expert",
"messages": [
{
"role": "user",
"content": "How do I get started?"
}
]
}'
```
Follow the guides for the mode you want to use for details on the expected response schema and usage patterns.
## Limitations
### Rate Limits
* **Per-IP throttling** is enabled.\
Need a higher rate? Email [support@inkeep.com](mailto:support@inkeep.com?subject=Rate%20limit%20request).
### Chat Limits
* **30 messages per chat session**\
(1 user message + 1 assistant response = 2 βmessagesβ).
### Message Size
| Direction | Recommended tokens | Notes |
| ---------- | ------------------ | ------------------------------------------------------------------------------ |
| **Input** | β€ **100** | Short fragments, single sentences, or brief paragraphs yield the best results. |
| **Output** | β€ **1 000** | Longer outputs are allowed but may be less optimal. |
Have a use case that is outside these recommended limits? Reach out to [support@inkeep.com](mailto:support@inkeep.com?subject=Custom%20limits).
***
sidebarTitle: Overview
title: Question Answer API Overview
icon: IoSparklesOutline
keywords: Question Answer API, chatbot development, AI assistant, support automation, API tools, response structure, custom tools, source citations, TypeScript schema, API integration, tool calls, QA implementation, AI models, chat completion, response formatting, API documentation, customer support, auto-reply system, inkeep-qa, Claude Sonnet, GPT-4, provideRecordsConsidered, provideLinks, custom tool calls
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The `inkeep-qa` API is specifically tailored for customer-facing question-answer scenarios like support chatbots or auto-reply workflows.
## Overview
This API comes with Inkeep's sensible built-in behavior for:
* format of citations
* tone
* protecting your brand
* minimal hallucinations
`inkeep-qa` is best suited for when you want to develop your own chat UX or question-answer automations with a great out of the box building block.
## Available Models
You can specify the model used in the format of `inkeep-qa-[model]`
* `inkeep-qa-expert` - Let Inkeep manage which model is used
* `inkeep-qa-sonnet-4` - Use Anthropic's Claude Sonnet 4
* `inkeep-qa-gpt-4o` - Use OpenAI's GPT-4o
## Response Structure
The API responds with an AI assistant message (`content`) and optional tools for displaying extra metadata or annotations about an answer.
| Component | Description |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `content` | Contains the conversational answer of the AI assistant as any normal OpenAI chat completion request. This is what you would display as the AI assistant answer in a traditional chat UI. |
## Tools
In addition to `content`, which is always returned, `inkeep-qa` can return additional tool calls.
You can provide your own and use the two built in ones:
| Tools | Description |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provideRecordsConsidered` | Provides a list of records considered (sources) by the AI assistant to generate a response. You can use this to give a preview of relevant records that were considered for an answer prior to the generation of the response. If using streaming, it will stream the records used before the response is generated. NOTE: Not all of these records are used in the final answer. |
| `provideLinks` | Provides a list of links (sources) used by the AI assistant to generate a response. You can use this to display citations for an answer. |
| `[customToolCall]` | Allows you to pass in custom tool calls to the AI assistant. You can use this to, for example, determine whether the AI assistant is confident, detect buying intent, categorize a question, determine when to call your own backend APIs to retrieve dynamic information from backend systems, or perform custom actions. These are defined by you and are not managed by Inkeep. See [common tools](/ui-components/tools/common-tool-schemas) for examples. |
## Built In Schemas
```ts title="inkeep-qa-tools-schema.ts"
import { z } from "zod";
/* provideRecordsConsidered tool schema */
const InkeepRecordTypes = z.enum([
"documentation",
"site",
"discourse_post",
"github_issue",
"github_discussion",
"stackoverflow_question",
"discord_forum_post",
"discord_message",
"custom_question_answer",
]);
const LinkType = z.union([
InkeepRecordTypes,
z.string(), // catch all
]);
const ProvideRecordsConsideredToolSchema = z.object({
recordsConsidered: z.array(
z.object({
breadcrumbs: z.array(z.string()).nullish(),
title: z.string().nullish(),
type: LinkType.nullish(),
url: z.string().nullish(),
})
),
});
/* provideLinks tool schema */
const InkeepRecordTypes = z.enum([
"documentation",
"site",
"discourse_post",
"github_issue",
"github_discussion",
"stackoverflow_question",
"discord_forum_post",
"discord_message",
"custom_question_answer",
]);
const LinkType = z.union([
InkeepRecordTypes,
z.string(), // catch all
]);
const LinkSchema = z
.object({
label: z.string().nullish(), // the value of the footnote, e.g. `1`
url: z.string(),
title: z.string().nullish(),
description: z.string().nullish(),
type: LinkType.nullish(),
breadcrumbs: z.array(z.string()).nullish(),
})
.passthrough();
export const LinksSchema = z.array(LinkSchema).nullish();
export const LinksToolSchema = z.object({
links: LinksSchema,
});
```
## Implementation Examples
To learn more about implementing the QA API with different SDKs and frameworks:
* [Using the OpenAI SDK](/ai-api/question-answer-mode/openai-sdk)
* [Using the Vercel AI SDK](/ai-api/question-answer-mode/vercel-ai-sdk)
* [Working with Custom Tool Calls](/ai-api/question-answer-mode/custom-tool-calls)
***
sidebarTitle: Vercel AI SDK
title: Using the Question Answer API with the Vercel AI SDK
keywords: Vercel AI SDK, React integration, Next.js implementation, server components, streaming UI, chat interface, API integration, React hooks, server actions, TypeScript implementation, QA API, chat components, UI components, API streaming, tool functions, React Server Components, inkeep-qa, useChat hook, streamUI, edge runtime, server-side rendering, client-side rendering
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Using useChat and a route
[`useChat`](https://sdk.vercel.ai/docs/reference/ai-sdk-ui/use-chat) is cross-platform hook that helps you create a conversational experience with the Vercel AI SDK with React, Svelte, Vue, and Solid frontends.
To use useChat, first create an API route using Next.js. Here's where we'll call Inkeep.
### API Route
```tsx title="app/api/chat/route.ts"
import { LinksTool } from "@/lib/chat/inkeep-qa-schema";
import { createOpenAI } from "@ai-sdk/openai";
import { streamText } from "ai";
export const runtime = "edge";
const openai = createOpenAI({
apiKey: process.env.INKEEP_API_KEY,
baseURL: "https://api.inkeep.com/v1",
});
export async function POST(req: Request) {
const reqJson = await req.json();
const result = await streamText({
model: openai("inkeep-qa-sonnet-4"),
messages: reqJson.messages.map((message: any) => ({
role: message.role,
content: message.content,
name: "inkeep-qa-user-message",
id: message.id,
})),
tools: {
// to get the citation information
provideLinks: {
...LinksTool,
},
},
toolChoice: "auto",
});
return result.toAIStreamResponse();
}
```
### Client
```tsx title="app/page.tsx"
"use client";
import { useChat } from "ai/react";
export default function Page() {
const { messages, isLoading, input, handleSubmit, handleInputChange } =
useChat({
streamMode: "stream-data",
sendExtraMessageFields: true,
onResponse(response) {
if (response.status === 401) {
console.error(response.statusText);
}
},
});
return (
<>
{messages.map((message) => (
{message.role === "user" ? "User: " : "AI: "}
{message.content}
))}
{isLoading && Loading...
}
>
);
}
```
## Using Server Actions (AI SDK Actions)
[`streamUI`](https://sdk.vercel.ai/docs/reference/ai-sdk-rsc/stream-ui) is another way to use the Vercel AI SDK, but with React Server Components. This lets you stream entire UI components, not just the text that is then parsed and rendered on the client.
This example illustrates how to render assistant messages and a "sources" list provided by the `provideLinks` tool.
### Server Action
```tsx title="lib/chat/actions.ts"
import "server-only";
import { createAI, getMutableAIState, streamUI } from "ai/rsc";
import { createOpenAI } from "@ai-sdk/openai";
import { Message } from "ai";
import { nanoid } from "./utils";
import { LinksTool } from "./inkeep-qa-schema";
const openai = createOpenAI({
apiKey: process.env.INKEEP_API_KEY,
baseURL: "https://api.inkeep.com/v1",
});
async function submitUserMessage(content: string) {
"use server";
const aiState = getMutableAIState();
aiState.update({
...aiState.get(),
messages: [
...aiState.get().messages,
{
id: nanoid(),
role: "user",
content,
},
],
});
const answerMessageId = nanoid();
const result = await streamUI({
model: openai("inkeep-qa-sonnet-3-5"),
messages: [
...aiState.get().messages.map((message: any) => ({
role: message.role,
content: message.content,
name: "inkeep-qa-user-message",
id: message.id,
})),
],
text: ({ content }) => {
const assistantAnswerMessage = {
id: answerMessageId,
role: "assistant",
content,
name: "inkeep-qa-assistant-message",
} as Message;
const currentMessages = aiState.get().messages;
const lastMessage = currentMessages[currentMessages.length - 1];
aiState.update({
...aiState.get(),
messages:
lastMessage?.id === answerMessageId
? [...currentMessages.slice(0, -1), assistantAnswerMessage]
: [...currentMessages, assistantAnswerMessage],
});
return {assistantAnswerMessage.content}
;
},
tools: {
provideLinks: {
...LinksTool,
generate: async ({ links }) => {
// render sources UI once tool is complete
const currentMessages = aiState.get().messages;
const lastMessage = currentMessages[currentMessages.length - 1];
const lastMessageWithToolResults = {
...lastMessage,
toolInvocations: [
{
toolName: "provideLinks",
result: links,
},
],
} as Message;
aiState.done({
...aiState.get(),
messages: [
...currentMessages.slice(0, -1),
lastMessageWithToolResults,
],
});
return {lastMessageWithToolResults.content}
;
},
},
},
toolChoice: "auto",
});
return {
id: nanoid(),
display: result.value,
};
}
export type AIState = {
chatId: string;
messages: Message[];
};
export type UIState = {
id: string;
display: React.ReactNode;
}[];
export const AI = createAI({
actions: {
submitUserMessage,
},
initialUIState: [],
initialAIState: { chatId: nanoid(), messages: [] },
});
```
## Page.tsx
```tsx title="app/page.tsx"
import { Chat } from "@/components/chat";
import { AI } from "@/lib/chat/actions";
import { nanoid } from "@/lib/chat/utils";
export default async function IndexPage() {
const id = nanoid();
return (
);
}
```
### Client
```tsx title="app/components/chat.tsx"
"use client";
import { useUIState, useAIState, useActions } from "ai/rsc";
import { Message } from "ai";
import { UIState } from "@/lib/chat/actions";
import { nanoid } from "@/lib/chat/utils";
export interface ChatProps extends React.ComponentProps<"div"> {
initialMessages?: Message[];
id?: string;
}
export function Chat({ id, className }: ChatProps) {
const [messages] = useUIState();
return (
);
}
export interface ChatList {
messages: UIState;
}
export function ChatList({ messages }: ChatList) {
const [messagesUIState, setMessagesUIState] = useUIState();
const { submitUserMessage } = useActions();
const handleSubmit = async (e: any) => {
e.preventDefault();
const form = e.currentTarget;
const input = form.elements.namedItem("prompt") as HTMLInputElement;
const value = input.value.trim();
if (!value) return;
input.value = ""; // Clear the input after submission
const userMessage = {
id: nanoid(),
content: value,
role: "user",
} as Message;
// Optimistically add user message UI
setMessagesUIState((currentMessages) => [
...currentMessages,
{
id: nanoid(),
display: {userMessage.content}
,
},
]);
// Submit and get response message
const responseMessage = await submitUserMessage(value);
setMessagesUIState((currentMessages) => [
...currentMessages,
responseMessage,
]);
};
return (
<>
{messages.map((message) => (
{message.display}
))}
>
);
}
```
***
sidebarTitle: OpenAI SDK
title: Use the Question Answer API with the OpenAI SDK
keywords: OpenAI SDK integration, chat completions, TypeScript implementation, streaming responses, tool calls, API examples, Node.js integration, QA API, response handling, link processing, API authentication, TypeScript SDK, OpenAI client, API streaming, tool functions, inkeep-qa, zod schema, JSON schema, environment variables, async streaming, tool call handling
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Here's an example of how to use [Chat Completions](https://platform.openai.com/docs/guides/chat-completions) with one of Inkeep's `qa` models
```ts title="index.ts"
import OpenAI from "openai";
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
import { LinksToolSchema } from "./LinksToolSchema";
import dotenv from "dotenv";
dotenv.config();
if (!process.env.INKEEP_API_KEY) {
throw new Error("INKEEP_API_KEY is required");
}
const client = new OpenAI({
baseURL: "https://api.inkeep.com/v1/",
apiKey: process.env.INKEEP_API_KEY,
// dangerouslyAllowBrowser: true, use this setting if you are using this in browser
});
async function getResponseFromAI() {
const result = await client.chat.completions.create({
model: "inkeep-qa-sonnet-4",
messages: [{ role: "user", content: "How do I get started with Inkeep?" }],
stream: true,
tools: [
{
type: "function",
function: {
name: "provideLinks",
description: "Provides links",
parameters: zodToJsonSchema(
LinksToolSchema.extend({
text: z.string(),
})
),
},
},
],
tool_choice: "auto",
});
let toolCalls: any[] = [];
for await (const chunk of result) {
const c = chunk.choices[0];
process.stdout.write(c.delta.content || "");
if (c.delta?.tool_calls) {
c.delta.tool_calls.forEach((toolCall) => {
const existingCall = toolCalls[toolCall.index ?? 0];
if (existingCall) {
// Update existing call
if (toolCall.function) {
existingCall.function = existingCall.function || {};
if (toolCall.function.name)
existingCall.function.name = toolCall.function.name;
if (toolCall.function.arguments) {
existingCall.function.arguments =
(existingCall.function.arguments || "") +
toolCall.function.arguments;
}
}
if (toolCall.type) existingCall.type = toolCall.type;
} else {
// Add new call
toolCalls[toolCall.index ?? 0] = toolCall;
}
});
}
}
// Check if the function is called in the response
if (toolCalls && toolCalls.length > 0) {
const provideLinksCall = toolCalls.find(
(call) => call.function.name === "provideLinks"
);
if (provideLinksCall) {
const functionArgs = JSON.parse(provideLinksCall.function.arguments);
await provideLinks(functionArgs);
} else {
console.log("No provideLinks tool call found");
}
}
}
const provideLinks = async ({
links,
text,
}: {
links?: (typeof LinksToolSchema._type)["links"];
text: string;
}) => {
console.log("\nLinks used in response: ", links);
return Promise.resolve();
};
getResponseFromAI();
```
***
sidebarTitle: Custom Tool Calls
title: Custom Tool Calls for the Question Answer API
keywords: custom tool calls, AI assistant tools, function calling, OpenAI integration, tool schemas, API customization, answer confidence, sales detection, TypeScript implementation, API tools, tool definitions, schema validation, API examples, tool parameters, API integration, custom functions, tool automation
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Inkeep's `inkeep-qa` API allows you to pass in custom tool calls to the AI assistant.
You can use this to: - determine an answer's confidence and escalate to a human if needed - route, categorize, or label the question - trigger actions based on the content of a question or answer
To effectively use tool calls, you should:
1. Define a clear semantic schema for the tool call arguments
2. Write detailed descriptions of each tool call and its intended use cases
3. Experiment with multiple test cases
For more details on implementing function calling, see [this guide](https://platform.openai.com/docs/guides/function-calling?api-mode=chat) on tool calling.
The examples below leverage the tool argument definitions found in the [Common
Tools](/ui-components/tools/common-tool-schemas) guide.
## Single Tool Call
You can provide a single tool definition to the AI assistant by passing a tool object to the `tools` array parameter in the `chat.completions.create` function.
```ts title="index.ts"
import OpenAI from "openai";
import dotenv from "dotenv";
import { provideAnswerConfidenceSchema } from "./common-tool-schemas.ts";
import { zodToJsonSchema } from "zod-to-json-schema";
dotenv.config();
if (!process.env.INKEEP_API_KEY) {
throw new Error("INKEEP_API_KEY is required");
}
const client = new OpenAI({
baseURL: "https://api.inkeep.com/v1/",
apiKey: process.env.INKEEP_API_KEY,
// dangerouslyAllowBrowser: true, use this setting if you are using this in browser
});
const singleTool = [
{
function: {
name: "provideAnswerConfidence",
description:
"Determine how confident the AI assistant was and whether or not to escalate to humans.",
parameters: zodToJsonSchema(provideAnswerConfidenceSchema),
},
type: "function",
},
];
const completion = await client.chat.completions.create({
model: "inkeep-qa-expert",
messages: [{ role: "user", content: "How do I get started?" }],
tools: singleTool,
});
console.log(completion.choices[0].message.tool_calls);
```
## Multiple Tool Calls
We can also combine multiple tool calls. The LLM will choose all relevant tools. If you'd like a tool to always be invoked, include that in the description of the tool.
```ts title="index.ts"
import OpenAI from "openai";
import dotenv from "dotenv";
import {
provideAnswerConfidenceSchema,
detectedSalesSignal,
} from "./common-tool-schemas.ts";
import { zodToJsonSchema } from "zod-to-json-schema";
dotenv.config();
if (!process.env.INKEEP_API_KEY) {
throw new Error("INKEEP_API_KEY is required");
}
const client = new OpenAI({
baseURL: "https://api.inkeep.com/v1/",
apiKey: process.env.INKEEP_API_KEY,
// dangerouslyAllowBrowser: true, use this setting if you are using this in browser
});
const completion = await client.chat.completions.create({
model: "inkeep-qa-expert",
messages: [
{
role: "user",
content: "How much does your enterprise plan cost for a team of 50?",
},
],
tools: [
{
type: "function",
function: {
name: "provideAnswerConfidence",
description: "Grade how confident the AI assistant was in its answer.",
parameters: zodToJsonSchema(provideAnswerConfidenceSchema),
},
},
{
type: "function",
function: {
name: "detectSalesSignal",
description:
"Identify when users express interest in potentially purchasing a product.",
parameters: zodToJsonSchema(detectedSalesSignal),
},
},
],
});
console.log(completion.choices[0].message.tool_calls);
```
***
sidebarTitle: Vercel AI SDK
title: Use the Context Mode API with the Vercel AI SDK
keywords: context mode API, Vercel AI SDK, structured responses, streaming objects, TypeScript implementation, custom copilots, AI workflows, step-by-step instructions, API integration, OpenAI compatibility, LLM applications, dynamic UI, conversational AI, API examples, context-aware AI
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
With the Inkeep `context` mode, you can leverage all of the capabilities provided by a normal OpenAI API endpoint but "grounded" with context about your product.
This gives you the full flexibility of creating any LLM application: custom copilots, AI workflows, etc., all backed by your own data. Structured data can be particularly powerful in rendering dynamic UI components as part of a conversational experience.
As a basic example, instead of having a support bot that answers with a single `content` payload, we can instead define a response to be returned as a series of structured steps. The example shown below illustrates how to accomplish that with [streamObject](https://sdk.vercel.ai/docs/reference/ai-sdk-core/stream-object) and Inkeep's `context` model.
```ts title="index.ts"
import { z } from "zod";
import { streamObject } from "ai";
import { createOpenAI } from "@ai-sdk/openai";
import dotenv from "dotenv";
dotenv.config();
if (!process.env.INKEEP_API_KEY) {
throw new Error("INKEEP_API_KEY is required");
}
const openai = createOpenAI({
apiKey: process.env.INKEEP_API_KEY,
baseURL: "https://api.inkeep.com/v1",
});
const StepSchema = z.object({
steps: z.array(
z.object({
step: z.string(),
description: z.string(),
})
),
});
async function getResponseFromAI() {
const result = await streamObject({
model: openai("inkeep-context-sonnet-4"),
schema: StepSchema,
messages: [
{
role: "system",
content:
"Generate step-by-step instructions to answer the user question about Inkeep only based on the information sources. Break it down to be as granular as possible. Always generate more than one step.",
},
],
});
const { partialObjectStream } = result;
for await (const partialObject of partialObjectStream) {
console.clear();
console.log(partialObject.steps);
}
}
getResponseFromAI();
```
***
sidebarTitle: HTTP Request
title: Call the Inkeep RAG API with an HTTP Request
keywords: RAG API, HTTP request, API documentation, JSON response format, document retrieval, knowledge base integration, API endpoints, content schema, source types, API examples, curl commands, response processing, document structure, API authentication, content formatting, REST API, API integration, document sources, API response handling
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The Inkeep RAG API provides structured documents from your knowledge base. This page shows how to make direct HTTP requests to the API. Please ensure you have an API key (don't have one? [Get one here](https://docs.inkeep.com/ai-api/chat-completions-api#get-an-api-key)).
## Request Format
```json
POST https://api.inkeep.com/v1/chat/completions
Content-Type: application/json
Authorization: Bearer YOUR_INKEEP_API_KEY
{
"model": "inkeep-rag",
"messages": [
{
"role": "user",
"content": "How do I get started?"
}
],
"response_format": {
"type": "json_object"
}
}
```
## Response Format
```json
{
"id": "chatcmpl-123abc",
"object": "chat.completion",
"created": 1677858242,
"model": "inkeep-rag",
"choices": [
{
"message": {
"role": "assistant",
"content": "{\"content\":[{\"type\":\"document\",\"record_type\":\"Documentation\",\"url\":\"https://docs.inkeep.com/ui-components/js-snippet/in-page/embedded-search-and-chat\",\"title\":\"Embedded Search and Chat (JS) - Inkeep\",\"source\":{\"type\":\"content\",\"content\":[{\"type\":\"text\",\"text\":\"## Quick start\\n\\nAdd the below `\n```"
}
]
}
````
## Processing the Response
To process the response, you'll need to:
1. Parse the JSON response
2. Extract the `content` field from the `message.content` JSON string
3. Process each document in the `content` array
This will give you structured access to the documents retrieved from your knowledge base.
***
sidebarTitle: Vercel AI SDK
title: Using the Inkeep RAG API with the Vercel AI SDK
keywords: Vercel AI SDK, RAG API integration, TypeScript implementation, Zod schema validation, structured data retrieval, knowledge base integration, API examples, document processing, Vercel integration, Next.js integration, API authentication, TypeScript types, schema definition, RAG documents, API response handling, structured output
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Using the Vercel AI SDK with Inkeep's RAG API
The Inkeep RAG API provides structured documents from your knowledge base. This example shows how to use the Vercel AI SDK to retrieve these documents. Please ensure you have an API key (don't have one? [Get one here](https://docs.inkeep.com/ai-api/chat-completions-api#get-an-api-key)).
### Schema Definition
```tsx title="inkeep-rag-schema.ts"
import { generateObject } from "ai";
import { z } from "zod";
import dotenv from "dotenv";
import { createOpenAI } from "@ai-sdk/openai";
dotenv.config();
if (!process.env.INKEEP_API_KEY) {
throw new Error("INKEEP_API_KEY is required");
}
export const provider = createOpenAI({
baseURL: "https://api.inkeep.com/v1/",
apiKey: process.env.INKEEP_API_KEY,
});
/* Inkeep RAG Document Schema */
export const InkeepSourceContentSchema = z
.object({
type: z.union([z.literal("text"), z.string()]),
media_type: z.union([z.literal("text/plain"), z.string()]).optional(),
text: z.string().optional(),
data: z.string().optional(),
})
.passthrough();
export const InkeepSourceSchema = z
.object({
content: z.array(InkeepSourceContentSchema).optional(),
type: z.union([z.literal("content"), z.string()]).optional(),
media_type: z.string().optional(),
data: z.string().optional(),
})
.passthrough();
const InkeepRecordTypes = z.enum([
"documentation",
"site",
"discourse_post",
"github_issue",
"github_discussion",
"stackoverflow_question",
"discord_forum_post",
"discord_message",
"custom_question_answer",
]);
export const InkeepRAGDocumentSchema = z
.object({
type: z.string(),
source: InkeepSourceSchema,
title: z.string().optional(),
context: z.string().optional(),
record_type: z.union([z.string(), InkeepRecordTypes]).optional(),
url: z.string().optional(),
})
.passthrough();
export const InkeepRAGResponseSchema = z
.object({
content: z.array(InkeepRAGDocumentSchema),
})
.passthrough();
export type InkeepSourceContent = z.infer;
export type InkeepSource = z.infer;
export type InkeepRAGDocument = z.infer;
export type InkeepRAGResponse = z.infer;
```
### Simple Example
```tsx title="index.ts"
import { createOpenAI } from "@ai-sdk/openai";
import { z } from "zod";
import dotenv from "dotenv";
import fetch from "node-fetch";
dotenv.config();
if (!process.env.INKEEP_API_KEY) {
throw new Error("INKEEP_API_KEY is required");
}
// Initialize OpenAI client with Inkeep's base URL
const provider = createOpenAI({
apiKey: process.env.INKEEP_API_KEY,
baseURL: "https://api.inkeep.com/v1",
});
// Define the RAG document schema
const InkeepSourceContentSchema = z
.object({
type: z.union([z.literal("text"), z.string()]),
media_type: z.union([z.literal("text/plain"), z.string()]).optional(),
text: z.string().optional(),
data: z.string().optional(),
})
.passthrough();
const InkeepSourceSchema = z
.object({
content: z.array(InkeepSourceContentSchema).optional(),
type: z.union([z.literal("content"), z.string()]).optional(),
media_type: z.string().optional(),
data: z.string().optional(),
})
.passthrough();
const InkeepRAGDocumentSchema = z
.object({
type: z.string(),
source: InkeepSourceSchema,
title: z.string().optional(),
context: z.string().optional(),
record_type: z.string().optional(),
url: z.string().optional(),
})
.passthrough();
const InkeepRAGResponseSchema = z
.object({
content: z.array(InkeepRAGDocumentSchema),
})
.passthrough();
const { object } = await generateObject({
model: provider.languageModel("inkeep-rag"),
messages: [{ role: "user", content: "How do I get started?" }],
schema: InkeepRAGResponseSchema,
mode: "json",
});
// Process the RAG documents
object.content.forEach((doc, index) => {
console.log(`Document ${index + 1}:`);
console.log(`Title: ${doc.title || "N/A"}`);
console.log(`URL: ${doc.url || "N/A"}`);
console.log(`Context: ${doc.context || "N/A"}`);
console.log(`Record Type: ${doc.record_type || "N/A"}`);
console.log("---");
});
```
This example demonstrates how to use the Vercel AI SDK to retrieve structured RAG documents from Inkeep's knowledge base. The response includes an array of documents with context, source information, and URLs.
***
sidebarTitle: OpenAI SDK
title: Using the Inkeep RAG API with the OpenAI SDK
keywords: OpenAI SDK, RAG implementation, TypeScript integration, Zod validation, structured output, API integration, knowledge base, document retrieval, schema validation, OpenAI client, API examples, TypeScript SDK, document processing, API response parsing, Node.js integration, RAG documents, API authentication, structured data
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Here's an example of how to use [Structured Output Parsing](https://platform.openai.com/docs/guides/structured-output) with Inkeep's `rag` model to retrieve structured documents from your knowledge base. Please ensure you have an API key (don't have one? [Get one here](https://docs.inkeep.com/ai-api/chat-completions-api#get-an-api-key)).
## Example
```ts title="index.ts"
import OpenAI from "openai";
import { z } from "zod";
import dotenv from "dotenv";
import { zodResponseFormat } from "openai/helpers/zod";
dotenv.config();
if (!process.env.INKEEP_API_KEY) {
throw new Error("INKEEP_API_KEY is required");
}
const client = new OpenAI({
baseURL: "https://api.inkeep.com/v1/",
apiKey: process.env.INKEEP_API_KEY,
// dangerouslyAllowBrowser: true, use this setting if you are using this in browser
});
// Define the RAG document schema
const InkeepSourceContentSchema = z
.object({
type: z.union([z.literal("text"), z.string()]),
media_type: z.union([z.literal("text/plain"), z.string()]).optional(),
text: z.string().optional(),
data: z.string().optional(),
})
.passthrough();
const InkeepSourceSchema = z
.object({
content: z.array(InkeepSourceContentSchema).optional(),
type: z.union([z.literal("content"), z.string()]).optional(),
media_type: z.string().optional(),
data: z.string().optional(),
})
.passthrough();
const InkeepRecordTypes = z.enum([
"documentation",
"site",
"discourse_post",
"github_issue",
"github_discussion",
"stackoverflow_question",
"discord_forum_post",
"discord_message",
"custom_question_answer",
]);
const InkeepRAGDocumentSchema = z
.object({
type: z.string(),
source: InkeepSourceSchema,
title: z.string().optional(),
context: z.string().optional(),
record_type: z.union([z.string(), InkeepRecordTypes]).optional(),
url: z.string().optional(),
})
.passthrough();
const InkeepRAGResponseSchema = z
.object({
content: z.array(InkeepRAGDocumentSchema),
})
.passthrough();
const completion = await client.beta.chat.completions.parse({
model: "inkeep-rag",
messages: [{ role: "user", content: "How do I get started?" }],
response_format: zodResponseFormat(InkeepRAGResponseSchema, "rag"),
});
const validationResult = completion.choices[0].message.parsed;
console.log("Schema validation successful!");
// Process the RAG documents
validationResult.content.forEach((doc, index) => {
console.log(`Document ${index + 1}:`);
console.log(`Title: ${doc.title || "N/A"}`);
console.log(`URL: ${doc.url || "N/A"}`);
console.log(`Context: ${doc.context || "N/A"}`);
console.log(`Record Type: ${doc.record_type || "N/A"}`);
console.log("---");
});
```
This example demonstrates how to use the OpenAI Node SDK to retrieve structured RAG documents from Inkeep's knowledge base. The response includes an array of documents with context, source information, and URLs.
***
sidebarTitle: Overview
title: MCP Server Overview
icon: IoSparklesOutline
-----------------------
Inkeep provides multiple ways to integrate with Model Context Protocol (MCP) clients like Claude Desktop, Cursor, and Windsurf. Choose the option that best fits your needs.
## What is MCP?
Model Context Protocol (MCP) allows AI assistants to access external tools and data sources. With Inkeep's MCP integration, you can give your AI assistant access to your knowledge base for answering questions and searching documentation.
## Choose Your Integration
### 1. Managed MCP Server (Recommended)
**Best for**: Teams who want to get started quickly without managing infrastructure.
Inkeep provides a fully managed MCP server that's ready to use with your existing knowledge base. No deployment or maintenance required.
* **Zero setup**: Works with your existing Inkeep project
* **Automatic updates**: Always has the latest features
* **Built-in analytics**: Tracks usage and performance
* **Enterprise ready**: Scales with your team
*Recommended for most users*
[Get started with Managed MCP Server β](/mcp/managed)
***
### 2. Self-Hosted Options
**Best for**: Teams who need custom control or want to integrate with existing infrastructure.
We provide open-source templates for deploying your own MCP server. These templates include the same core functionality as our managed server but give you full control over deployment and customization.
Choose your deployment platform:
* [Deploy on Vercel](/mcp/vercel-deployment)
* [Deploy on Cloudflare Workers](/mcp/cloudflare-deployment)
***
### 3. Extend Your Existing MCP Server
**Best for**: Teams who already have an MCP server and want to add Inkeep's tools to it.
If you have an existing MCP server that you want to extend with Inkeep's question-answering and search capabilities, you can use our tool implementations as a reference.
Check out our deployment templates to see how we implement the Inkeep MCP tools:
* [Vercel deployment guide](/mcp/vercel-deployment)
* [Cloudflare Workers deployment guide](/mcp/cloudflare-deployment)
You can adapt these patterns to add the same functionality to your existing server.
***
## Available Tools
Your MCP server automatically includes these tools based on your knowledge base:
| Tool Name | Description | Use Case |
| ----------------------------------- | ------------------------------------------ | ---------------------------------------- |
| `ask-question-about-{product-name}` | AI-powered Q\&A using your knowledge base | Get direct answers to specific questions |
| `search-{product-name}-docs` | Semantic search through your documentation | Find relevant content and context |
***
## Next Steps
**Ready to get started?**
1. **Quick Start**: Use our [Managed MCP Server](/mcp/managed) for immediate setup
2. **Custom Deployment**: Try [Vercel](/mcp/vercel-deployment) or [Cloudflare Workers](/mcp/cloudflare-deployment) for easy self-hosting
**Need help?** [Contact support](https://inkeep.com/contact)
***
## Supported MCP Clients
Inkeep's MCP servers work with any MCP-compatible client:
* **[Cursor](https://cursor.sh)** - AI-powered code editor
* **[Claude Desktop](https://claude.ai/desktop)** - Anthropic's desktop application
* **[Windsurf](https://windsurf.ai)** - AI development environment
* **Custom clients** - Any application implementing the MCP protocol
***
***
sidebarTitle: Managed
title: Managed MCP Server
icon: IoCloudOutline
--------------------
**Best for**: Teams who want to get started quickly without managing infrastructure.
Inkeep provides a fully managed MCP server that's ready to use with your existing knowledge base. No deployment or maintenance required.
* **Zero setup**: Works with your existing Inkeep project
* **Automatic updates**: Always has the latest features
* **Built-in analytics**: Tracks usage and performance
* **Enterprise ready**: Scales with your team
## Setup Steps
1. **Create an MCP Assistant**
* Log in to the [Inkeep Dashboard](https://portal.inkeep.com)
* Navigate to **Projects** β Select your project
* Open the **Assistants** tab
* Click **Create assistant** β Choose **MCP**
* Enter a name and click **Create**
2. **Configure Your MCP Client**
**Important**: Replace `YOUR_MCP_SERVER_URL` with the actual URL from your MCP Assistant page.
**Cursor Example:**
```json title=".cursor/mcp.json"
{
"mcpServers": {
"Inkeep MCP": {
"url": "YOUR_MCP_SERVER_URL"
}
}
}
```
**Claude Desktop Example:**
```json title="claude_desktop_config.json"
{
"mcpServers": {
"inkeepMcp": {
"command": "npx",
"args": ["-y", "mcp-remote", "YOUR_MCP_SERVER_URL"]
}
}
}
```
## Available Tools
Your MCP server automatically includes these tools based on your knowledge base:
| Tool Name | Description | Use Case |
| ----------------------------------- | ------------------------------------------ | ---------------------------------------- |
| `ask-question-about-{product-name}` | AI-powered Q\&A using your knowledge base | Get direct answers to specific questions |
| `search-{product-name}-docs` | Semantic search through your documentation | Find relevant content and context |
## Analytics & Insights
All interactions through the managed MCP server are automatically logged to your Inkeep analytics dashboard, giving you insights into:
* Most common questions
* Content gaps
* Usage patterns
* Performance metrics
## Examples in Action
### Basic Q\&A
```
User: "How do I configure rate limiting?"
Assistant: [Uses ask-question-about-inkeep tool]
Response: "Rate limiting in Inkeep can be configured..."
```
### Documentation Search
```
User: "Find information about API authentication"
Assistant: [Uses search-inkeep-docs tool]
Response: "Here are the relevant sections about API authentication..."
```
***
**Need help?** [Contact support](https://inkeep.com/contact)
***
sidebarTitle: Vercel Deployment
title: Deploy MCP Server on Vercel
icon: TbBrandVercel
-------------------
Deploy your own AI-powered MCP server on Vercel with automatic conversation logging and analytics integration.
## Overview
This self-hosted option gives you full control over your MCP server while leveraging Vercel's serverless infrastructure.
### Key Features
* **Ready-to-deploy**: Drop-in MCP server with Vercel integration
* **AI-powered tools**: Q\&A and documentation search using Inkeep's models
* **Inkeep Analytics integration**: Automatic conversation logging for insights
* **Scalable**: Leverages Vercel's serverless infrastructure
* **Custom domains**: Use your own domain for the MCP server
* **Environment variables**: Secure configuration management
***
## Quick Start
**[View the complete template on GitHub β](https://github.com/inkeep/mcp-for-vercel)**
All setup instructions, configuration details, and deployment steps are in the repository README.
The template provides a complete MCP server implementation ready to deploy:
```bash
git clone https://github.com/inkeep/mcp-for-vercel
cd mcp-for-vercel
npm install
vercel --prod
```
***
## Implementation Example
Below is a snippet of the server tool that calls the `inkeep-qa-expert` model:
```typescript title="app/[transport]/route.ts"
server.tool(
qaToolName,
qaToolDescription,
{ question: z.string().describe('Question about the product') },
{
title: `Ask AI about ${INKEEP_PRODUCT_NAME}`,
readOnlyHint: true,
openWorldHint: true,
},
async ({ question }: { question: string }) => {
try {
const qaModel = 'inkeep-qa-expert';
const response = await openai.chat.completions.create({
model: qaModel,
messages: [{ role: 'user', content: question }],
});
const qaResponse = response.choices?.[0]?.message?.content;
if (qaResponse) {
await logToInkeepAnalytics({
messagesToLogToAnalytics: [
{ role: 'user', content: question },
{ role: 'assistant', content: qaResponse },
],
});
return {
content: [
{
type: 'text' as const,
text: qaResponse,
},
],
};
}
return { content: [] };
} catch (error) {
console.error('Error getting QA response:', error);
return { content: [] };
}
},
);
```
***
## MCP Client Setup
After deploying, configure your MCP client to use your Vercel deployment:
**Cursor:**
```json title=".cursor/mcp.json"
{
"mcpServers": {
"Inkeep Custom": {
"url": "https://your-app.vercel.app/mcp"
}
}
}
```
**Claude Desktop:**
```json title="claude_desktop_config.json"
{
"mcpServers": {
"inkeep-custom": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://your-app.vercel.app/mcp"]
}
}
}
```
***
**Need help?** [Contact support](https://inkeep.com/contact)
***
sidebarTitle: Cloudflare Deployment
title: Deploy MCP Server on Cloudflare Workers
icon: TbBrandCloudflare
-----------------------
Deploy a Model Context Protocol server to Cloudflare Workers with semantic search and Q\&A capabilities.
## Overview
This self-hosted option deploys your MCP server to Cloudflare's infrastructure.
### Key Features
* **Semantic search**: RAG-powered search through your knowledge base
* **AI Q\&A**: Direct answers from an AI assistant trained on your content
* **Inkeep Analytics integration**: Logs interactions for insights and improvements
* **Serverless**: No server management required
* **Custom domains**: Use your own domain with Cloudflare
***
## Quick Start
**[View the complete template on GitHub β](https://github.com/inkeep/mcp-for-cloudflare)**
All setup instructions, configuration details, and deployment steps are in the repository README.
The template provides a complete MCP server implementation ready to deploy:
```bash
git clone https://github.com/inkeep/mcp-for-cloudflare
cd mcp-for-cloudflare
npm install
wrangler secret put INKEEP_API_KEY
wrangler deploy
```
***
## Implementation Example
Below is a snippet of the server tool that calls the `inkeep-qa-expert` model.
```typescript title="src/index.ts"
// Q&A tool using inkeep-qa-expert model
const qaTool = this.server.tool(
"ask-question-about-inkeep",
{ question: z.string().describe("Question about the product") },
async ({ question }) => {
const openai = new OpenAI({
baseURL: INKEEP_API_BASE_URL,
apiKey: INKEEP_API_KEY
});
const resp = await openai.chat.completions.create({
model: "inkeep-qa-expert",
messages: [
{ role: "system", content: "You are an AI assistant knowledgeable about Inkeep." },
{ role: "user", content: question },
],
});
const answer = resp.choices?.[0]?.message?.content;
return answer ? { content: [{ type: "text", text: answer }] } : { content: [] };
},
);
```
***
## MCP Client Setup
Configure your MCP client to use your Cloudflare Workers deployment:
**Cursor:**
```json title=".cursor/mcp.json"
{
"mcpServers": {
"Inkeep Cloudflare": {
"url": "https://your-worker-name.your-subdomain.workers.dev/mcp"
}
}
}
```
**Claude Desktop:**
```json title="claude_desktop_config.json"
{
"mcpServers": {
"inkeep-cf": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://your-worker-name.your-subdomain.workers.dev/mcp"]
}
}
}
```
***
**Need help?** [Contact support](https://inkeep.com/contact)
***
title: Add analytics to any OpenAI compatible chat
sidebarTitle: Overview
keywords: chat analytics, OpenAI integration, conversation tracking, user feedback, analytics API, conversation logging, chat monitoring, feedback collection, conversation history, API integration, chat metrics, analytics dashboard, conversation data, chat feedback, API implementation, conversation storage, chat reporting
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
With Inkeep's Analytics API, you can log your AI chat conversations to:
1. Get Inkeep's analytics and reporting for the chats
2. Provide and track "Thumbs up/down" feedback
3. Power "Share" or "Saved Chats" experiences
The Inkeep Analytics API is designed to be flexible and can log any OpenAI-compatible conversation, including those with tool calls or custom functionality.
If you're using [Inkeep's Chat API](/ai-api/chat-completions-api) to create your own chat UX or custom copilot, you should use the Analytics API to enable the same reporting as provided by the `@inkeep/cxkit-react` component library.
## Authentication
All Analytics API endpoints require authentication using an API key in the request headers. See our [Authentication Page](/analytics-api/authentication) for details.
## Log a conversation
### Initial message
To log a new conversation, make a POST request to the `/conversations` endpoint.
```javascript
const initialConversationData = {
id: "conv_1234", // optional
type: "openai",
messages: [
{
role: "user",
content: "Can I log any OpenAI-compatible conversation?",
},
{
role: "assistant",
content:
"Yes, our analytics engine is agnostic. You can log full conversations of your agent or custom copilot, even if not all interactions hit Inkeep's API endpoint.",
},
],
properties: {
// Add any custom properties here
},
userProperties: {
// Add any user-specific properties here
},
};
let currentConversation = await fetch(
"https://api.analytics.inkeep.com/conversations",
{
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify(initialConversationData),
}
).then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
});
console.log(currentConversation);
```
### Follow-up messages
To log additional messages in an existing conversation, include the `id` returned from the initial submission:
```javascript
const continueConversationData = {
id: currentConversation.id,
type: "openai",
messages: [
...currentConversation.messages,
// Add new messages
{
role: "user",
content: "Does that mean it supports logging tool calls?",
},
{
role: "assistant",
content:
"Yup, Inkeep's Analytics API is fully compatible with OpenAI chat completions endpoints, including tool calling.",
},
],
};
currentConversation = await fetch(
"https://api.analytics.inkeep.com/conversations",
{
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify(continueConversationData),
}
).then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
});
console.log(currentConversation);
```
You can provide your own IDs for conversations and messages, or Inkeep will
auto-generate them. For logging continuous exchanges in a conversation, make
sure to retain and use the same conversation ID and always include the entire
message history. `POST /conversation` works like an upsert operation.
## Submit feedback
Use the `/feedback` endpoint to log π / π feedback from your UI.
```javascript
const feedbackData = {
type: "positive", // or "negative"
messageId: "{assistant_message_id}", // e.g. currentConversation.messages[1].id
reasons: [
{
label: "accurate_code_snippet",
details: "The code worked perfectly.",
},
],
userProperties: {
// Add any user-specific properties here
},
};
fetch("https://api.analytics.inkeep.com/feedback", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify(feedbackData),
})
.then((response) => response.json())
.then((data) => console.log(data));
```
## Monitor
To view analytics for your logged conversations and feedback:
1. Go to [portal.inkeep.com](https://portal.inkeep.com)
2. Navigate to **Projects** and select the relevant one
3. View the **Chat Sessions**, **Insights**, and **Analytics** tabs
## Use for "Share" or "Saved Chats"
You can use the `GET /conversations` endpoint to retrieve logged conversations and power "Share" or "Saved Chats" features.
Here's an example of how to fetch a specific conversation:
```ts
fetch(
"https://api.analytics.inkeep.com/conversations/{existing_conversation_id}",
{
method: "GET",
headers: {
Authorization: "Bearer YOUR_API_KEY",
},
}
)
.then((response) => response.json())
.then((data) => {
// Use the conversation data to rehydrate your UI
console.log(data);
});
```
The response will contain detailed information about the conversation:
```json
{
"id": "conv_123456789",
"type": "openai",
"createdAt": "2024-07-11T10:15:30.123Z",
"updatedAt": "2024-07-11T10:16:45.678Z",
"projectId": "proj_987654321",
"integrationId": "intg_246813579",
"properties": {
"source": "web_chat"
},
"userProperties": {
"userId": "user_135792468"
},
"messages": [
{
"id": "msg_1",
"type": "openai",
"conversationId": "conv_123456789",
"createdAt": "2024-07-11T10:15:30.123Z",
"updatedAt": "2024-07-11T10:15:30.123Z",
"role": "user",
"content": "Can I log any OpenAI-compatible conversation?",
"name": null,
"links": null,
"properties": {},
"userProperties": {}
},
{
"id": "msg_2",
"type": "openai",
"conversationId": "conv_123456789",
"createdAt": "2024-07-11T10:15:40.456Z",
"updatedAt": "2024-07-11T10:15:40.456Z",
"role": "assistant",
"content": "Yes, our analytics engine is agnostic. You can log full conversations of your agent or custom copilot, even if not all interactions hit Inkeep's API endpoint.",
"name": null,
"links": null,
"properties": {},
"userProperties": {}
},
{
"id": "msg_3",
"type": "openai",
"conversationId": "conv_123456789",
"createdAt": "2024-07-11T10:16:15.789Z",
"updatedAt": "2024-07-11T10:16:15.789Z",
"role": "user",
"content": "Does that mean it supports logging tool calls?",
"name": null,
"links": null,
"properties": {},
"userProperties": {}
},
{
"id": "msg_4",
"type": "openai",
"conversationId": "conv_123456789",
"createdAt": "2024-07-11T10:16:45.678Z",
"updatedAt": "2024-07-11T10:18:45.678Z",
"role": "assistant",
"content": "Yup, Inkeep's Analytics API is fully compatible with OpenAI chat completion endpoints, including tool calling.",
"name": null,
"links": null,
"properties": {},
"userProperties": {}
}
],
"messagesOpenAIFormat": [
{
"role": "user",
"content": "Can I log any OpenAI-compatible conversation?"
},
{
"role": "assistant",
"content": "Yes, Inkeep's analytics engine is agnostic. You can log full conversations of your agent or custom copilot, even if not all interactions hit Inkeep's API endpoint."
},
{
"role": "user",
"content": "Does that mean it supports logging tool calls?"
},
{
"role": "assistant",
"content": "Yup, Inkeep's Analytics API is fully compatible with OpenAI chat completions endpoints, including tool calling."
}
]
}
```
This response includes all extended details about the conversation and its messages, including any properties you associated with it.
The `messagesOpenAIFormat` property provides the messages of the conversation in a format compatible with OpenAI's chat completions API. You can use this to implement **Share a chat**, **Saved Chats**, or any other functionality that requires retrieving an existing chat.
Here's how:
* **Share a chat** - Create an entry point in your application or UI that parses a query parameter, e.g. `?chatId=`. Then, use the `GET /conversations/{id}` endpoint to get the last state of a conversation and hydrate the chat UI in your own application. If you want to be able to "fork" shared chats, then simply use a different `id` when logging the continuation of a shared conversation to `POST /conversations`. This will log it as a separate conversation from the original.
* **Saved Chats** - Whenever a user creates a new conversation, associate that `id` with the user in your database or application. This way, you have a relationship of `chats<>user` and can display a user's history in your UI. You can also store that relationship in a user's browser session for unauthenticated contexts.
## Log usage events
In addition to logging conversations and feedback, you can also track specific usage events related to conversations or messages using the `/events` endpoint.
For example, you may want to track events like:
* `message:copied`: When a user copies a message
* `message:code_snippet:copied`: When a user runs a code snippet from a message
* `conversation:shared`: When a user shares a conversation
When logged, they will be incorporated in the Inkeep Analytics reporting.
The below shows an example of how to log these events.
```js title="log-event.js"
// Message event
const eventData = {
type: "message:copied",
entityType: "message" // 'message' or 'conversation'
messageId: "{message_id}",
};
fetch('https://api.analytics.inkeep.com/events', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify(eventData)
})
.then(response => response.json())
.then(data => console.log(data));
// Conversation Event
const conversationEventData = {
type: "conversation:shared",
entityType: "conversation"
conversationId: "{conversation_id}",
};
fetch('https://api.analytics.inkeep.com/events', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify(conversationEventData)
})
.then(response => response.json())
```
## Concepts
This glossary defines the key objects and concepts used throughout the Inkeep Analytics API and explains how they relate to each other.
### Conversation
A conversation represents a series of messages between a user and an AI assistant. Conversations are the primary unit for tracking chat interactions in the Analytics API. Each conversation contains multiple messages and can receive feedback from users. Conversations can be grouped into semantic threads based on their topical similarity.
### Message
A message represents a single interaction within a conversation, either from a user or the assistant. Messages are contained within conversations and can individually receive feedback. Users can perform various actions on messages (like copying), which are tracked as events.
### Feedback
Feedback captures user reactions to assistant messages, typically in the form of thumbs up/down reactions with optional explanations. Feedback is associated with specific messages and helps improve the quality of responses over time.
### Event
Events track specific user interactions with the Analytics API, such as copying a message, sharing a conversation, or clicking on a source. Events are always associated with either a message or a conversation entity and help analyze user engagement patterns.
### Query
Queries allow for retrieving and analyzing analytics data stored in the system. There are several types of queries:
* **Conversation queries**: Retrieve conversation data
* **Event queries**: Access logged events
* **Semantic thread queries**: Retrieve semantically linked conversation threads
### Properties / User Properties
Custom properties can be attached to Analytics API objects for filtering and segmentation. These properties allow for flexible data organization and analysis across conversations, messages, and other entities.
### SemanticThread
A semantic thread is a set of one or more related conversations grouped by semantic meaning rather than by converstion ID or timestamp. Threads connect conversations that discuss similar topics, allowing for analysis of user interests and common questions across multiple interactions.
### Project
The organizational unit that groups analytics data in the Inkeep system. Projects contain conversations, messages, and all related analytics data, typically corresponding to a specific integration or implementation.
***
title: "Authentication"
sidebarTitle: "Authentication"
icon: "LuLock"
description: "How to authenticate with the Inkeep Analytics API"
keywords: "authentication, API key, auth, bearer token, authorization header, authorization, api key generation, security"
--------------------------------------------------------------------------------------------------------------------------
## Authentication
All Analytics API endpoints require authentication using an API key provided in the request headers.
### Authentication Header
Include your API key in the `Authorization` header of each request using Bearer token authentication:
```javascript
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
```
### API Key Generation
## Get an API key
1. Log in to the [Inkeep Dashboard](https://portal.inkeep.com)
2. Navigate to the **Projects** section and select your project
3. Open the **Assistants** tab
4. Click **Create assistant** and choose **API** from the options
5. Enter a Name for your new API assistant.
6. Click on **Create**
7. A generated **API key** will appear that you can use to authenticate API requests.
### API Key Access Levels
API keys have different access levels depending on the assistant type:
* **API Integration Keys**: Provide both read and write access to the Analytics API
* **Other Integration Keys**: Some assistant types may have restricted access (write-only access)
Always use an API Integration key for full access to all Analytics API functionalities.
#### Assistant Types and Access Levels
| Assistant Type | Access Level | Description |
| ------------------- | :----------: | ---------------------------------------------------------------- |
| API (Server-side) | Full Access | Can both send and retrieve data from all Analytics API endpoints |
| Web (Docs, Website) | Write Only | Can only send data, cannot retrieve analytics |
| Slack | Write Only | Limited to sending conversation data |
| Support Copilot | Write Only | Can only log support interactions |
| Discord | Write Only | Limited to logging community conversations |
| MCP | Write Only | Limited to sending platform-specific data |
### Project Scoping
All API keys are scoped to the specific project in which they were created. An API key cannot be used to access data from other projects. This ensures proper security isolation between different projects in your Inkeep account.
### Security Best Practices
When using the API key in your applications:
1. **Never expose the API key** in client-side code
2. **Use environment variables** to store the key securely
### Rate Limiting
The API implements rate limiting to prevent abuse. If you exceed the rate limits, you may receive a `429 Too Many Requests` response. Implementation details vary based on your usage plan.
For more information on API access or issues with authentication, contact Inkeep support.
***
title: Log Conversation
description: >-
Logs a new conversation or updates an existing one with new messages. Always
include all messages.
**API Key Types:** `WEB`, `API`
full: true
\_openapi:
method: POST
route: /conversations
toc: \[]
structuredData:
headings: \[]
contents:
* content: >-
Logs a new conversation or updates an existing one with new messages.
Always include all messages.
**API Key Types:** `WEB`, `API`
***
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Get All Conversations
full: true
\_openapi:
method: GET
route: /conversations
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Delete Conversation
full: true
\_openapi:
method: DELETE
route: /conversations/{id}
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Get All Feedback
full: true
\_openapi:
method: GET
route: /feedback
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Get Feedback by ID
full: true
\_openapi:
method: GET
route: /feedback/{id}
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Log Feedback
description: |-
Logs new feedback or updates an existing one.
**API Key Types:** `WEB`, `API`
full: true
\_openapi:
method: POST
route: /feedback
toc: \[]
structuredData:
headings: \[]
contents:
* content: |-
Logs new feedback or updates an existing one.
**API Key Types:** `WEB`, `API`
***
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Log Event
full: true
\_openapi:
method: POST
route: /events
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Query Conversations
full: true
\_openapi:
method: POST
route: /query/conversations
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Query Events
full: true
\_openapi:
method: POST
route: /query/events
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Query Feedback
full: true
\_openapi:
method: POST
route: /query/feedback
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Query Semantic Threads
full: true
\_openapi:
method: POST
route: /query/semantic-threads
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Export Semantic Threads Query Results
full: true
\_openapi:
method: POST
route: /query/semantic-threads/export
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Query Property Keys
full: true
\_openapi:
method: POST
route: /query/property-keys
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Query Property Values
full: true
\_openapi:
method: POST
route: /query/property-values
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Top Search Queries
full: true
\_openapi:
method: GET
route: /query/top-search-queries
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: Weekly Search Users
full: true
\_openapi:
method: GET
route: /query/weekly-search-users
toc: \[]
structuredData:
headings: \[]
contents: \[]
-------------
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
***
title: "Pricing"
keywords: "pricing plans, sandbox access, usage limits, free trial, AI search, neural search, spam protection, bot protection, white labeling, open source pricing, subscription management, billing options, enterprise pricing, service tiers"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Can't find an answer? Reach out to [sales@inkeep.com](mailto:sales@inkeep.com?subject=Question).
We aim to account for your expected usage in the pricing we quote you. If
you're using a self-serve plan and your usage exceeds typical usage patterns,
we'll communicate with your team to find pricing that makes sense for your
scenario. Note that we monitor usage patterns to ensure fair use and maintain
service quality for all customers.
While we don't have a free tier, we do offer a free demo on your own content. To get one [schedule a call](https://inkeep.com/demo-form?cta_id=nav_demo_cta). Our team will have a sandbox prepared for you powered by your public content, in addition to reviewing your use case and answering any questions. Our team will provide that sandbox as a sharable link after the call, and with it you can try out the UI components and chat service against your own content without creating an account or providing a payment method. The sandbox will be available for 30 days after the call.
To get access to the full platform, including the dashboard, analytics, AI assistant for Slack, and other features, we'll work with you to scope a pilot for your use case.
A "search" refers to a traditional search query -- a user enters a few words or a phrase, and Inkeep returns a list of relevant documents. Our search service is available if you (optionally) use our Search Bar component or via our API. Unlimited searches are included in any plan.
Our AI search is powered by proprietary neural net and lexical search algorithms that deliver fast, highly relevant out of the box search results without any tuning. Our AI search is part of our "RAG" system we use to feed relevant content to large language models to power our "Ask AI" chat experience.
{" "}
We use a variety of mechanisms to protect our service against malicious or
miscellaneous usage. For example, we set dynamic IP-level or
organization-level throttling to prevent against volume-based attacks.
Further, we smartly detect if there is a surge of questions that seem out of
the ordinary from your company's typically usage patterns. We strive to
mitigate against these attack vectors and have not yet had downtime or cost
issues related to malicious usage. If you're particularly keen on enforcing
your protection mechanisms, we can work with you to [add
authentication](/ui-components/customization-guides/authenticate-users), add a
CAPTCHA service, send usage through your own proxy, or in general find a
solution that meets your requirements.
{" "}
By default, the terms of all of our plans ask that customers keep the Inkeep
branding in our UI components. If you require a white labeled solution, it can
be offered as an add-on to enterprise plans.
{" "}
We don't currently offer a free tier for open source projects.
{" "}
We do not currently support multi-tenant or reseller/vendor scenarios.
Log in to the [Inkeep Dashboard](https://portal.inkeep.com) and navigate to the **Billing** tab underneath **Organization**. Click on the **Manage Billing** button which will take you to the Stripe subscription management page.
In some cases, if you signed up with specific promotions or you have an Enterprise agreement with Inkeep, Stripe billing management may not be available. For those cases, please email [billing@inkeep.com](mailto:billing@inkeep.com?subject=Cancel%20Subscription).
**Note**: We're always on the look out for feedback and insights shared with us so we can take it into consideration as we build our roadmap. Please do feel free to share any feedback you have on how Inkeep did or did not fit your scenario.
***
title: Features
keywords: language support, self hosting, open source, image support, video content, multilingual support, content ingestion, documentation features, platform capabilities, technical specifications, service features, content handling, media support, platform functionality
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Can't find an answer? Reach out to [support@inkeep.com](mailto:support@inkeep.com?subject=Question).
Yes, our AI assistant should automatically answer in the language that the
user used. You can also set a 'primary language' in your project settings if
your users or documentation are primarily in a different language. This will
bias our AI and content ingestion service to account for that language (but
still work for any). You can also customize the strings or use an
internationalization solution with Inkeep's UI components
{" "}
Currently Inkeep is not setup to be a self-hostable solution. However, if your
concern is data processing or privacy concerns, review our [privacy
overview](/overview/privacy) to learn about options available for customers
with custom data processing requirements.
{" "}
While we love supporting open source teams and projects like Drizzle, Auth.js
and others, our solution is not currently open source.
{" "}
For security reasons, our UI components don't render images or content from
URLs. We typically don't ingest images out of the box, but let us know if
images are an important part of your documentation. We can enable ingestion of
images for your sources.
Yes, this is typically available as an add-on to your plan.
***
title: Troubleshooting
keywords: widget troubleshooting, Shadow DOM, custom CSS, component loading, widget display, search bar issues, chat mode, page performance, loading optimization, technical support, debugging guide, component issues, UI troubleshooting
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Can't find an answer? Reach out to [support@inkeep.com](mailto:support@inkeep.com?subject=Question).
If you're having trouble loading the Inkeep UI components, try checking the below.
Inkeep components are loaded into a "Shadow" DOM. This is done so that they don't affect your pages styles or vice versa. Use your browser's developer tools to check if there's an HTML element with an ID that contains `inkeep-shadow`. If you don't see an element that matches that description, that means there is an issue instantiating the component. This is typically due to an issue with loading the JavaScript.
If you're using the `@inkeep/cxkit-js` package, there are two `scripts` that need to be loaded:
1. The component library: ``
2. A script that includes `Inkeep.({...})` to instantiate the UI components.
Inspect your DOM to see if both of these scripts were successfully loaded. Sometimes, the issue is that script #2 loads before script #1. To prevent this, you can add an id to script #1 and use the "load" event to execute script #2.
```
inkeepScript.addEventListener("load", function () {
// embed logic
});
```
The UI components are designed to not display until custom stylesheets have been fetched. If you specify a link type style in the `styles` array in the widget configurations' theme object but any of the provided paths are invalid, this can cause the widget to not render. Please ensure that the URL is an absolute URL (like for a CDN); or, if using a relative URL, ensure it's relative to your site's root.
If you see the `inkeep-shadow` element, the issue might be that the Search Bar or Chat Button components are not being properly displayed in your page. Find all the elements with id `inkeep-widget-root` and inspect whether they are being rendered off the page or hidden by other elements.
By default, UI components use same-domain cookies in the browser to keep track of what "mode" a user last had open so that they are taken to that same mode when they next open the Inkeep Modal.
To disable this "remember" behavior, you can set `baseSettings.optOutFunctionalCookies` = `true` or use the `forceInitialDefaultView` prop in `modalSettings` which will open the modal in the `defaultView` regardless of which view was last opened.
New users will see the default search or chat experience based on your component type or if you customize `modalSettings.defaultView`.
The Inkeep UI components and related scripts are loaded asynchronously so they
don't affect page performance.
***
title: Comparisons
description: How does Inkeep compare to other AI search and chat services?
--------------------------------------------------------------------------
Teams that have evaluated Inkeep AI assistants compared to other products tend to highlight that Inkeep:
* admits when it doesn't know and guides users to support channels
* contains minimal (if any) hallucinations or search misses
* provides rich citations that help users inspect answers
* leverages many sources while prioritizing authoritative content
That said - don't take our word for it! Use our [free trial](https://inkeep.com/demo-form) or [schedule a call](https://go.inkeep.com/demo) to test out Inkeep with your toughest questions.
## Comparisons
Teams typically look for a managed solution so that they don't have to invest engineering resources in:
* Building the pipelines and infra to ingest and keep content up to date
* Experimenting with LLM models and RAG techniques to get high-quality results
* Building user-friendly chat UIs that are embeddable anywhere
* Providing insights to product and documentation teams
Algolia is a popular service that is particularly focused on just search. While Algolia offers "Neural" or "AI search", those terms refer to search algorithms rather than "AI chat" or conversational experiences.
While Inkeep similarly provides a neural search service (with unlimited usage in any plan), we also provide:
* AI chat experiences powered by large language models and your own content
* An analytics platform to analyze user conversations - not just search queries.
* Slack and Discord bots that can be used in your employee or customer-facing channels
* Zero-effort ingestion of any website using our intelligent scraper (no need for managing content over APIs!)
Many teams use Inkeep for just the chat experiences - you don't have to replace your existing Algolia search experience if you're happy with it.
Intercom is a general support solution for any type of product - consumer-facing, B2B SaaS products, etc. Intercom's offering includes "Fin", an AI chatbot focused on support deflection.
In comparison to Intercom, Inkeep has:
* UX experiences tailored for developer-facing or technical products
* Assistants for any touchpoint - Slack, Discord, Search Bar, Chat button, etc.
* Zero-effort ingestion of any content source
* Tools to help documentation teams address content gaps