Skip to content

Commit 571ef73

Browse files
authored
Merge pull request #146 from GleapSDK/v18-regions
feat: v18.0.0 data regions via Gleap.setRegion
2 parents 274b646 + e7531fa commit 571ef73

14 files changed

Lines changed: 460 additions & 13 deletions

‎CHANGELOG.md‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Changelog
2+
3+
## 18.0.0
4+
No breaking changes: major version aligned across all Gleap SDKs for the data-region release. Without `Gleap.setRegion` the SDK behaves exactly as 17.x (EU hosts).
5+
6+
Added data regions: `Gleap.setRegion("eu" | "us")` (case-insensitive, call before `Gleap.initialize`) sets the API url, the SDK streaming (WS) url and the messenger realtime host for the region at once; `Gleap.getRegion()` returns the active region. The default region stays `eu`. An unknown region logs a console warning and changes nothing.
7+
(eu: `https://api.gleap.io`, `wss://ws.gleap.io`, `sockets.gleap.io`; us: `https://api.us.gleap.ai`, `wss://ws.us.gleap.ai`, `sockets.us.gleap.ai`)
8+
Manual host setters are unchanged and keep working: `setApiUrl`, `setWSApiUrl`, `setRealtimeHost`, `setFrameUrl`, `setBannerUrl`, `setModalUrl`. The last call wins: a manual setter called after `setRegion` overrides that single host, `setRegion` called after manual setters overrides the three region hosts.
9+
The static widget hosts stay global for every region (`messenger-app.gleap.io`, `outboundmedia.gleap.io`, `sdk.gleap.io`, `js.gleap.io`); `setRegion` never changes the frame, banner or modal url.
10+
Added `Gleap.setAgentConversationUrl` to override the `<gleap-agent-conversation>` iframe url (same as `setBannerUrl` / `setModalUrl`).
11+
Added `gleap.ai` to the default network-log blacklist, so the SDK does not record its own US traffic.
12+
Added the `GleapRegion` type to the TypeScript definitions.
13+
Fixed the consentmanager allowlist (`window.cmp_block_ignoredomains`): `messenger-app.gleap.io` was never actually added because the result of `concat` was discarded.

