← Ana sayfa← Home

Site entegrasyonuSite integration

Setup is a single <script> tag. Signed identity for logged-in users and VIP customers is optional.

Bu belgeler şu an yalnızca İngilizce. Türkçe yardım için support@embrchat.com adresine yazabilirsiniz.

01How it works

The EmbrChat widget is added to your site with a single <script> tag. The tag only draws a small launcher button on your page; it lives inside a Shadow DOM, so it never clashes with your CSS.

  • The chat window runs in an isolated iframe on widget.embrchat.com. Your page and the iframe talk only through origin-verified postMessage calls.
  • Visitors start as anonymous guests. You can verify your logged-in users with a signed identity or a site token.
  • Conversations are first answered by the assistant using approved content, and handed off to an agent when needed or when the visitor asks.
Your site→Launcher (Shadow DOM)→Chat iframe→Assistant→Agent

02Quick start

Get your site key from the Setup page in the panel and place the code below on every page, right before the closing </body> tag.

HTML
<script type="module" src="https://widget.embrchat.com/v1/widget.js"
  data-widget-key="wk_YOUR_SITE_KEY"
  data-channel="web"
  async></script>

Allowed origins

The widget only opens on sites listed under Allowed origins in the panel. The list can have up to 10 lines and only https is accepted.

FormatExampleDescription
Exact matchhttps://www.yoursite.comThis origin only
Single-level wildcardhttps://*.yoursite.comshop.yoursite.com, app.yoursite.com …
Numeric rangehttps://store{1-50}.comUp to 5,000 domains; you must own all of them

Pages where the widget is hidden

To hide the widget on specific pages such as checkout, add paths under Excluded pages in the panel:

Example
/checkout
/account/payment
/campaign/*

03Tag attributes

AttributeDefaultDescription
data-widget-key required—Your site key from the panel (wk_…)
data-channelwebChannel the conversation is routed to (see Channels)
data-lazyfalseIf true, the widget loads only when the button is clicked; online-visitor tracking is disabled
data-send-titletrueShows the page title to agents; disable with false
data-launcherdefaultnone hides the launcher; open the chat from your own button
data-localeautoFixed language such as en-GB, de-DE, tr-TR
data-positionrightLauncher position: right / left
If the same option is set both as an attribute and in EmbrChatSettings, the Settings value wins.

04Settings: window.EmbrChatSettings

For advanced configuration, define a settings object before the script tag:

HTML
<script>
  window.EmbrChatSettings = {
    channel: "web",
    visitor: { name: "Jane Doe", email: "jane@example.com", memberId: "U-1042" },
    identity: { payload: "...", signature: "..." },   // signed identity (section 6)
    siteToken: null,                                  // or a JWT (section 7)
    onSessionExpired: async () => { /* fetch a fresh identity */ },
    lazy: false,
    sendPageTitle: true,
    launcher: "default",
    locale: "en-GB"
  };
</script>
<script type="module" src="https://widget.embrchat.com/v1/widget.js" data-widget-key="wk_..." async></script>
FieldTypeDescription
visitorobjectUnverified name, email and member ID. Shown to agents with an unverified label
identityobjectpayload + signature — verified identity
siteTokenstringYour site's own JWT — secret-less verification
onSessionExpiredfunctionCalled when the signature or token expires
channel, lazy, sendPageTitle, launcher, locale—Same as the tag attributes

05Visitor types

TypeHow it's identifiedWhat agents seeHistory
GuestNo identity providedRandom visitor name, page, device typeOpen conversation on the same device
Member (verified)Signed identity or site tokenVerified name, email, member ID, attributesLast 180 days
VIPsegment: "vip" in the signed identityMember details + VIP badge; routed to the VIP queueLast 180 days
Only signed data counts as verified. Information sent via visitor is always marked as unverified.

06Signed identity (HMAC)

To verify your logged-in users, sign their identity on your server and print it on the page. You'll find the signing secret under Setup → Identity verification in the panel.

