diff --git a/README.md b/README.md index 1568d91d..5a3ff306 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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) @@ -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, @@ -63,7 +64,7 @@ const token = jwt.sign( ``` ``` -// Your app +// Your app (token from your backend) Gleap.setUserJwt(token); ``` @@ -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) diff --git a/docs/custom-widget-domains.md b/docs/custom-widget-domains.md index dae3016d..269756d8 100644 --- a/docs/custom-widget-domains.md +++ b/docs/custom-widget-domains.md @@ -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. @@ -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: @@ -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 diff --git a/index.d.ts b/index.d.ts index 60753073..24c1f354 100644 --- a/index.d.ts +++ b/index.d.ts @@ -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; @@ -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. @@ -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; /** - * 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` @@ -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: { @@ -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( diff --git a/src/Gleap.js b/src/Gleap.js index feb1767f..bb80aae2 100755 --- a/src/Gleap.js +++ b/src/Gleap.js @@ -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] @@ -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); @@ -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} @@ -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(); diff --git a/src/GleapSession.js b/src/GleapSession.js index 1919391a..0fca2664 100644 --- a/src/GleapSession.js +++ b/src/GleapSession.js @@ -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-` cookie (when cookies are on) so a reload and a + // `gleap-grant-` cookie (when cookies are on) so a reload and a // help center on the same domain stay signed. grant = null; grantRefreshTimeout = null;