‎README.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ Add the following code to initialize the Gleap JavaScript SDK. Replace "SDK-TOKE
3434
Gleap.initialize("SDK-TOKEN");
3535
```
3636

37+
### Data region (optional)
38+
39+
Projects hosted in the US data region select it before initializing. The default region is `eu`. See [docs/custom-widget-domains.md](docs/custom-widget-domains.md) for the host table and custom domains.
40+
41+
```
42+
Gleap.setRegion("us");
43+
Gleap.initialize("SDK-TOKEN");
44+
```
45+
3746
Congrats, you are now all set! Report your first bug by using the feedback button.
3847

3948
## 🤝 Need help?

‎docs/custom-widget-domains.md‎

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,62 @@ Deploy the updated Messenger-App before releasing the updated SDK. An older
2222
messenger ignores `realtimeHost` and continues using its default realtime domain.
2323
The agent dashboard requires no changes.
2424

25+
## Data regions
26+
27+
Gleap projects live in a data region. Select it with `Gleap.setRegion` before
28+
`Gleap.initialize()`. The default region is `eu`, so existing integrations need
29+
no change.
30+
31+
```js
32+
import Gleap from 'gleap';
33+
34+
Gleap.setRegion('us'); // "eu" | "us", case-insensitive
35+
Gleap.initialize('YOUR_PROJECT_SDK_KEY');
36+
```
37+
38+
`setRegion` sets three hosts at once:
39+
40+
| Region | API (`setApiUrl`) | SDK streaming (`setWSApiUrl`) | Messenger realtime (`setRealtimeHost`) |
41+
|--------|-------------------|-------------------------------|----------------------------------------|
42+
| `eu` (default) | `https://api.gleap.io` | `wss://ws.gleap.io` | `sockets.gleap.io` |
43+
| `us` | `https://api.us.gleap.ai` | `wss://ws.us.gleap.ai` | `sockets.us.gleap.ai` |
44+
45+
An unknown region logs a console warning and changes nothing.
46+
`Gleap.getRegion()` returns the active region. Without a `setRegion` call the
47+
realtime host is not sent to the messenger, which then uses its own default
48+
(`sockets.gleap.io`), exactly as before.
49+
50+
### Order rule
51+
52+
The last call wins:
53+
54+
- A manual setter (`setApiUrl`, `setWSApiUrl`, `setRealtimeHost`) called AFTER
55+
`setRegion` overrides that single host; the other two keep the region's value.
56+
- `setRegion` called after manual setters overrides all three region hosts.
57+
58+
```js
59+
Gleap.setRegion('us');
60+
Gleap.setApiUrl('https://api.support.example.com'); // only the API host is custom
61+
Gleap.initialize('YOUR_PROJECT_SDK_KEY');
62+
```
63+
64+
### Static widget hosts are global
65+
66+
The static widget hosts are the same for every region: `messenger-app.gleap.io`
67+
(widget frame), `outboundmedia.gleap.io` (banners, modals, agent conversation),
68+
`sdk.gleap.io` and `js.gleap.io` (SDK script and assets). `setRegion` never
69+
changes `setFrameUrl`, `setBannerUrl`, `setModalUrl` or
70+
`setAgentConversationUrl`; those setters keep working independently.
71+
72+
If you use a Content-Security-Policy or a network allowlist, US projects must
73+
additionally allow `https://api.us.gleap.ai`, `wss://ws.us.gleap.ai` and
74+
`wss://sockets.us.gleap.ai` (`connect-src`) next to the global `*.gleap.io`
75+
widget hosts.
76+
77+
The region table lives in one place in the SDK: `src/GleapRegions.js`.
78+
79+
> The EU region is also reachable on `api.eu.gleap.ai`, `ws.eu.gleap.ai` and `sockets.eu.gleap.ai`. The JavaScript SDK keeps the `*.gleap.io` hosts as its EU default for now, because sites with a Content-Security-Policy allow-list `*.gleap.io`; add `*.gleap.ai` to your CSP today so a later SDK release can switch the default without any change on your side. To use the new hosts already, set them with `setApiUrl`, `setWSApiUrl` and `setRealtimeHost`.
80+
2581
## Hosting requirements
2682

2783
Provision DNS, valid TLS certificates and reverse proxy routing for each custom
@@ -36,7 +92,9 @@ Bundle the SDK with the customer's app or proxy its script delivery separately.
3692
Test with Gleap domains blocked, including files/uploads, avatars, help content,
3793
banners/modals and any enabled voice integrations. Proxy/configure remaining
3894
required resources before promising that no Gleap domains need allowlisting.
39-
Banner and modal frame URLs already have `setBannerUrl` and `setModalUrl` setters.
95+
Banner and modal frame URLs already have `setBannerUrl` and `setModalUrl` setters;
96+
the `<gleap-agent-conversation>` frame has `setAgentConversationUrl` (call it
97+
before the element is attached to the DOM).
4098

4199
References:
42100
- https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/worker-as-origin/