Payload fields

FieldRequiredDescription
userIdYesUnique user ID in your system
issuedAtYesUnix timestamp (seconds). Signatures older than 10 minutes are rejected
name, emailNoDetails shown to agents
segmentNomember or vip
attributesNoUp to 10 key–value pairs (e.g. plan, city)

Signature: hex(HMAC_SHA256(secret, payload)) — computed over the exact same payload string you send to the page.

Node.js
import { createHmac } from "node:crypto";

export function chatIdentity(user) {
  const payload = JSON.stringify({
    userId: String(user.id),
    name: user.name,
    email: user.email,
    segment: user.isVip ? "vip" : "member",
    attributes: { plan: user.plan },
    issuedAt: Math.floor(Date.now() / 1000)
  });
  const signature = createHmac("sha256", process.env.CHAT_SECRET)
    .update(payload).digest("hex");
  return { payload, signature };
}
PHP
<?php
$payload = json_encode([
  'userId'   => (string) $user->id,
  'name'     => $user->name,
  'email'    => $user->email,
  'segment'  => $user->is_vip ? 'vip' : 'member',
  'issuedAt' => time(),
], JSON_UNESCAPED_UNICODE);
$signature = hash_hmac('sha256', $payload, getenv('CHAT_SECRET'));
Python
import hmac, hashlib, json, os, time

payload = json.dumps({
    "userId": str(user.id),
    "name": user.name,
    "email": user.email,
    "segment": "vip" if user.is_vip else "member",
    "issuedAt": int(time.time()),
}, ensure_ascii=False, separators=(",", ":"))
signature = hmac.new(os.environ["CHAT_SECRET"].encode(), payload.encode(), hashlib.sha256).hexdigest()

Using it on the page

HTML
<script>
  window.EmbrChatSettings = {
    identity: <?= json_encode(['payload' => $payload, 'signature' => $signature]) ?>,
    onSessionExpired: async () => {
      const r = await fetch("/api/chat-identity", { credentials: "include" });
      if (r.ok) window.EmbrChat.setIdentity(await r.json());
    }
  };
</script>
Never send the secret to the browser or embed it in your source code. If you think it has leaked, rotate it in the panel immediately; signatures made with the old secret stop working at once.

07Site session token (JWT, secret-less)

If your site already uses JWT-based sessions, you can pass that token instead of sharing a separate secret. EmbrChat verifies it with the method you configure in the panel:

  • JWKS URL or PEM public key (RS256 / ES256)
  • HS256 shared key
  • Verification endpoint: the token is sent to your server with an Authorization: Bearer … header and is accepted if it returns 200
JavaScript
window.EmbrChatSettings = { siteToken: getAccessToken() };

// When the token is refreshed:
window.EmbrChat.setSiteToken(newJwt);

// On logout:
window.EmbrChat.reset();

Rules

  • exp is required; when the token expires, onSessionExpired is called.
  • An algorithm allowlist is enforced; none is always rejected.
  • iss and aud are checked if configured in the panel.
  • Name and email are not taken from the token; only sub is used as the user ID.

08Login and logout

Login without a page reload: when the user logs in, fetch a fresh signature from your server and pass it to the widget. Any open guest conversation is linked to the member account.

JavaScript
const identity = await fetch("/api/chat-identity").then(r => r.json());
window.EmbrChat.setIdentity(identity);

Logout: reload the page, or remove and reload the widget. The widget doesn't keep session data in cookies or localStorage, so the previous user's conversations are not visible after logout.

JavaScript
window.EmbrChat.destroy();
// then re-add the script tag or reload the page

09Server-to-server session (optional)

When the signature can't be printed on the page (for example in an in-app web view), you can open a session directly from your server.

HTTP
POST https://api.embrchat.com/v1/widget/sessions/exchange
content-type: application/json
x-operator-timestamp: 1767225600
x-operator-signature: hex(HMAC_SHA256(secret, "1767225600." + body))

