Jetlink JavaScript SDK user guide
Use the Jetlink JavaScript SDK to add Web Messenger to your website, customize its appearance and behavior, pass user information, and display proactive messages.
This guide covers installation, Messenger settings, language selection, user identification, contact information collection rules, SDK functions, events, and proactive message examples. It explains both the existing direct user data method and the new JWT authentication method.
Recommended method: JWT user authentication. We recommend using JWT when passing the identity and profile information of logged-in users to Jetlink. A server-signed JWT helps prevent modified user information from the browser from being accepted as a valid identity. Choose this more secure alternative to direct field submission for new integrations, and plan to migrate existing integrations to JWT.
1. Installation and channel credentials
Where can I find the App ID and App Token / App Key?
In the Jetlink dashboard, open Settings → Web Messenger. You can also use this direct link. Select the relevant Web Messenger channel from the list at the top, then open the Install on Your Website tab.
In the installation code, the Jetlink.Init(...) call takes the App ID as its first parameter and the channel installation key as its second parameter. The README labels the second parameter YOUR-APP-TOKEN; this guide uses YOUR_APP_KEY. Replace both placeholders with the corresponding values from your dashboard.
The installation key and the JWT secret are different. The App ID and App Key are used in the browser installation script. The JWT secret stays on the server and is used to sign user tokens.
Basic installation
Add the following code before the closing </body> tag on every page where Messenger should appear. If you use a shared page template, you can add it there once. Do not include multiple Jetlink installation snippets on the same page.
<script type="text/javascript"> var jetlinkScript = document.createElement("script"); jetlinkScript.src = "https://public.jetlink.io/Sdk/Jetlink.js?j=" + Date.now() / 1000; jetlinkScript.onload = function () { // Configure appearance, language, and rules here. Jetlink.Init("YOUR_APP_ID", "YOUR_APP_KEY"); }; document.head.appendChild(jetlinkScript); </script>
After the SDK script has loaded, place SDK customization code inside onload, before calling Jetlink.Init. Messenger initialized without user information can be used by anonymous visitors.
2. Messenger appearance settings
Configure the following properties through Jetlink.Options. The values in the table are examples, not defaults. Replace image URLs with your own HTTPS URLs.
| Jetlink.Options property | Description | Example value |
|---|---|---|
ShowEmojiButton | Shows or hides the emoji button. | true |
LauncherImageUrl | Image URL for the Messenger launcher button. | "https://example.com/chat-icon.png" |
LauncherType | Launcher shape: "circular" or "cornered". | "circular" |
ChatWindowBackgroundImageUrl | Chat window background image. | "https://example.com/chat-background.png" |
MessageTextBoxPlaceholder | Placeholder text in the message input field. | "Type your message..." |
ShowAttachmentButton | Shows or hides the attachment button. | true |
FontFamily | Messenger font family. | "Arial" |
LauncherStyleBehaviour | Launcher styling mode: "default" or "custom". For custom dimensions, use "custom". | "default" |
LauncherHeight | Launcher image height; custom sizing setting. | "100" |
LauncherWidth | Launcher image width; custom sizing setting. | "100" |
Height | Messenger window height. | "500" |
LauncherBorderColor | Launcher border color. | "#ccc" |
NewConversationButtonBackgroundColor | New conversation button background color. | "#cdcdcd" |
NewConversationButtonFontColor | New conversation button text color. | "#cdcdcd" |
HeaderGeneralFontColor | General header text color. | "#cdcdcd" |
ConversationListPageGeneralFontColor | General text color on the conversation list page. | "#cdcdcd" |
EditorPageGeneralFontColor | General text color on the chat screen. | "#cdcdcd" |
AgentMessageBackgroundColor | Agent/assistant message bubble background color. | "#cdcdcd" |
AgentMessageFontColor | Agent/assistant message text color. | "#cdcdcd" |
UserMessageBackgroundColor | User message bubble background color. | "#cdcdcd" |
UserMessageFontColor | User message text color. | "#cdcdcd" |
EditorPageBackButtonBackgroundColor | Background color of the back button on the chat screen. | "#cdcdcd" |
HeaderAvatarImageBorderColor | Header avatar border color. | "#cdcdcd" |
EmojiButtonBackgroundColor | Emoji button background color. | "#cdcdcd" |
EmojiButtonInnerColor | Emoji button icon/inner color. | "#cdcdcd" |
AttachmentButtonBackgroundColor | Attachment button background color. | "#cdcdcd" |
AttachmentButtonInnerColor | Attachment button icon/inner color. | "#cdcdcd" |
EditorPageAgentImageListWindowBorderLineColor | Border color of the agent image list area on the chat screen. | "#cdcdcd" |
MessageStatusFontColor | Message status text color. | "#cdcdcd" |
HeaderGeneralBackgroundColor | General header background color. | "#cdcdcd" |
GeneralBackgroundColor | General Messenger background color. | "#cdcdcd" |
Appearance customization example
// After the SDK loads, before calling Jetlink.Init: Jetlink.Options.LauncherImageUrl = "https://example.com/chat-icon.png"; Jetlink.Options.LauncherType = "circular"; Jetlink.Options.LauncherStyleBehaviour = "custom"; Jetlink.Options.LauncherHeight = "100"; Jetlink.Options.LauncherWidth = "100"; Jetlink.Options.Height = "500"; Jetlink.Options.FontFamily = "Arial"; Jetlink.Options.MessageTextBoxPlaceholder = "Type your message..."; Jetlink.Options.ShowEmojiButton = true; Jetlink.Options.ShowAttachmentButton = true; Jetlink.Options.HeaderGeneralBackgroundColor = "#08052e"; Jetlink.Options.HeaderGeneralFontColor = "#ffffff";
3. Language settings
The SDK reference documents tr for Turkish and en for English. Set the language before calling Jetlink.Init.
Jetlink.Options.Language = "en"; // English // For Turkish: Jetlink.Options.Language = "tr";
4. Passing user information: two methods
There are two ways to pass a logged-in user's identity and profile information to Jetlink: send user fields directly or send a server-signed JWT. Both approaches use Jetlink.SetUser to pass information to the SDK, but the source of the data and how it is verified differ.
| Topic | Direct user data | JWT — Recommended |
|---|---|---|
| Data passed to the SDK | SourceUserId, Email, Phone, Name, Surname fields | Server-generated signed token: { Jwt: token } |
| Source of user data | Plain fields submitted by the browser | Token payload verified and signed by the server |
| Integrity and identity assurance | This method alone does not provide server-signed identity verification; browser fields can be modified. | Protects against accepting modified user information without a valid signature. |
| Dashboard setting | JWT authentication must be disabled. | JWT authentication must be enabled. |
| Recommendation | Documented for compatibility with existing integrations. | Recommended for new integrations and for upgrading existing systems to secure user identification. |
Prefer JWT for passing user information. Verify the user's identity in your backend and pass it to Jetlink in a signed JWT instead of relying solely on a user ID received from the browser. Keeping the secret exclusively on the server is fundamental to this security model.
4.1. Method 1 — Passing user information directly
Use this method when Authenticate users with JWT is disabled. Pass information about the current user of your application using the following object.
var user = { SourceUserId: "54355353534", Email: "user@example.com", Phone: "+905321231212", Name: "Jane", Surname: "Doe" }; Jetlink.SetUser(user);
| Field | Description |
|---|---|
SourceUserId | The user's unique ID in your own system. |
Email | The user's email address. |
Phone | The user's phone number. |
Name | The user's first name. |
Surname | The user's last name. |
Field names are case-sensitive and must match the example. In your application, replace the sample values with the logged-in user's information.
Complete installation example for direct user data
<script type="text/javascript"> var jetlinkScript = document.createElement("script"); jetlinkScript.src = "https://public.jetlink.io/Sdk/Jetlink.js?j=" + Date.now() / 1000; jetlinkScript.onload = function () { Jetlink.SetUser({ SourceUserId: "54355353534", Email: "user@example.com", Phone: "+905321231212", Name: "Jane", Surname: "Doe" }); Jetlink.Init("YOUR_APP_ID", "YOUR_APP_KEY"); }; document.head.appendChild(jetlinkScript); </script>
Security difference: With direct submission, user information can be changed in the browser. Passing these fields does not constitute server-signed proof of identity. We recommend migrating to JWT to identify logged-in users reliably.
4.2. Method 2 — Secure user identification with JWT (recommended)
With JWT, user identity and profile information are prepared on your server, signed with the Jetlink secret using HS256, and delivered to the browser as a single token. Jetlink identifies the user through a valid token; when JWT authentication is enabled, user information is read only from the token.
- The user logs in to your application.
- Your backend verifies the session and reads the user record.
- Your backend signs the user information with the JWT secret and embeds the token in the script when rendering the page.
- The browser passes the prepared token by calling
Jetlink.SetUser({ Jwt: token }). - Messenger is initialized with
Jetlink.Init.
A client without the secret cannot change the user ID or profile fields in the payload while preserving a valid signature. This makes JWT more secure than direct field submission. A JWT signature is not encryption; the token contents can be read.
4.2.1. Accessing JWT settings and the secret
- Open Settings → Web Messenger and select the relevant channel.
- Open Customize Messenger → User Authentication (JWT).
- Enable Authenticate users with JWT.
- Select a duration in JWT validity period.
- Use the copy icon next to JWT secret to copy the key.
- Store the key only in your backend's secret storage. The examples below read it from the
JETLINK_JWT_SECRETenvironment variable.
Available validity periods: 5 minutes, 10 minutes, 15 minutes, 30 minutes, 1 hour, 12 hours, 1 day, 7 days, and 30 days. Tokens with iat values older than the selected period are rejected. Generate a new token on each page load or application session.
Do not put the JWT secret in client-side code. The secret must not appear in HTML, JavaScript bundles, mobile application code, or API responses sent to the browser. Only the signed user token is sent to the browser.
When JWT is enabled, visitors who do not provide a token use Messenger anonymously. When JWT is disabled, user information can be passed as direct fields.
4.2.2. JWT payload fields
user_id and iat are required. All other fields are optional. Use the exact field names shown below.
| Field | Type / requirement | Description |
|---|---|---|
user_id | String · Required | The unique, persistent user ID in your application. Example: "100001". |
iat | Number · Required | Token creation time as a Unix timestamp in seconds. |
email | String · Optional | Email address. |
phone | String · Optional | Phone number. Example: "905551112233". |
name | String · Optional | First name. |
surname | String · Optional | Last name. |
avatar_url | String · Optional | Profile image URL. |
custom_fields | Object · Optional | Additional user information, such as role and department. |
{ "user_id": "100001", "email": "john.doe@example.com", "phone": "905551112233", "name": "John", "surname": "Doe", "avatar_url": "https://example.com/avatar.png", "custom_fields": { "role": "customer", "department": "sales" }, "iat": 1790860807 }
The iat value in this JSON is illustrative only. Do not use a fixed timestamp in production; use the current server time for every new token. To calculate it manually in JavaScript, use Math.floor(Date.now() / 1000); Date.now() alone returns milliseconds.
Use a persistent user_id for the same user; do not generate a random ID on every page load. Do not sign identity or profile fields from the browser without verifying them. Values such as role in custom_fields do not replace your application's authorization checks.
Mapping direct user fields to JWT fields
| Direct user data | JWT payload |
|---|---|
| SourceUserId | user_id |
| Email | email |
| Phone | phone |
| Name | name |
| Surname | surname |
JWT also includes avatar_url, custom_fields and the required iat field. Consistently map the existing user's SourceUserId value to the JWT user_id field.
4.2.3. Generating the token on the server
Node.js and jsonwebtoken
Generate tokens only in your backend application. Add the jsonwebtoken package to your project:
npm install jsonwebtoken
The following function accepts the user record verified by your server. Fields such as id and firstName belong to the sample application model; map them to your own data model.
const jwt = require("jsonwebtoken"); const secret = process.env.JETLINK_JWT_SECRET; if (!secret) { throw new Error("JETLINK_JWT_SECRET must be configured."); } function createJetlinkUserJwt(user) { if (user.id === undefined || user.id === null || String(user.id) === "") { throw new Error("A user ID is required."); } const payload = { user_id: String(user.id), email: user.email, phone: user.phone, name: user.firstName, surname: user.lastName, avatar_url: user.avatarUrl, custom_fields: { role: user.role, department: user.department } }; // jsonwebtoken automatically adds iat using the current time. return jwt.sign(payload, secret, { algorithm: "HS256" }); }
Use the secret copied from the dashboard as a text value. Do not apply Base64 or hex decoding to it. In this example, iat is added automatically; do not use noTimestamp: true.
Node.js — Generating the token when rendering the page
The following example is for an existing Express application using EJS. requireAuthenticatedSession represents your application's session authentication middleware, and req.user represents the user record verified by the backend. Replace these with the corresponding components in your application.
After login, the token is generated while the account page is rendered on the server and is passed to the page template. The browser does not need to make a separate API call to obtain it.
// In your existing Express application, using createJetlinkUserJwt above: // Assumes the EJS view engine is configured in the application. app.get("/account", requireAuthenticatedSession, (req, res) => { if (!req.user) return res.redirect("/login"); // Do not store user-specific HTML in shared caches. res.set("Cache-Control", "private, no-store"); const userJwt = createJetlinkUserJwt(req.user); return res.render("account", { userJwt }); });
C# / ASP.NET Core — Generating a JWT
The following example is for an ASP.NET Core MVC application. It produces the same fields, HS256 signature, and iat timestamp in seconds as the Node.js example. Add the JWT package to your project:
dotnet add package System.IdentityModel.Tokens.Jwt
You can place token generation in a server-side helper class. JetlinkUser is the sample data model, populated from the verified user record in your application.
using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Text; using Microsoft.IdentityModel.Tokens; public sealed record JetlinkUser( string Id, string? Email = null, string? Phone = null, string? Name = null, string? Surname = null, string? AvatarUrl = null, Dictionary<string, object>? CustomFields = null); public static class JetlinkTokenFactory { public static string Create(JetlinkUser user, string secret) { if (string.IsNullOrWhiteSpace(user.Id)) throw new ArgumentException("A user ID is required."); if (string.IsNullOrWhiteSpace(secret)) throw new ArgumentException("The JWT secret is required."); // Use the text value of the key from the dashboard. var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)); var credentials = new SigningCredentials( signingKey, SecurityAlgorithms.HmacSha256); var payload = new JwtPayload { ["user_id"] = user.Id, ["iat"] = DateTimeOffset.UtcNow.ToUnixTimeSeconds() }; // Omit empty optional fields. if (!string.IsNullOrWhiteSpace(user.Email)) payload["email"] = user.Email; if (!string.IsNullOrWhiteSpace(user.Phone)) payload["phone"] = user.Phone; if (!string.IsNullOrWhiteSpace(user.Name)) payload["name"] = user.Name; if (!string.IsNullOrWhiteSpace(user.Surname)) payload["surname"] = user.Surname; if (!string.IsNullOrWhiteSpace(user.AvatarUrl)) payload["avatar_url"] = user.AvatarUrl; if (user.CustomFields is { Count: > 0 }) payload["custom_fields"] = user.CustomFields; var token = new JwtSecurityToken(new JwtHeader(credentials), payload); return new JwtSecurityTokenHandler().WriteToken(token); } }
iat is written as a numeric Unix timestamp, and custom_fields as a JSON object. The secret is converted directly from text using Encoding.UTF8.GetBytes, without Base64 or hex decoding. As in the Node.js example, store the key in the JETLINK_JWT_SECRET environment variable or your server's secret storage.
C# — Generating the token in a controller and passing it to a ViewModel
This example assumes that your existing ASP.NET Core authentication is configured. [Authorize] restricts the page to authenticated users. User fields are read from the verified User claims; adapt claim names to your identity system. If profile information is stored in a database, read the record in the backend using the verified user ID and populate the model.
using System; using System.Security.Claims; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; public sealed class AccountPageViewModel { public string UserJwt { get; init; } = string.Empty; } [Authorize] public sealed class AccountController : Controller { [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] public IActionResult Index() { // This ID comes from your existing authentication mechanism. var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (string.IsNullOrWhiteSpace(userId)) return Forbid(); var secret = Environment.GetEnvironmentVariable("JETLINK_JWT_SECRET") ?? throw new InvalidOperationException("JETLINK_JWT_SECRET must be configured."); var user = new JetlinkUser( Id: userId, Email: User.FindFirst(ClaimTypes.Email)?.Value, Phone: User.FindFirst(ClaimTypes.MobilePhone)?.Value, Name: User.FindFirst(ClaimTypes.GivenName)?.Value, Surname: User.FindFirst(ClaimTypes.Surname)?.Value); return View(new AccountPageViewModel { UserJwt = JetlinkTokenFactory.Create(user, secret) }); } }
In production, place these classes within your project's namespace structure. If you need an avatar or additional fields, populate the AvatarUrl and CustomFields properties of JetlinkUser from the server-side user record. Do not log token or secret values.
4.2.4. Browser integration after login
At this point, the JWT is assumed to have been generated in the backend. The server inserts the token value into the Jetlink script while rendering the HTML page. The browser only loads the SDK and passes the prepared token using Jetlink.SetUser; it does not use fetch, AJAX, or a separate token API request to retrieve a token.
Node.js / EJS page template
Use this code in views/account.ejs. userJwt is the server-generated JWT passed to the template by the page handler above. JSON.stringify writes the token as a JavaScript string value.
<script type="text/javascript"> var userJwt = <%- JSON.stringify(userJwt) %>; var jetlinkScript = document.createElement("script"); jetlinkScript.src = "https://public.jetlink.io/Sdk/Jetlink.js?j=" + Date.now() / 1000; jetlinkScript.onload = function () { Jetlink.SetUser({ Jwt: userJwt }); Jetlink.Init("YOUR_APP_ID", "YOUR_APP_KEY"); }; document.head.appendChild(jetlinkScript); </script>
C# / Razor page template
Use this code in the controller's Views/Account/Index.cshtml view. AccountPageViewModel may need your project's namespace added to the @model directive.
@model AccountPageViewModel @using System.Text.Json <script type="text/javascript"> var userJwt = @Html.Raw(JsonSerializer.Serialize(Model.UserJwt)); var jetlinkScript = document.createElement("script"); jetlinkScript.src = "https://public.jetlink.io/Sdk/Jetlink.js?j=" + Date.now() / 1000; jetlinkScript.onload = function () { Jetlink.SetUser({ Jwt: userJwt }); Jetlink.Init("YOUR_APP_ID", "YOUR_APP_KEY"); }; document.head.appendChild(jetlinkScript); </script>
In the Razor example, JsonSerializer.Serialize converts the token to a string literal suitable for JavaScript. Html.Raw is used only to write this serialized, server-generated token; do not write unverified user input directly into a script.
General form of the server-rendered script
The SERVER_GENERATED_USER_JWT placeholder below represents the value replaced by the backend with the actual token when rendering the page. Do not use one fixed token for all users.
<script type="text/javascript"> var jetlinkScript = document.createElement("script"); jetlinkScript.src = "https://public.jetlink.io/Sdk/Jetlink.js?j=" + Date.now() / 1000; jetlinkScript.onload = function () { Jetlink.SetUser({ Jwt: "SERVER_GENERATED_USER_JWT" }); Jetlink.Init("YOUR_APP_ID", "YOUR_APP_KEY"); }; document.head.appendChild(jetlinkScript); </script>
The JWT signing key is the value that remains secret. Because the user token is passed to the SDK, it is accessible in the rendered page and the browser. Omitting a separate token request does not hide the token from the browser. Do not place user-specific HTML in shared caches, and serve it over HTTPS.
Do not run these examples alongside the anonymous installation snippet. On a logged-in page, use a single installation example for your server technology.
Call order and field naming
- The backend verifies the user's application session.
- The user payload and JWT are created in the backend.
- The server writes the token into the page's Jetlink script.
- The browser loads
Jetlink.js. - First call
Jetlink.SetUser({ Jwt: token }), thenJetlink.Init.
The SDK field is named Jwt with an uppercase J. Token payload fields use lowercase names such as user_id, email and custom_fields. When JWT authentication is enabled, do not send profile information as additional direct fields; add it to the server-side payload.
4.2.5. Token validity and session management
How is the validity period evaluated?
Jetlink evaluates the token's iat against the validity period selected in the dashboard. Tokens with an iat older than that period are rejected. For example, if 10 minutes is selected, do not reuse a token generated more than 10 minutes ago.
Generate a new token on each page load or application session. Keep the server clock accurate. The documented validity rule for this integration uses iat and the dashboard period; adding exp alone does not replace this check.
Single-page applications and account switching
In single-page applications such as React, Vue, or Angular, manage SDK loading centrally; do not add the script again on each component render or route change. When a user logs out or switches accounts, do not reuse the previous user's token embedded in the page. Generate a token for the new user session in the backend and include it in the relevant page output.
The example in this guide covers initial SDK setup. If Messenger has already been initialized anonymously or for another user, verify the SDK version's session cleanup and user update behavior for login/logout, account switching, and token renewal in long-running sessions. Do not assume that refreshing the page, deleting the token variable, or calling Init again clears the previous Messenger session.
Rotating the secret
Roll out the new key to every backend instance that generates tokens and test authentication with newly generated tokens. Do not assume that tokens signed with the old key will continue to work. Coordinate key rotation with a transition that allows users to receive new tokens.
4.3. Migrating from direct user data to JWT
- Identify the channel credentials and user ID mapping in the existing installation.
- Configure the secret in the backend and add token generation to the page rendering flow.
- Move the user fields into the payload and verify that the
user_idmapping remains consistent with existing users. - Update the page template to write the backend-generated token into the Jetlink script and call
SetUser. - Coordinate enabling JWT authentication with frontend and server deployment. If it is enabled before the new token integration is ready, users who do not send a token will continue anonymously.
- Test valid tokens, invalid tokens, and anonymous usage.
- Enable JWT authentication on all Web Messenger, iOS, and Android channels.
Users are shared across channels. For full protection, enable JWT on all channels you use. The JavaScript examples in this guide are for the web; configure mobile token submission through the relevant mobile integration.
5. Messenger rules and the contact information form
Collecting contact information — ShowContactInfoRequest
You can configure which fields appear in the contact information form and which are required independently. Properties ending in IsExists control visibility, while those ending in IsRequired control whether a field is required. Assign each property a Boolean value of true or false.
| Field | Visibility setting | Required setting |
|---|---|---|
| First name | ContactInfoNameIsExists | ContactInfoNameIsRequired |
| Last name | ContactInfoSurnameIsExists | ContactInfoSurnameIsRequired |
| Email | ContactInfoEmailIsExists | ContactInfoEmailIsRequired |
| Phone | ContactInfoPhoneIsExists | ContactInfoPhoneIsRequired |
| Gender | ContactInfoGenderIsExists | ContactInfoGenderIsRequired |
| Agreement acceptance | ContactInfoAgreementIsExists | ContactInfoAgreementIsRequired |
All of these properties are used under Jetlink.Options. The agreement link is set through ContactInfoAgreementLink, and its text through ContactInfoAgreementText.
IsVisitorContactInfoRequired = true makes entering contact information mandatory. Completing the contact form is not the same as server-signed user authentication with JWT.
// Before calling Jetlink.Init: Jetlink.Options.ContactInfoNameIsExists = true; Jetlink.Options.ContactInfoNameIsRequired = true; Jetlink.Options.ContactInfoSurnameIsExists = true; Jetlink.Options.ContactInfoSurnameIsRequired = false; Jetlink.Options.ContactInfoEmailIsExists = true; Jetlink.Options.ContactInfoEmailIsRequired = true; Jetlink.Options.ContactInfoPhoneIsExists = true; Jetlink.Options.ContactInfoPhoneIsRequired = false; Jetlink.Options.ContactInfoGenderIsExists = false; Jetlink.Options.ContactInfoGenderIsRequired = false; Jetlink.Options.ContactInfoAgreementIsExists = true; Jetlink.Options.ContactInfoAgreementIsRequired = true; Jetlink.Options.ContactInfoAgreementLink = "https://example.com/information-notice"; Jetlink.Options.ContactInfoAgreementText = "I have read the information notice."; Jetlink.Options.IsVisitorContactInfoRequired = true;
The agreement text and link are examples; replace them with your organization's content. The README describes this topic under ShowContactInfoRequest but does not provide a separate call or assignment example for that name. The configuration above uses the documented form field settings.
Hiding the launcher while the chat window is open
Jetlink.Options.HideLauncherWhenChatWindowIsOpen = true;
This setting hides the Messenger launcher while the chat window is open. Configure it before calling Jetlink.Init.
6. Messenger functions
Jetlink.AddMessage — Adding an informational message to the conversation
Use this function to display an informational message in the conversation. The optional second parameter determines how long the typing indicator is displayed. A value of 3000 means 3 seconds. If omitted, no typing indicator is displayed.
Jetlink.AddMessage("Thank you for visiting our website.", 3000); // Without a typing indicator: Jetlink.AddMessage("How can we help you?");
Jetlink.OpenChatWindow — Opening the chat window
Use this function to open the chat window programmatically after Messenger has been initialized and displayed on screen.
Jetlink.OpenChatWindow();
Jetlink.CloseChatWindow — Closing the chat window
Use this function to close the chat window after it has been opened and displayed on screen.
Jetlink.CloseChatWindow();
CloseChatWindow closes the visible window; do not use it as a session cleanup or logout function.
7. Messenger events
OnChatWindowFirstOpened — First opening
Triggered when the user clicks the Messenger launcher for the first time. For example, you can display a welcome message on the first opening.
Jetlink.OnChatWindowFirstOpened = function () { Jetlink.AddMessage("Thank you for visiting our website.", 3000); };
OnChatWindowOpened — Every opening
Triggered whenever the user clicks the Messenger launcher. For example, you can track the number of openings in your application.
var launcherIconClickCount = 0; Jetlink.OnChatWindowOpened = function () { launcherIconClickCount++; };
Define event handlers after the SDK has loaded. In the combined example, handlers are assigned before Init. Test the relevant flow rather than assuming that programmatic opening also triggers these events.
8. Proactive messages
Jetlink.AddCampaignMessage displays proactive messages to a user currently viewing your website, according to your business rules. Example triggers include payment problems, registration form errors, or a user clicking a specific button.
Call it in response to the relevant application event after Messenger has been initialized. The typeof Jetlink check in the examples only verifies that the SDK object exists; it does not guarantee that initialization has fully completed.
Text-based proactive message
if (typeof Jetlink !== "undefined") { var messageObject = { Message: "There was a problem processing your payment. Try another card or message us for help." }; Jetlink.AddCampaignMessage(messageObject); }
Rich proactive message
if (typeof Jetlink !== "undefined") { var messageObject = { Message: "We can help you with registration.", MessageTitle: "Need help?", PictureUrl: "https://example.com/support.png", ButtonText: "Get support" }; Jetlink.AddCampaignMessage(messageObject); }
| Field | Description |
|---|---|
| Message | Message content. |
| MessageTitle | Message title. |
| PictureUrl | Message image URL. |
| ButtonText | Text displayed on the button. |
Add appropriate checks in your application to prevent repeated events from displaying duplicate messages. Button text alone does not define a destination URL; do not add an undocumented link field to the example.
9. Combined SDK example
The following example assumes that the JWT has been generated in the backend and inserted in place of SERVER_GENERATED_USER_JWT when rendering the HTML. For Node.js/EJS, use <%- JSON.stringify(userJwt) %>; for C#/Razor, use @Html.Raw(JsonSerializer.Serialize(Model.UserJwt)) as shown in the previous section. These template expressions replace the entire quoted placeholder.
This example combines language, appearance, a Messenger rule, an event, and user identification. Use it instead of the basic installation snippet on a logged-in page.
<script type="text/javascript"> // The backend inserts this value when rendering the page. var userJwt = "SERVER_GENERATED_USER_JWT"; var jetlinkScript = document.createElement("script"); jetlinkScript.src = "https://public.jetlink.io/Sdk/Jetlink.js?j=" + Date.now() / 1000; jetlinkScript.onload = function () { Jetlink.Options.Language = "en"; Jetlink.Options.FontFamily = "Arial"; Jetlink.Options.MessageTextBoxPlaceholder = "Type your message..."; Jetlink.Options.ShowEmojiButton = true; Jetlink.Options.ShowAttachmentButton = true; Jetlink.Options.HideLauncherWhenChatWindowIsOpen = true; Jetlink.OnChatWindowFirstOpened = function () { Jetlink.AddMessage("Hello, how can we help you?", 3000); }; Jetlink.SetUser({ Jwt: userJwt }); Jetlink.Init("YOUR_APP_ID", "YOUR_APP_KEY"); }; jetlinkScript.onerror = function () { console.error("The Jetlink SDK could not be loaded."); }; document.head.appendChild(jetlinkScript); </script>
10. Testing and troubleshooting
Start in a test environment with two different users. Seeing Messenger on the page does not by itself confirm successful authentication; also check the user information associated with the conversation in Jetlink.
| Test | Expected result / check |
|---|---|
| Valid HS256 token | The user is identified with the correct user_id, and submitted profile fields appear under the correct user. |
| No token submitted | Anonymous usage continues when JWT is enabled. |
| Token signed with the wrong key or modified after signing | The token is not accepted as a verified user identity. Inspect the exact error behavior in the application. |
Missing user_id or iat | A token missing a required field should not provide valid user authentication. |
Older than the dashboard validity period: iat | The token is rejected; repeat the test with a new token. |
| Different direct profile data sent alongside JWT | Verify that user data is taken only from the token when JWT is enabled. |
| Log out as user A and log in as user B | User A's identity and conversation content must not be visible to B. The transition is not complete until session cleanup has been verified. |
| Other channels | Verify that JWT settings and user ID mappings are consistent across web and mobile channels. |
Checking SDK functionality
- Verify that Messenger loads only once on each target page.
- Check language, colors, images, and dimensions in desktop and mobile layouts.
- Test contact form field visibility and required settings.
- Verify that first-opening and every-opening events work as expected.
- Test programmatic opening/closing and informational messages.
- Test text and rich proactive messages using real application triggers.
What should you check for each symptom?
| Symptom | Check |
|---|---|
| Messenger does not appear. | Inspect Jetlink.js loading in Network, Console errors, channel credentials, and browser/CSP restrictions. |
| The user is not recognized despite being logged in. | Check the token embedded in the page by the backend, the selected channel, the spelling of Jwt, and the SetUser → Init order. |
| The token is rejected. | Check the HS256 algorithm, the correct JWT secret, required fields, iat in seconds, and token age. |
| Profile fields are not updated. | Verify that the new token payload contains the latest information and that an old token is not being reused. |
| The page is rendered without a token value. | Check backend session authentication, token generation, and how the token is passed to the EJS/Razor template. |
| Another user's information appears. | Check for user-specific HTML in shared caches, race conditions during account switching, and Messenger session cleanup. |
For support, provide the relevant channel, date and time, browser version, integration flow, and redacted error details. Do not include the JWT secret, complete user token, or session cookies in support records.
Frequently asked questions
Can visitors who are not logged in still chat when JWT is enabled?
Yes. Visitors without a JWT can use Messenger anonymously.
Can I generate the token in the browser?
No. Signing requires the secret and must happen exclusively on your server. The browser receives only the signed token.
Can I send my existing application access token?
Do not assume that your existing token matches Jetlink's format. For this integration, generate a dedicated user token with the required fields, signed with HS256 using the secret from the dashboard.
Is the information inside a JWT confidential?
A JWT signature is not encryption. Anyone who obtains the token can read its payload. Do not include passwords, application access tokens, or unnecessary sensitive information in the payload.
Can I also pass email or name directly to SetUser when JWT is enabled?
In this mode, user data is taken only from the token. Add profile information to the server-side payload and generate a new token.
Does the validity period also end the chat at the same time?
The documented rule rejects tokens whose iat is older than the selected period. This does not imply that an open chat ends at that moment or that the SDK automatically renews the token.
Is enabling JWT only on the web channel sufficient?
Users are shared across channels, so enable JWT on all relevant channels, including Web Messenger, iOS, and Android, for full protection.
Technical reference: Jetlink JavaScript SDK. Existing SDK features are based on the supplied README; JWT settings and integration are based on the User Authentication (JWT) screen and the supplied product descriptions. C# serialization reference: JsonSerializer.Serialize.