Widget lifecycle management
Kapa's JavaScript API supports render() and unmount() functions which give
you manual control over the widget state. They are especially useful in
Single-Page Applications (SPAs) or other environments where you need to change
the widget's visibility or behavior across different pages.
Overview
The render() function asynchronously
mounts and initializes the global Kapa object. It optionally accepts an
onRender callback that executes after the widget has been fully rendered. Use
this callback to perform subsequent actions (such as opening the widget) to
ensure they occur only after initialization is complete.
The unmount() function removes the
widget's DOM elements and clears its references. Call this when you want to
remove the widget from the page (for example, when navigating away from a page
that should display the widget).
Use case
In SPAs, where the widget exists outside your component tree, you can control its lifecycle manually, rendering it only on pages that require it and unmounting it otherwise.
The lifecycle functions provide an API for manually transitioning between the possible widget states:
- Unmounted: The widget is completely removed from the DOM.
- Mounted and closed: The widget is rendered but not open.
- Mounted and opened: The widget is rendered and actively open.
Preinitialize Kapa
When you manage the widget's lifecycle manually using the JavaScript API, you
may want to consider preinitializing Kapa
to avoid calling functions before the script has loaded. Preinitializing Kapa
ensures that calls to render() and unmount() are queued properly even if
the widget script hasn’t finished loading, preventing errors when these
functions are called early.
Usage examples
The following examples show different examples of how to manage the widget's
lifecycle using the render() and unmount() functions.
These examples assume you have preinitialized Kapa, so
calls made before the widget script loads are queued. They also reference a
loadScriptIfNotExists() setup function, which loads the widget and disables
the default render-on-load behavior. See
Appendix: setup function.
Vanilla JavaScript
// Ensure the widget script is loaded
loadScriptIfNotExists();
// Render the widget with an onRender callback to open it once rendered
window.Kapa("render", {
onRender: () => window.Kapa("open"),
});
// If the widget is already rendered on this page, call open directly
window.Kapa("open");
loadScriptIfNotExists();
// calling render when the script is already rendered is harmless,
// it will just log a warning: “widget already rendered”
window.Kapa("render");
// Unmount the widget in case it was rendered on another page
window.Kapa("unmount");
React
In React, use the useEffect hook to load the script and clean up when the
component unmounts. Load the script with the
setup function, which creates the element with
document.createElement() and appends it to the document. Do not add the
script from inside a component with a JSX <script> tag,
dangerouslySetInnerHTML, or innerHTML. These methods can add the script
element to the DOM without executing it. This does not apply to the
Next.js installation methods,
which load the script correctly.
useEffect(() => {
loadScriptIfNotExists();
window.Kapa("render", {
onRender: () => {
window.Kapa("open");
},
});
return () => window.Kapa("unmount");
}, []);
useEffect(() => {
loadScriptIfNotExists();
window.Kapa("render");
return () => window.Kapa("unmount");
}, []);
Appendix: setup function
function loadScriptIfNotExists() {
const scriptSrc = "https://widget.kapa.ai/kapa-widget.bundle.js";
// Check if the script already exists in the document
if (document.querySelector(`script[src="${scriptSrc}"]`)) {
console.log("Website Widget script is already loaded.");
return;
}
const script = document.createElement("script");
// Set the async property correctly
script.async = true;
script.src = scriptSrc;
// Define other script attributes
const attributes = {
"data-website-id": "6d04c434-4090-4ebf-aeb3-8e90645a504d",
"data-project-name": "kapa.ai",
"data-project-color": "#5B4CFE",
"data-project-logo": "kapa.ai/assets/logo.png",
"data-render-on-load": "false",
};
// Set attributes on the script element
Object.entries(attributes).forEach(([key, value]) => {
script.setAttribute(key, value);
});
// Append to the document head
document.head.appendChild(script);
}