Developer Reference for Widget Integration — Login/Logout, Sessions, and JS Functions
Developer reference for widget integration — full list of installation code options, JS functions (push, open, close, toggle, reset, destroy, track), what to do right after SPA login and during logout, when to re-identify users, the 24-hour widget session and past conversations, page history, CSP, and mobile display. Keywords: widget SDK, Lenit.reset, logout, getToken, CSP, trackPageView.
Updated
Developers refer to this document when attaching the widget to their service code. For installation screen guidance, see Installing the widget — widget popup and board link. For how to create signatures (JWT·HMAC) and the differences between methods, see User identification (SSO) and customer attributes (traits).
Installation code and options
What does the installation code look like?
You put the settings into the window.Lenit queue and load the script asynchronously. Even if the script loads late, the settings queued in advance are applied as-is. Copy the actual code from the Connect code tab under Settings > Integrations > Service integrations — the board key is already filled in.
<script>
window.Lenit = window.Lenit || [];
window.Lenit.push({ boardKey: "vb_live_…", userId: "user_123" });
</script>
<script src="https://lenit.cloud/widget.js" async></script>
Calling Lenit.init(...) before the script has loaded causes an error. Use push at first; after the script has loaded, either Lenit.push or Lenit.init works.
What options identify the customer?
Only the board key (boardKey) is required. Include the rest when you want to tell the widget who the logged-in member is.
| Option | Default | Meaning |
|---|---|---|
boardKey | Required | Workspace board key — a value that is safe to make public |
userId | None (anonymous) | The logged-in member's unchanging internal ID — do not include email or phone number |
userIdSignature | None | HMAC signature of userId (② userId + signature method) |
token | None | JWT signed by the server (① JWT method) |
getToken | None | A function that fetches a fresh JWT each time identification is needed — return it via callback or Promise within 5 seconds |
profile | None | Name, email, photo (name·email·avatarUrl) — used only with method ② when the signature is valid |
traits | None | Customer attributes (e.g., plan) — when using JWT, the values inside the token are used |
What options change the launcher and screen?
All are optional. If you don't include them, the defaults below apply.
| Option | Default | Meaning |
|---|---|---|
position | "bottom-right" | Button position — "bottom-left" is also allowed |
color | Launcher color from widget settings | Button color — if set in code, it takes precedence over the widget settings color (if neither is set, the brand color is used) |
zIndex | 2147483647 | Stacking order — adjust when it overlaps site elements |
showButton | true | When false, hides the default launcher button |
customLauncherSelector | None | Opens the widget when your own button (CSS selector) is clicked — the default button is hidden |
language | Customer's browser language | Sets the widget language to "ko" or "en" |
trackPageView | true | When false, page views are not recorded |
openMode | "panel" | When "newtab", opens the public board in a new tab instead of the widget |
Can I set the widget language in the installation code?
Yes. Include language: "ko" or "en", and the launcher text and widget open in that language. If you omit it, the customer's browser language is followed — Korean if Korean, otherwise English. Passing any other value logs a warning in the developer console and the widget opens in the browser language.
Customers can also switch between 한국어/English directly in the widget settings. For the full language rules, see Language and time zone — languages shown on screens, emails, and to customers, and the reference time zone.
When should I use openMode: "newtab"?
Use it only where the widget screen (iframe) is difficult to display. When the launcher is clicked, the public board opens in a new tab instead of the widget, and chat is not included. If you use user identification, use the default ("panel").
Controlling the widget with code
What functions can I call from code?
After the script has loaded, you can call the functions below. Before it loads, use only window.Lenit.push(settings).
| Function | What it does |
|---|---|
Lenit.push(settings) · Lenit.init(settings) | Redraws the widget with new settings — call right after login |
Lenit.open() | Opens the widget (home) |
Lenit.open({ tab: "chat", prefill: "…" }) | Opens the new inquiry screen directly and fills the input with the text |
Lenit.close() · Lenit.toggle() | Close · close if open, open if closed |
Lenit.reset() (= Lenit.logout()) | Logs out — clears the previous person's session, chats, and notification badges, and restarts anonymously |
Lenit.destroy() | Removes the widget from the page — to show it again, call Lenit.push(settings) |
Lenit.track("name", { properties }) | Records customer behavior |
Can I make the new inquiry screen open immediately when a button is clicked?
Yes. Call Lenit.open({ tab: "chat", prefill: "text" }). The new inquiry screen opens immediately and the input is filled with the text (up to 1,000 characters). The customer presses send themselves. Calling Lenit.open() without arguments opens the widget home.
document.querySelector("#contact-btn").addEventListener("click", () => {
Lenit.open({ tab: "chat", prefill: "Question about billing" });
});
To open only via your own button without the default launcher, include showButton: false in the installation code or use customLauncherSelector.
Where can I see events sent with Lenit.track()?
They accumulate under Recent activity in the customer information panel of the inbox. They appear chronologically alongside chats, ideas, votes, and comments, and the number of attached properties is shown next to the event name.
Lenit.track("Order Completed", { plan: "pro", amount: 29000 });
Only events from customers identified via user identification (userId) are recorded — events from anonymous visitors are not saved. Events are not used for customer group conditions or campaign targeting, so pass values you want to group by as traits.
Login, logout, and the widget
After logging in to my SPA, the widget still shows as anonymous
Call Lenit.push(settings) once more after login completes. The widget identifies the customer using the values passed in the installation code. In sites that change screens without reloading (SPA), the widget drawn at first stays anonymous, so calling it again with the logged-in user's values (userId·token·getToken) redraws the widget and identifies that user.
// Right after successful login — fetchLenitToken is a function that fetches a new JWT from the server
Lenit.push({ boardKey: "vb_live_…", getToken: fetchLenitToken });
Sites that open a new page on each navigation need nothing extra — if the installation code on the first page after login passes the logged-in user's values, that's enough.
How do I log the widget out when users log out of my service?
Call Lenit.reset() (the same as Lenit.logout()) in your logout handling. It clears the session, chat identity, and unread indicators stored in the widget, closes the open widget, and restarts anonymously.
Sites that open a new page on each navigation: after logout, as soon as the next page's installation code omits userId or passes a different value, the widget automatically discards the previous person's information. SPAs that log out without reloading must call reset to update on the spot.
Does the widget show the previous customer's conversations when a different customer uses a shared PC?
No. When the userId in the install code (or the userId inside the token) changes, the widget discards the previous person's session, conversation identity, and notification display, and identifies the new person from scratch. However, if you don't call Lenit.reset() on a logout screen without a page reload, the widget will remain tied to the previous person until the next person logs in.
When the Widget Re-identifies Users and Widget Sessions
When does the widget re-identify a customer?
If you use getToken, the widget re-identifies the customer every time it loads. If you use a fixed token or userId (with a signature), the widget reuses the saved session in the same browser and re-identifies only in the following cases:
- When the widget loads for the first time in that browser
- When the person in the install code changes — login, logout, or a different member
- When the widget loads again more than 6 hours after the last identification
- When the widget session has ended (see "How long does a widget session last?" below)
Customer attributes (traits) and the name, email, and photo passed with the signature are updated during re-identification.
I changed customer attributes (traits), but the changes are applied late
Attributes are applied only when the widget re-identifies. If you use a fixed token or userId, the previous values remain in the same browser until the widget loads again more than 6 hours after the last identification. For values that must take effect immediately, such as a subscription plan, have the token issued via getToken — the widget re-identifies with a new token every time it loads.
The last-visit time in the customer list is updated separately: every minute while the widget is open and the tab is visible.
How long does a widget session last?
24 hours after it was last used. The widget exchanges messages and notifications using the session it received during identification, and while it is in use the session is automatically extended every hour. When a session ends, the widget re-identifies on its own the next time it loads, so there is nothing you need to do.
This is separate from the JWT expiration time (exp) — the token is only used during identification. If a fixed token has already expired when re-identification happens, that customer opens as anonymous, so include a new token on each page or use getToken.
If a customer returns after a day or opens the widget on another device, will past conversations be visible?
Customers identified with a signature (JWT or userId + signature) can see all their conversations on any device.
Customers who send only a userId without a signature, or who inquire anonymously, see only the conversations created in that browser's widget session (messages the company sent that haven't been answered yet are also shown). So past conversations won't appear on other devices or browsers, and if the customer doesn't return for more than 24 hours and the session ends, they disappear from the widget list even in the same browser. This is because an unsigned userId can be impersonated by anyone.
Conversations remain in the inbox, and customers can return to them through Continue conversation in the reply notification email. To make conversations visible across devices, identify customers using the signed method.
Page History and Privacy
What page information does the widget send?
It sends the address and title of the pages the customer viewed, so they appear in the Recently Viewed Pages section of the customer information panel in the inbox. This covers the page where the widget first loads and pages that change without a reload (SPA routing). The same address is sent only once every 5 minutes.
Only customers who arrive with user identification (userId) are recorded. To turn this off, add trackPageView: false to the install code. Access environment information such as browser, OS, language, time zone, and referral source is sent during identification regardless of this setting.
Are values such as tokens in a page URL stored?
No. When sending the page address to Lenit, the widget keeps only the origin and path, keeps only the query parameters utm_source, utm_medium, utm_campaign, utm_term, utm_content, and ref, and removes everything after #. Page history, track events, the page where a conversation was started, and referral sources all follow the same rule, so values like ?token= or #access_token= are never stored in Lenit.
Content Security Policy (CSP) and Mobile
The widget doesn't appear because of CSP. Which addresses should I allow?
Allow https://lenit.cloud for the script and widget screen, and https://api.lenit.cloud for communication. The widget loads https://lenit.cloud/widget.js and displays the widget screen (iframe) from the same address, while communication, including real-time notifications, goes through https://api.lenit.cloud.
| CSP directive | Address to allow |
|---|---|
script-src | https://lenit.cloud |
frame-src | https://lenit.cloud |
connect-src | https://api.lenit.cloud |
Photos and images in the new reply preview above the launcher are loaded directly from your page. If you have restricted img-src, only the photos in the preview will not appear, and the widget will otherwise work normally.
How does the widget look on mobile?
When the widget is first opened and the screen width is less than 520px, it covers the entire screen. While it's open, the launcher button is hidden and scrolling of the page behind it is locked. Close it using the X at the top of the widget.
On wider screens, it opens as a 400px-wide panel above the launcher (up to 720px high; it shrinks if the screen is short). When an announcement, help document, or campaign body is expanded, the width increases to 470px. The launcher is a 60px-diameter circular button, positioned 24px from the bottom corner of the screen.