‎index.d.ts‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
/** Gleap data region. */
2+
export type GleapRegion = "eu" | "us";
3+
14
export namespace Gleap {
25
function initialize(sdkKey: string, disablePing?: boolean): void;
36
function sendSilentCrashReport(
@@ -54,6 +57,23 @@ export namespace Gleap {
5457
options?: { context?: any; initialQuestion?: string; initialMessage?: string }
5558
): void;
5659
function isOpened(): boolean;
60+
/**
61+
* Sets the data region your Gleap project lives in. Call before initialize.
62+
* Defaults to "eu". The value is case-insensitive; an unknown value logs a
63+
* console warning and changes nothing.
64+
*
65+
* Sets three hosts at once:
66+
* - eu: apiUrl `https://api.gleap.io`, wsApiUrl `wss://ws.gleap.io`, realtimeHost `sockets.gleap.io`
67+
* - us: apiUrl `https://api.us.gleap.ai`, wsApiUrl `wss://ws.us.gleap.ai`, realtimeHost `sockets.us.gleap.ai`
68+
*
69+
* Order rule (last call wins): setApiUrl / setWSApiUrl / setRealtimeHost
70+
* called AFTER setRegion override that single host; setRegion called after
71+
* them overrides all three region hosts. The static widget hosts
72+
* (setFrameUrl, setBannerUrl, setModalUrl) are global and never changed by setRegion.
73+
*/
74+
function setRegion(region: GleapRegion): void;
75+
/** Returns the current data region ("eu" unless setRegion was called). */
76+
function getRegion(): GleapRegion;
5777
function setApiUrl(apiUrl: string): void;
5878
function setWSApiUrl(wsApiUrl: string): void;
5979
/** Messenger realtime hostname, without protocol or path. Set before initialize. */
@@ -63,6 +83,11 @@ export namespace Gleap {
6383
function closeModal(): void;
6484
function setBannerUrl(bannerUrl: string): void;
6585
function setModalUrl(modalUrl: string): void;
86+
/**
87+
* Custom url for the `<gleap-agent-conversation>` iframe. Applies to elements
88+
* attached to the DOM after this call.
89+
*/
90+
function setAgentConversationUrl(agentConversationUrl: string): void;
6691
function setMaxNetworkRequests(maxRequests: number): void;
6792
function startNetworkLogger(): void;
6893
function setNetworkLogsBlacklist(networkLogBlacklist: string[]): void;

‎package-lock.json‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "gleap",
3-
"version": "17.0.3",
3+
"version": "18.0.0",
44
"main": "build/cjs/index.js",
55
"module": "build/esm/index.mjs",
66
"exports": {

‎src/Gleap.js‎

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import AgentNetworkManager from './AgentNetworkManager';
22
import ChecklistNetworkManager from './ChecklistNetworkManager';
33
import GleapAdminManager from './GleapAdminManager';
44
import GleapAgentChat from './GleapAgentChat';
5-
import { registerGleapAgentComponents } from './GleapAgentConversation';
5+
import { registerGleapAgentComponents, setGleapAgentConversationUrl } from './GleapAgentConversation';
66
import GleapAgentToolManager from './GleapAgentToolManager';
77
import GleapAiChatbarManager from './GleapAiChatbarManager';
88
import GleapAudioManager from './GleapAudioManager';
@@ -619,6 +619,29 @@ class Gleap {
619619
GleapMetaDataManager.setAppBuildNumber(appBuildNumber);
620620
}
621621

622+
/**
623+
* Sets the data region. Call before initialize.
624+
* Applies the region's apiUrl, wsApiUrl and realtimeHost at once. The static
625+
* widget hosts (frameUrl, bannerUrl, modalUrl) are global and stay untouched.
626+
*
627+
* Order rule: the last call wins. A manual setter (setApiUrl, setWSApiUrl,
628+
* setRealtimeHost) called AFTER setRegion overrides that single host;
629+
* setRegion called after manual setters overrides all three region hosts.
630+
* Unknown regions log a warning and change nothing.
631+
* @param {"eu"|"us"} region The data region (case-insensitive). Defaults to "eu".
632+
*/
633+
static setRegion(region) {
634+
GleapSession.getInstance().setRegion(region);
635+
}
636+
637+
/**
638+
* Returns the current data region.
639+
* @returns {"eu"|"us"}
640+
*/
641+
static getRegion() {
642+
return GleapSession.getInstance().getRegion();
643+
}
644+
622645
/**
623646
* Set a custom ws api url.
624647
* @param {string} wsApiUrl
@@ -660,6 +683,15 @@ class Gleap {
660683
GleapModalManager.getInstance().setModalUrl(modalUrl);
661684
}
662685

686+
/**
687+
* Set a custom agent conversation url (<gleap-agent-conversation>).
688+
* Applies to elements attached to the DOM after this call.
689+
* @param {string} agentConversationUrl
690+
*/
691+
static setAgentConversationUrl(agentConversationUrl) {
692+
setGleapAgentConversationUrl(agentConversationUrl);
693+
}
694+
663695
/**
664696
* Set a custom frame api url.
665697
* @param {string} frameUrl

‎src/GleapAgentConversation.js‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
11
import { GleapSession } from './Gleap';
22
import { bootstrapGleapFrame } from './GleapHelper';
3+
import { GLEAP_DEFAULT_REGION, GLEAP_REGIONS } from './GleapRegions';
4+
5+
let agentConversationUrl = 'https://outboundmedia.gleap.io/agent-conversation';
6+
7+
/**
8+
* Set a custom agent conversation url. Applies to <gleap-agent-conversation>
9+
* elements attached to the DOM after this call.
10+
* @param {string} url
11+
*/
12+
export const setGleapAgentConversationUrl = (url) => {
13+
agentConversationUrl = url;
14+
};
315

416
export const registerGleapAgentComponents = () => {
517
if (typeof customElements === 'undefined' || typeof HTMLElement === 'undefined' || typeof window === 'undefined') return;
618

719
if (!customElements.get('gleap-agent-conversation')) {
820
class GleapAgentConversation extends HTMLElement {
921
_iframe = null;
10-
_agentConvUrl = 'https://outboundmedia.gleap.io/agent-conversation';
22+
_agentConvUrl = agentConversationUrl;
1123
_messageListener = null;
1224
_config = {};
1325

@@ -35,6 +47,7 @@ export const registerGleapAgentComponents = () => {
3547

3648
_injectIframe() {
3749
if (this._iframe) return;
50+
this._agentConvUrl = agentConversationUrl;
3851
this.style.display = 'block';
3952
this.style.width = '100%';
4053
this.style.height = '100%';
@@ -97,7 +110,7 @@ export const registerGleapAgentComponents = () => {
97110
_sendConfig() {
98111
if (!this._iframe?.contentWindow) return;
99112

100-
let apiUrl = 'https://api.gleap.io';
113+
let apiUrl = GLEAP_REGIONS[GLEAP_DEFAULT_REGION].apiUrl;
101114
let sdkKey = '';
102115
let gleapId = '';
103116
let gleapHash = '';

‎src/GleapAiChatbarManager.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
} from './Gleap';
99
import GleapAgentToolManager from './GleapAgentToolManager';
1010
import { applyGleapCSPNonce, bootstrapGleapFrame, runFunctionWhenDomIsReady } from './GleapHelper';
11+
import { GLEAP_DEFAULT_REGION, GLEAP_REGIONS } from './GleapRegions';
1112

1213
export default class GleapAiChatbarManager {
1314
get chatbarUrl() {
@@ -377,7 +378,7 @@ export default class GleapAiChatbarManager {
377378
async _validateAgent(agentId) {
378379
try {
379380
const session = GleapSession.getInstance();
380-
const apiUrl = session.apiUrl || 'https://api.gleap.io';
381+
const apiUrl = session.apiUrl || GLEAP_REGIONS[GLEAP_DEFAULT_REGION].apiUrl;
381382

382383
const headers = {};
383384
if (session.sdkKey) headers['Api-Token'] = session.sdkKey;

‎src/GleapFrameManager.js‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,11 @@ export default class GleapFrameManager {
139139
}
140140

141141
autoWhiteListCookieManager = () => {
142-
if (window && window.cmp_block_ignoredomains) {
143-
window.cmp_block_ignoredomains.concat(['messenger-app.gleap.io']);
142+
// Push in place: concat returns a new array and would leave the allowlist untouched.
143+
if (window && Array.isArray(window.cmp_block_ignoredomains)) {
144+
if (window.cmp_block_ignoredomains.indexOf('messenger-app.gleap.io') === -1) {
145+
window.cmp_block_ignoredomains.push('messenger-app.gleap.io');
146+
}
144147
}
145148
};
146149

0 commit comments

Comments
 (0)