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.

HTML
<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

NameTypeDescription
data-widget-keyrequiredwk_…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-urlrequiredhttps://…Core API address (http or https). Use the value from the install snippet.
data-realtime-urlrequiredwss://…Realtime (WebSocket) endpoint (ws or wss). Use the value from the install snippet.
data-localetr | enInterface 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-themelight | dark | systemColour theme. When omitted the website setting is used, otherwise system (the visitor’s OS preference).
data-positionright | leftCorner 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:

JavaScript
// 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
MethodDescription
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.

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:

HTML
<!-- 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.com for example.com).
  • http is also accepted for localhost and 127.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):

HTTP
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';