{
  "widgetKey": "wk_YOUR_SITE_KEY",
  "subjectRef": "U-1042",
  "authLevel": "member",
  "issuedAt": 1767225600,
  "profile": { "name": "Jane Doe", "email": "jane@example.com", "segment": "member" }
}
Response
{ "token": "ses_9f2c…", "expiresIn": 3600 }

Pass the returned token on the page with window.EmbrChat.setSession(token). The timestamp must be within ±5 minutes of server time.

10JavaScript API: window.EmbrChat

MethodDescription
open() / close() / toggle()Opens, closes or toggles the chat window
setIdentity({ payload, signature })Provides a signed identity after login
setSiteToken(jwt, origin?)Provides or refreshes the site token
setVisitor({ name?, email? })Updates unverified guest details
setSession(token)Provides the server-to-server session token
pageView()Reports a page change in an SPA
setLocale('en-GB')Changes the widget language
on(event, fn) / off(event, fn)Adds or removes an event listener
reset()Clears the identity and restarts as a guest
destroy()Removes the widget from the page entirely

To open the chat from your own button:

HTML
<a href="#" onclick="window.EmbrChat?.open(); return false;">Live support</a>
The widget loads asynchronously, so use ?. before calling the API or wait for the ready event.

11Events

EventWhenData
readyThe widget has loaded and the API is ready—
open / closeThe window was opened / closed—
conversation:startA new conversation started{ conversationId }
conversation:handoffThe assistant handed the conversation to an agent{ conversationId, queue }
message:receivedThe visitor received a new message{ from: 'bot'|'agent' }
conversation:endThe conversation was closed{ conversationId, rating? }
JavaScript
window.addEventListener("EmbrChat:ready", () => {
  window.EmbrChat.on("conversation:handoff", (e) => {
    analytics.track("chat_handoff", { queue: e.queue });
  });
});
Event data never contains message content — only the metadata needed for analytics.

12Language

The default language is English. The widget language is chosen in this order:

  1. The data-locale attribute or locale setting
  2. The language the visitor previously picked in the widget
  3. The page's <html lang> value
  4. The site default in the panel

Visitors can switch language from inside the window. Texts you enter in the panel, such as the greeting and form labels, are defined per language under Widget appearance → Text language. When your site changes language:

JavaScript
window.EmbrChat?.setLocale("de-DE");

13Single-page apps (React, Vue, Next.js)

Add the tag once to your app shell (index.html, _document, app.html). Hash changes and back/forward navigation are detected automatically. After navigations done with history.pushState, report the page change:

Next.js
// Next.js (App Router)
"use client";
import { usePathname } from "next/navigation";
import { useEffect } from "react";

export function ChatPageView() {
  const pathname = usePathname();
  useEffect(() => { window.EmbrChat?.pageView(); }, [pathname]);
  return null;
}
Vue
// Vue Router
router.afterEach(() => window.EmbrChat?.pageView());

14Channels

Channels decide which team and queue a conversation goes to. They are created in the panel under Advanced configuration → Channels; adding a channel or changing its audience requires approval from two admins.

AudienceWho gets in
everyoneEveryone, including guests
membersVerified members only
vipVerified members with segment: "vip" only
  • A channel can require a pre-chat form (name, email, topic) for guests. Verified members and visitors with a memberId skip the form.
  • Requests about account security, payments and personal data always go to the specialist queue, regardless of channel settings; the assistant never answers them.

15Online visitors and proactive messages

While the page is visible, the widget sends a heartbeat every 30 seconds. Agents see who is on the site in the panel and can start a chat. The visitor then sees an invitation card with the agent's name, not the message content.

  • An agent can't start a new chat while the visitor is talking to the assistant or waiting in a queue.
  • Under Proactive messages in the panel you can set automatic greeting rules for specific pages (e.g. after 20 seconds on the pricing page).
  • To turn this off entirely, use data-lazy="true".

16File attachments

