Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

Add AI-native customer support, live chat, in-app bug reporting, a help center and surveys to websites and web apps using JavaScript or TypeScript with [Gleap](https://www.gleap.ai). Gleap is an Intercom alternative for software teams that connects customer conversations and feedback with product development.

[SDK documentation](https://docs.gleap.ai/documentation/javascript/README) · [Website](https://www.gleap.ai) · [Plans and pricing](https://www.gleap.ai/pricing)
[SDK documentation](https://docs.gleap.ai/en/articles/393-javascript-sdk-setup) · [Website](https://www.gleap.ai) · [Plans and pricing](https://www.gleap.ai/pricing)

## 📖 Docs & Examples

Checkout our [documentation](https://docs.gleap.ai/documentation/javascript/README) for full reference.
Checkout our documentation for full reference: [JavaScript SDK setup](https://docs.gleap.ai/en/articles/393-javascript-sdk-setup), [code snippet](https://docs.gleap.ai/en/articles/394-javascript-sdk-code-snippet) and [user identity](https://docs.gleap.ai/en/articles/395-javascript-sdk-user-identity).

## 🚀 Getting started

Expand All @@ -32,10 +32,11 @@ import Gleap from 'gleap';

### Initialize the SDK

Add the following code to initialize the Gleap JavaScript SDK. Replace "YOUR_PROJECT_ID" with your Project ID from the [Gleap dashboard](https://app.gleap.io) (Settings > Project). The Project ID was called "SDK key" or "API key" before; the value is the same and existing keys keep working.
Add the following code to initialize the Gleap JavaScript SDK. Replace "YOUR_PROJECT_ID" with your Project ID from the [Gleap dashboard](https://app.gleap.ai) (**Settings → Project → General**). The Project ID was called "SDK key" or "API key" before; the value is the same and existing keys keep working.

```
Gleap.initialize("YOUR_PROJECT_ID");
// or: Gleap.initialize({ projectId: "YOUR_PROJECT_ID" });
```

### Data region (optional)
Expand All @@ -49,12 +50,12 @@ Gleap.initialize("YOUR_PROJECT_ID");

### Identify your users

#### Signed identity (recommended)
#### Sign in with an identity token

Your backend signs an HS256 JWT with an identity key from Settings > Security > Identity keys (put the key id in the `kid` header; the secret stays on your server). `userId` is required. Optional claims: `email`, `name`, `company` (`{ id, name }`), `plan`, and provider ids such as `stripeCustomerId`. Set `exp` to at most one hour. The token is the whole identify: every claim lands on the contact as signed data that the browser cannot change. Call `Gleap.setUserJwt(token)` after login and on every page load of a logged-in user. See [Customer identity](https://docs.gleap.ai/documentation/guides/customer-identity).
Your backend signs an HS256 JWT with an identity key from Settings → Security → Customer identity → Identity keys (put the key id in the `kid` header; the secret stays on your server). `userId` is required. Optional claims: `email`, `name`, `company` (`{ id, name }`), `plan`, and provider ids such as `stripeCustomerId`. Set `exp` to at most one hour. The token is the whole identify: every claim lands on the contact as signed data that the browser cannot change. Call `Gleap.setUserJwt(token)` after login and on every page load of a logged-in user; no separate `identify` call is needed. See [Customer identity](https://docs.gleap.ai/en/articles/709-customer-identity) and [JavaScript SDK user identity](https://docs.gleap.ai/en/articles/395-javascript-sdk-user-identity).

```
// Your backend (Node, jsonwebtoken). Use an identity key from Settings > Security > Identity keys.
// Your backend (Node, jsonwebtoken). Use an identity key from Settings → Security → Customer identity → Identity keys.
const token = jwt.sign(
{ userId, email, stripeCustomerId, exp: Math.floor(Date.now() / 1000) + 60 * 60 },
SECRET,
Expand All @@ -63,7 +64,7 @@ const token = jwt.sign(
```

```
// Your app
// Your app (token from your backend)
Gleap.setUserJwt(token);
```

Expand Down Expand Up @@ -93,9 +94,9 @@ or later with `Gleap.setSessionDuration(24 * 60 * 60 * 1000)` (the same call as

`Gleap.clearIdentity()` on logout clears the contact, the token, the grant (and its cookie) and the auth tokens. The JWT provider stays set.

#### Legacy user hash
#### Older integrations

Instead of a token you can still call `Gleap.identify(userId, data, userHash)`, with `userHash` the HMAC-SHA256 of the user id created on your server with the project's identity verification secret. It is accepted while "Accept legacy user hash" is on for the project.
Older integrations that pass a user hash to `Gleap.identify(userId, data, userHash)` keep working while "Accept legacy user hash" is on for the project; see [Upgrade to identity tokens](https://docs.gleap.ai/en/articles/16752008-upgrade-to-identity-tokens) to move them to `Gleap.setUserJwt`. `Gleap.identify(userId, data)` without a hash creates an unsigned contact.

### Dark mode (optional)

Expand Down
6 changes: 3 additions & 3 deletions docs/custom-widget-domains.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Gleap.setApiUrl('https://api.support.example.com');
Gleap.setFrameUrl('https://widget.support.example.com');
Gleap.setWSApiUrl('wss://ws.support.example.com');
Gleap.setRealtimeHost('sockets.support.example.com');
Gleap.initialize('YOUR_PROJECT_SDK_KEY');
Gleap.initialize('YOUR_PROJECT_ID');
```

`setRealtimeHost` takes a hostname only; the messenger uses WSS on port 443.
Expand All @@ -32,7 +32,7 @@ no change.
import Gleap from 'gleap';

Gleap.setRegion('us'); // "eu" | "us", case-insensitive
Gleap.initialize('YOUR_PROJECT_SDK_KEY');
Gleap.initialize('YOUR_PROJECT_ID');
```

`setRegion` sets three hosts at once:
Expand All @@ -58,7 +58,7 @@ The last call wins:
```js
Gleap.setRegion('us');
Gleap.setApiUrl('https://api.support.example.com'); // only the API host is custom
Gleap.initialize('YOUR_PROJECT_SDK_KEY');
Gleap.initialize('YOUR_PROJECT_ID');
```

### Static widget hosts are global
Expand Down
32 changes: 25 additions & 7 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export namespace Gleap {
/** Options for `initialize`. */
interface InitializeOptions {
/**
* Your Project ID (Gleap dashboard: Settings > Project, or the install page).
* Your Project ID (Gleap dashboard: Settings → Project → General).
* Only needed when `initialize` is called with the options object alone.
*/
projectId?: string;
Expand All @@ -19,7 +19,8 @@ export namespace Gleap {
}
/**
* Initializes Gleap with your Project ID (formerly called "SDK key" or "API key";
* the value is the same, existing keys keep working).
* the value is the same, existing keys keep working). Find it in the Gleap dashboard
* under Settings → Project → General.
*
* `options.sessionDuration`: how long (ms) a signed session stays signed before a new
* identify is needed. The server never goes beyond the project's session max age.
Expand Down Expand Up @@ -201,20 +202,28 @@ export namespace Gleap {
}[]): void;
function showTabNotificationBadge(showNotificationBadge: boolean): void;
function attachNetworkLogs(networkLogs: string): void;
/** Clears the current contact, its identity token and auth tokens. The JWT provider stays set. */
/**
* Call on logout. Clears the current contact, its identity token, the grant and auth tokens.
* The JWT provider stays set.
*/
function clearIdentity(): void;
/**
* Identifies the user with an identity token: an HS256 JWT signed by your backend.
* Identifies the user with an identity token: an HS256 JWT signed by your backend with an
* identity key (Settings → Security → Customer identity → Identity keys).
* The `userId` (or `user_id`) claim names the user; every other claim lands on the
* contact as signed data. Nothing else is sent. Kept in memory only.
* Call it after login and on every page load of a logged-in user; no separate
* `identify` call is needed.
* A token that is not a JWT, has no userId or is over 4096 characters is refused
* with a console warning and no request.
* Never rejects; refusals are logged.
* @see https://docs.gleap.ai/en/articles/709-customer-identity
*/
function setUserJwt(token: string): Promise<void>;
/**
* Returns a fresh identity token. Called when the current token expired, or before
* a renewal when it expires within 5 minutes. Also restores the signed session after
* Optional: sets a function that returns a fresh identity token from your backend.
* Called when the current token expired, or before a renewal when it expires within
* 5 minutes. Also restores the signed session after
* a page reload: when the server reports Signed mode for an identified session without
* a valid grant (no grant cookie) and no token was passed to `setUserJwt`, it is asked
* once per page load and the user is identified with its token. Returning `null`
Expand Down Expand Up @@ -245,6 +254,11 @@ export namespace Gleap {
function setDisablePageTracking(
disablePageTracking: boolean
): void;
/**
* Identifies the user by user id and contact data. Without a signature this is an
* unsigned contact; to sign the user in, use `setUserJwt`.
* @see https://docs.gleap.ai/en/articles/395-javascript-sdk-user-identity
*/
function identify(
userId: string,
customerData: {
Expand All @@ -263,7 +277,11 @@ export namespace Gleap {
avatar?: string | null;
createdAt?: Date | null;
},
/** The HMAC-SHA256 of the user id (legacy), or an identity token (see `setUserJwt`). */
/**
* Older integrations pass the HMAC-SHA256 user hash here; it keeps working. An identity
* token is accepted too, but `setUserJwt` is the way to sign in.
* @see https://docs.gleap.ai/en/articles/16752008-upgrade-to-identity-tokens
*/
userHash?: string
): void;
function updateContact(
Expand Down
15 changes: 11 additions & 4 deletions src/Gleap.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,9 @@ class Gleap {
}

/**
* Initializes the SDK with your Project ID (formerly called "SDK key"; the value is
* the same, existing keys keep working).
* Initializes the SDK with your Project ID (formerly called "SDK key" or "API key"; the
* value is the same, existing keys keep working). Find it in the Gleap dashboard under
* Settings → Project → General.
* @param {string | { projectId: string, sessionDuration?: number }} projectId
* The Project ID, or an options object that carries it as `projectId`.
* @param {boolean | { projectId?: string, disablePing?: boolean, sessionDuration?: number }} [options]
Expand Down Expand Up @@ -485,9 +486,12 @@ class Gleap {
}

/**
* Indentifies the user session
* Identifies the user by user id and contact data. Without a signature this is an
* unsigned contact; to sign the user in, use setUserJwt.
* @param {string} userId
* @param {*} userData
* @param {string} [userHash] Older integrations pass the HMAC-SHA256 user hash here; it
* keeps working (see https://docs.gleap.ai/en/articles/16752008-upgrade-to-identity-tokens).
*/
static identify(userId, userData, userHash) {
return GleapSession.getInstance().identifySession(userId, flattenCompany(gleapDataParser(userData)), userHash);
Expand All @@ -497,6 +501,8 @@ class Gleap {
* Identifies the user with an identity token (HS256 JWT signed by your backend).
* The token is the whole identify: its `userId` (or `user_id`) claim names the user,
* every other claim lands on the contact as signed data. Kept in memory only.
* Call it after login and on every page load of a logged-in user; no separate identify
* call is needed. See https://docs.gleap.ai/en/articles/709-customer-identity
* Never rejects; refusals are logged.
* @param {string} token
* @returns {Promise<void>}
Expand Down Expand Up @@ -545,7 +551,8 @@ class Gleap {
}

/**
* Clears the current contact, its identity token and auth tokens. The JWT provider stays set.
* Call on logout. Clears the current contact, its identity token, the grant and auth
* tokens. The JWT provider stays set.
*/
static clearIdentity() {
GleapSession.getInstance().clearSession();
Expand Down
2 changes: 1 addition & 1 deletion src/GleapSession.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export default class GleapSession {
// (`identity.grant`). Sent as `Gleap-Grant` on every request and handed to
// the messenger next to (never inside) the session. Kept out of `session`,
// which is persisted to localStorage; stored only in the
// `gleap-grant-<apiKey>` cookie (when cookies are on) so a reload and a
// `gleap-grant-<projectId>` cookie (when cookies are on) so a reload and a
// help center on the same domain stay signed.
grant = null;
grantRefreshTimeout = null;
Expand Down
Loading