Integrate
Chat widget
The widget is added with a single script tag and runs inside a closed Shadow DOM, so your page styles cannot affect it.
#Installation
Copy the install snippet from Websites & widget in the admin console and add it before the </body> tag on every page. It loads async, so it never blocks your page.
<script src="https://cdn.2people.chat/widget.js" async
data-widget-key="wk_0123456789abcdef0123456789abcdef0123"
data-api-url="https://api.2people.chat"
data-realtime-url="wss://rt.2people.chat/ws"
data-locale="en"></script>#Attributes
| Name | Type | Description |
|---|---|---|
data-widget-keyrequired | wk_… | The website’s widget key: wk_ followed by 36 lower-case hex characters. It is in the install snippet in the admin console. |
data-api-urlrequired | https://… | Core API address (http or https). Use the value from the install snippet. |
data-realtime-urlrequired | wss://… | Realtime (WebSocket) endpoint (ws or wss). Use the value from the install snippet. |
data-locale | tr | en | Interface language. When omitted the browser language is used (tr for Turkish, otherwise en). If neither tr nor en is given or detected, the website’s default language applies. |
data-theme | light | dark | system | Colour theme. When omitted the website setting is used, otherwise system (the visitor’s OS preference). |
data-position | right | left | Corner of the chat bubble. When omitted the website setting is used, otherwise right. |
Values set explicitly on the page (data-locale, data-theme, data-position) always win over the website settings.
#JavaScript API
Once the widget has loaded, window.TwoPeople is defined. Use it, for example, to open the chat from your own button:
// window.TwoPeople is available once the widget has loaded.
window.TwoPeople.open(); // open the chat window
window.TwoPeople.close(); // close it
window.TwoPeople.toggle(); // open or close
window.TwoPeople.setTheme('dark'); // 'light' | 'dark' | 'system'
window.TwoPeople.destroy(); // remove the widget from the page| Method | Description |
|---|---|
open() · close() · toggle() | Opens, closes or toggles the chat window. |
setTheme(theme) | Changes the theme; this wins over the website setting. |
identify(token) | Links the visitor to the logged-in player; returns Promise<boolean>. See Player identity. |
setConsent(granted) | Reports analytics consent (see below). |
destroy() | Removes the widget from the page. |
#Appearance and texts
The website’s Widget appearance page in the admin console has these settings, with a live preview:
- Primary colour for the header, bubble, buttons and the visitor’s messages. The console checks readability against WCAG contrast, and the widget picks the text colour (white or dark) automatically.
- Position (bottom right / bottom left), theme and default language (TR/EN).
- Texts per language: header title, greeting, outside-hours notice and satisfaction question. Empty texts fall back to the widget’s built-in ones.
- Satisfaction (CSAT): when a conversation is closed the visitor is asked for a 1–5 score and an optional comment. The rating can be changed for 24 hours.
Visitors can attach PNG, JPEG, GIF, WebP or PDF files (up to 10 MB) to the chat.
#Business hours
Business hours are set in the admin console under Team & access → Departments & hours: a time zone and a weekly schedule (or 24/7) for the tenant, and optionally a separate schedule per department.
When no team is within its hours, the widget shows the outside-hours notice from the appearance settings (the notice can be switched off). Visitors can still write.
#Proactive triggers
On the Proactive triggers page you can make the widget show a message on its own under certain conditions: URL contains, time on page, number of page views, referrer, UTM source, new or returning visitor, and device. Each trigger has a priority (0–1000) and a TR/EN message. Triggers rely on visitor analytics, so they only run when analytics is allowed.
#Consent and privacy
Separately from chat, the widget can collect visitor analytics such as page views and widget usage. If require consent is on in the policy on the Privacy & telemetry page, analytics starts only after consent is given. If honour Global Privacy Control is on, nothing is collected from browsers that send the GPC signal. Chat itself is not affected by consent.
Pass consent from your consent manager in one of two ways:
<!-- Option A: after your consent banner accepts analytics -->
<script>
window.TwoPeople.setConsent(true);
</script>
<!-- Option B: consent already known when the page loads (before the widget script) -->
<script>
window.TwoPeopleConsent = true;
</script>
<script src="…/widget.js" async data-widget-key="…"></script>If consent is withdrawn, call window.TwoPeople.setConsent(false); queued events are dropped and collection stops.
#Allowed origins
The widget can only start a session on origins registered for the website:
- The registered domain and all its subdomains, over https (e.g.
https://www.example.comforexample.com). - http is also accepted for
localhostand127.0.0.1. - Exact origins listed in Extra origins (scheme, host and port must match).
A visitor session is bound to the origin it was created on; requests from any other origin are rejected.
#Content Security Policy
If your site uses a CSP, allow what the widget does: it loads its script file, sends HTTP requests to the Core API, opens a WebSocket to the realtime endpoint, shows image attachments from blob: URLs and adds its styles to its Shadow DOM as a <style> element. Example (merge with your own policy):
Content-Security-Policy:
script-src 'self' https://cdn.2people.chat;
connect-src 'self' https://api.2people.chat wss://rt.2people.chat;
img-src 'self' blob:;
style-src 'self' 'unsafe-inline';