TypeExtensionsMax size
ImageJPG, PNG, WebP, GIF10 MB
PDFPDF10 MB
AudioMP3, M4A, OGG, WAV20 MB
VideoMP4, WebM, MOV50 MB

Up to 3 files can be sent at once. SVG, HTML and office documents are rejected for security reasons. All files are quarantined and scanned before they are shared; they can't be opened on the agent side until marked clean.

17Content Security Policy (CSP)

If your site uses a CSP, add the following sources:

CSP
script-src   https://widget.embrchat.com
frame-src    https://widget.embrchat.com
connect-src  https://api.embrchat.com

Images and files load through the API, so no extra img-src entry is needed.

18Data sent and privacy

DataWhenNotes
Page URLEvery page viewQuery string (?…) and hash (#…) are never sent
Page titleEvery page viewDisable with data-send-title="false"
Referrer domainOn first loadDomain only, not the full URL
Device typeOn first loaddesktop / mobile / tablet
Name, email, member infoIf providedFrom visitor, signed identity or token
Messages and filesDuring a conversationOver an encrypted connection (TLS)
LanguageOn first load—
Random device IDOn first loadContains no personal data

The widget uses no cookies and does no fingerprinting. In localStorage it only keeps the chat-device and chat-lang keys; a dismissed banner is stored in sessionStorage.

You are responsible for informing your own visitors when you collect their data (you are the controller, we act as your processor under Art. 28 GDPR). See our Privacy Policy for details.

19Platform guides

WordPress

  1. Open Appearance → Theme File Editor → footer.php, or use a plugin such as “WPCode / Insert Headers and Footers”.
  2. Paste the code into the Footer area and save.
  3. With Elementor, use Elementor → Custom Code and choose Body – End as the location.
  4. If you use a caching plugin (LiteSpeed, WP Rocket), clear the cache.
If you use signed identity, the PHP code that creates the signature must run on non-cached pages or in an AJAX endpoint.

Shopify

  1. Go to Online Store → Themes → … → Edit code.
  2. In layout/theme.liquid, paste the code right before </body>.
  3. For logged-in customers, you can fill visitor inside a {% if customer %} block.

Wix / Squarespace / Webflow

Add the code under Settings → Custom code, set the location to Body – end and apply it to All pages.

Google Tag Manager

  1. Create a New tag → Custom HTML and paste the code.
  2. Choose All Pages (DOM Ready) as the trigger.
  3. If GTM strips the type="module" attribute, use this loader instead:
GTM
<script>
  (function(){
    var s = document.createElement("script");
    s.type = "module"; s.async = true;
    s.src = "https://widget.embrchat.com/v1/widget.js";
    s.setAttribute("data-widget-key", "wk_YOUR_SITE_KEY");
    document.body.appendChild(s);
  })();
</script>

20Troubleshooting

SymptomLikely cause and fix
The button doesn't appearDomain not in allowed origins; page is excluded; data-launcher="none"; CSP script-src missing
“Can't connect right now”CSP connect-src or frame-src missing; ad blocker; wrong key
Member shows as a guestSignature older than 10 minutes (cached page); payload changed after signing; wrong secret
VIP not routed to the VIP channelNo segment: "vip" in the payload; VIP channel not active in the panel
Agent can't see the visitordata-lazy="true" is on; tab is in the background; visitor idle for more than 60 s
Stale page shown in an SPApageView() not called after pushState
“Chat restricted” cardThe visitor was blocked by an agent; check the Blocked list in the panel

21Before going live

  • The tag loads exactly once on every page
  • The live domain (including www) is in the allowed origins
  • Signatures are generated on every page load; the secret stays on the server
  • Cached pages don't contain stale signatures
  • CSP updated (script, frame, connect)
  • Guest, member and VIP flows tested separately
  • Your privacy policy mentions the live chat tool
Need help with setup?
The Setup page in the panel generates a ready-made snippet for your site. If you get stuck, write to support@embrchat.com.
Apply now