flowhelp widget embed: customer guide
English version of the Polish guide. Code, identifiers and numbers are the same in both.
Version 1.10 · 2026-11-12 The snippet and the public API are stable: a tag pasted today will work with every future version of the widget.
1. Snippet
One tag, no inline code, before </body>:
<script async src="https://cdn.flowhelp.ai/loader.js" data-key="pk_live_…"></script>| Attribute | Required | Meaning |
|---|---|---|
data-key | yes | the agent's public key (pk_live_ + 32 hex characters), from the panel |
data-locale | no | forced window language (buttons and messages): en, pl, de, fr, it (a region is fine too, for example de-AT); if omitted, auto or a language outside the list, the setting from the panel decides, then the browser language, and if none matches, English. The assistant replies in the visitor's language when it is one of these five, and otherwise in the window language |
data-api | no | dev/staging only; production uses https://app.flowhelp.ai |
The public key is visible in your HTML by design. It is not protected by secrecy but by the domain allowlist (below), the rate limits and the assistant's daily message cap.
2. Domain allowlist (Origin)
The widget works only on the domains listed in the panel (Settings → Installation → "Allowed domains"). Semantics:
https://sklep.pl: exactly this domain (default port),*.sklep.pl: any subdomain over https (www.,blog.), without the apex; the apex is added separately,http://does not work: enter addresses withhttps://.
Local addresses are not supported (since 2026-11-12): localhost, 127.0.0.1, private networks (10.…, 192.168.…) and reserved names (.local, .test) are on the list of addresses flowhelp does not allow for any customer. The panel won't save them and the widget won't load on them. An entry saved earlier is flagged under the list in the panel. Test on your real domain or on a test subdomain (for example https://test.sklep.pl); check the look and the answers in the preview in the panel (Appearance).
A page outside the allowlist: the browser blocks the call (the server answers 403 without CORS headers), the widget does not appear and logs an error in the console. It costs nothing.
3. The host page's Content-Security-Policy
If your page has a CSP, exactly two sources are needed (the only exception is your own avatar, see below):
script-src … https://cdn.flowhelp.ai;
connect-src … https://app.flowhelp.ai;The widget uses no inline JS, no eval, and no external resources beyond these two hosts. The exception is an avatar loaded from your own address (the "Avatar URL" field): if your CSP has img-src, it must include the host of that image (section 9). Styles live in a Shadow DOM (adoptedStyleSheets), so style-src does not need to change. The loader has a fixed path (5-minute cache); the core is addressed by hash, with integrity (SRI) and crossorigin.
4. Public API
Calls can be queued before the widget loads; they are executed in order:
window.flowhelp = window.flowhelp || [];
window.flowhelp.push(['open']);
window.flowhelp.push(['on', 'ready', () => console.log('widget ready')]);| Method | Effect |
|---|---|
open / close / toggle / isOpen | the chat window |
sendMessage(text) | sends a message as the user |
setLocale('pl'|'en'|'de'|'fr'|'it') | window language; the assistant replies in the visitor's language when it is one of these five, and otherwise in the window language |
on(event, cb) / off(event, cb) | events: ready, open, close, message:sent, message:received, error |
grantConsent() / revokeConsent() | consent (see §6) |
reset() | clears the visitor identifier, the current conversation and the identity set by identify |
identify({ userId, hash }) | identity of a signed-in user with an HMAC signature (§5); identify(null) = sign out |
init | no effect (the widget starts by itself) |
Through the push queue methods return nothing, so isOpen makes sense only when called directly. After the ready event you can call the methods directly, for example window.flowhelp.open() or window.flowhelp.isOpen().
An unknown method logs a console warning and does not throw.
5. Signed-in users: identify() with an HMAC signature
If your site knows who is signed in, you can pass that to the widget. Conversations of such a user are labelled with their identifier in the panel.
The widget does not compute the signature and does not know the secret. Your backend computes the signature, using the assistant's HMAC secret (panel → Settings → Installation → "Secret for signing users (HMAC)"):
hash = hex( HMAC-SHA256( key = agent_secret, message = userId ) )Node.js:
const { createHmac } = require('node:crypto');
const hash = createHmac('sha256', process.env.FLOWHELP_HMAC_SECRET).update(user.id).digest('hex');PHP:
$hash = hash_hmac('sha256', $user->id, getenv('FLOWHELP_HMAC_SECRET'));Python:
import hmac, hashlib
hash_ = hmac.new(SECRET.encode(), user_id.encode(), hashlib.sha256).hexdigest()On the page (this can run before the widget loads; it goes into the queue):
window.flowhelp = window.flowhelp || [];
window.flowhelp.push(['identify', { userId: 'u_123', hash: '<64 hex characters>' }]);
// after sign-out:
window.flowhelp.push(['identify', null]);Rules:
userIdis your internal identifier (or an email): 1-200 printable ASCII characters without spaces. A full name with non-ASCII characters will not pass, because the value travels in an HTTP header. The widget rejects a bad payload with a console warning; the previous identity (if there was one) stays unchanged. Signing out is done only withidentify(null); switching to another user (or signing out) starts a new conversation, and the previous transcript disappears from the window.- The signature is sent with every message and verified on the server in constant time. A mismatched signature returns
403before anything is counted. - Identity does not change the limits or the owner of the conversation; those follow the visitor identifier from the browser. A conversation that started anonymously gets the identity once
identify()is called during it. - The widget sends only
userIdand the signature.email/nameare not passed today. - Keep the secret on the server side. If it leaks, changing the secret invalidates all signatures at once.
6. Consent (GDPR) and the AI disclaimer
You choose the consent mode in the panel: Appearance → the "Privacy" tab → "Visitor consent".
- "Chat right away" (
open): the widget works immediately, with no consent question. - "Chat after clicking “I agree”" (
deferred): the default. The chat button is visible, but the first message waits for consent. The visitor clicks "I agree" in the banner in the window, or your page callsgrantConsent(). A message typed before consent waits and is sent right after it. - "Widget hidden until your site passes consent" (
blocked): the widget draws nothing, neither the button nor the window, until your page callsgrantConsent(). An earlieropendoes nothing. You pass consent from your own cookie banner (CMP) once the visitor gives it:
window.flowhelp = window.flowhelp || [];
window.flowhelp.push(['grantConsent']); // the visitor agreed
window.flowhelp.push(['revokeConsent']); // the visitor withdrew consentrevokeConsent() ends the current conversation (clears the window), and in blocked mode hides the widget again. The visitor identifier stays; only reset() deletes it.
Consent is not remembered: after a page reload or a move to another page, deferred and blocked start over. In deferred the visitor clicks "I agree" again, and in blocked your page must call grantConsent() on every page load (a CMP usually remembers consent itself, so you can hook the call to its start). The visitor identifier is a UUID in localStorage (flowhelp:visitor:<key>; in sessionStorage when localStorage is blocked), with no cookies. The widget writes it only on the first interaction: the first message, a rating of an answer or a form submission. Loading a page with the widget writes nothing to the browser (not even an entry that checks whether storage is available). The first message always includes the AI disclaimer (EU AI Act Art. 50); it is editable in the panel and cannot be turned off.
Link to your privacy policy
As the controller of your site visitors' data, you inform them about the processing at the moment you collect it (GDPR Art. 13). In the panel (Appearance → the "Privacy" tab → "Privacy policy URL") you enter the address of your policy, and the widget shows a "Privacy policy" link in the language of the chat window (for example "Datenschutzerklärung" in German, "Politique de confidentialité" in French, "Informativa sulla privacy" in Italian):
- in the consent banner in the chat window (
deferredmode), above the "I agree" button, - in the contact form and in the "talk to a human" form, above the "Send" button (in every consent mode, including "Chat right away").
The link opens in a new tab (target="_blank", rel="noopener noreferrer"). Only https:// addresses are accepted (up to 2000 characters); an empty field means no link. In blocked mode the widget has no consent banner of its own: your banner (CMP) shows the consent request and the link to your policy, and the widget adds the link only in the forms. The link is a plain hyperlink and loads nothing from your site, so it needs no CSP changes.
7. Limits and errors
| Situation | Behavior |
|---|---|
| 20 messages / 5 min from one visitor | 429 RATE_LIMITED, the widget locks the input until the window ends and says how long to wait: in seconds, from one minute in minutes ("Try again in 5 min"), from one hour in hours |
| a second message before the previous answer has finished | 429 RATE_LIMITED (Retry-After: 5) |
| message allowance used up: the trial after 100 messages, a paid plan at 200% of its allowance | 429 QUOTA_EXCEEDED, the assistant is paused (below); the trial without Retry-After, a paid plan with Retry-After until the end of the billing period |
| the assistant's daily message limit is used up (safety cap): the greater of 1,000 and 10% of the message allowance per UTC day | 429 QUOTA_EXCEEDED with Retry-After until midnight UTC, the assistant is paused (below) |
| the agent stopped being published during a conversation | 403 FORBIDDEN, the assistant is paused (below) |
| the 14-day trial has ended | 403 FORBIDDEN on every widget route, the bootstrap included: the widget does not appear, the service is switched off (below) |
assistant unpublished or paused (not in the ready status) when the page loads | 403 from the bootstrap, the widget does not appear |
mismatched identify() signature | 403 before any answer, zero cost |
| question outside the knowledge base | the assistant searches again with different words; if there is still nothing, it says plainly what is missing, adds the closest fact with its source and suggests related questions, with no guessing |
RATE_LIMITED is only ever the limit of one visitor, their network, or parallel messages, so its windows are short. A used-up allowance and the daily safety cap apply to the whole assistant: those are QUOTA_EXCEEDED, and the assistant is paused while contact with your business stays (below). The end of the trial is different: the service is switched off and the widget disappears from the page (below).
When the assistant is paused
The assistant may stop, but contact with your business does not. The visitor sees neither "Something went wrong" nor a countdown, and reads nothing about your plan, trial or message limit. They see the line "The assistant is unavailable right now.", and under it a way to reach your team:
- when someone on your team takes live chats (section 14): the "Talk to a person" button (or your escalation label), which notifies the team as usual;
- otherwise a contact card: the "talk to a human" form when escalation is on, and without it the contact form (section 12).
The message field is then locked, with the hint "Use the contact option above", until someone on the team takes over the conversation. From the takeover on, the visitor writes as usual and their messages go to that person: a conversation taken over by a person goes through despite the pause. A closed card does not come back by itself every time the window opens; the pill under the line or the button with the form's title above the message field opens it again.
The bootstrap reports the pause in the behavior.assistantPaused field, without giving a reason: that is none of the visitor's business. The widget then shows this screen as soon as the window opens, instead of the welcome message and the suggested questions. A pause during a conversation (QUOTA_EXCEEDED or FORBIDDEN) looks the same: the visitor's question stays on screen, and the line takes the place of the answer. The error event of the public API (section 4) and the console entry with the error code work as before.
The widget checks by itself whether the assistant is back: when the window opens and when the visitor returns to the browser tab, at most once a minute. Once it is back (for example after a plan change, or at midnight UTC after the daily safety cap), the message field unlocks without a page reload and the "unavailable" line gives way to the welcome message; a line that took the place of an answer during a conversation stays in the history.
With no way to reach you, the widget does not appear. When the assistant is paused, nobody on your team is online, and both escalation and the contact form are off, the page shows neither the chat button nor the window, and the browser console has a short note for the site's developer. Exceptions: a conversation from the last 30 minutes (section 14) comes back to the window, and during a conversation the window never disappears. Every 10 minutes, and only while the tab is visible, the hidden widget checks whether the assistant is back or you have turned on a way to reach you, and then appears by itself. Advice: turn on the contact form (panel, Settings → Actions → "Enable the contact form"). Then, even with the assistant paused, visitors leave you their contact details instead of landing on a page without chat.
When the trial has ended
After the 14-day trial, if you have not chosen a plan, the service on your website is switched off, not paused: visitors see nothing at all, neither the chat button, nor the window, nor any message. Every widget route answers 403 FORBIDDEN with the message The trial has ended. Sign in to the flowhelp panel to choose a plan., and so does the bootstrap (GET /api/widget/bootstrap): the widget draws neither the chat button nor the window, and the browser console shows the same message with the error code. There is no contact mode: the contact form, the request for a person, live chat (including a conversation someone on your team has already taken over) and resuming a conversation after moving to another page stop working. The only exception is a visitor who had the chat window open at the very moment the trial ended: their next message is refused with the line "The assistant is unavailable right now.", and after a page reload the widget is gone.
Your data (knowledge, conversations, contact requests) stays in your dashboard: you can view and delete it, and export your conversations. Until your plan changes, the dashboard does not add or refresh knowledge (pages, files, notes, Q&A, "Refresh all websites"), does not take live chats, and does not answer test questions or suggest answers. The widget comes back by itself, from the next page view, as soon as we change your plan: you do not need to paste the snippet again. The dashboard shows a red banner on every page, and we email you about the switch-off the first time someone opens your site with the widget after the trial ends.
8. Formatting of answers (markdown)
The assistant's answers are rendered from markdown: paragraphs, bold, italic, ~~strikethrough~~, code and code blocks, lists (nested too), quotes, a horizontal rule, tables, links. # headings are rendered as bold paragraphs, not as <h1>, so they do not affect the structure of your page.
What the widget does not render, because model text never becomes HTML: raw HTML (shown as text), images (the description stays), links with a protocol other than http/https/mailto (they stay as text). Every link opens in a new tab with rel="noopener noreferrer".
Source links do not appear in the body of the answer. Instead of "[1][2]" in the middle of a sentence, a row of clickable links to subpages of your site is shown below the whole answer, preceded by the word "Sources"; each of them opens in a new tab. One subpage = one link, even if the answer drew on several of its fragments, and at most three links under one answer. Further hits are in the conversation in the panel.
Links appear only under an answer based on a web page from your knowledge. An answer based on a file, a note or a Q&A has no link, and neither has an answer that does not rely on your knowledge (a greeting, a clarifying question, an answer about the chat itself, section 15).
9. Appearance, theme, RTL, mobile
- The window header is the assistant's name, an avatar and an "AI" badge. The name comes from the assistant name set in the panel (Appearance → "Assistant name"; up to 60 characters in the chat window, longer names are truncated). Below the name there is a second line, "AI assistant" (in Polish: "Asystent AI"). Without a name the header has a single line and simply says "Assistant".
- The "AI" badge cannot be turned off or changed. It is a marking required by Art. 50 of the EU AI Act and is rendered by the widget code, not by configuration. The
aiDisclaimersentence in the thread stays unchanged; the badge does not replace it, it repeats the information where it is visible after scrolling the conversation. - The avatar should be an illustration, not a photo of a real person. Giving the assistant the face of a specific employee suggests to the visitor that they are writing to a human, and that is exactly what Art. 50 forbids. Without
avatarUrlthe widget draws the initials of the name on the primary color, and without a name a neutral speech-bubble icon. - The chat button in the corner of the page (panel: Appearance → "Chat button") has three variants. Bubble: a round button in the primary color; the default for older assistants. flowhelp mascot (the Flow character): our character (a speech bubble with eyes), white, on a circle in the flowhelp gradient, the same one used by the buttons on flowhelp.ai; the default for new assistants. Once after the page loads it hops slightly and blinks twice (after 5 seconds it stands still), and it rises by 2 px under the cursor; once the chat is open, the same circle shows a white cross. The circle's color does not depend on the primary color; this is the variant with the flowhelp brand. With this variant the character also appears in the window: in the header instead of initials (when you set no avatar URL) and in the "typing" indicator. In the window it reacts to the conversation: while the visitor has text in the field it looks down at the field; from sending a question until the first words of the answer its eyes become three bouncing dots; while the answer streams, the dot above the bubble breathes; then it blinks twice and stands still. The assistant's name stays yours. Assistant avatar: your image from the "Avatar URL" field inside the circle, with a small speech-bubble badge in the primary color; without an avatar URL (or if the image fails to load) the button shows the bubble. The label for screen readers is the same in every variant ("Open chat" / "Close chat"), and when the system has reduced motion turned on (
prefers-reduced-motion: reduce) the character stays still. The avatar variant loads the image in the button as soon as the page opens; if your CSP hasimg-src, it must include the avatar's host (the same as for the avatar in the window header). - The widget's texts never use the word "bot": the counterpart is called an AI assistant, never an "employee" or a "consultant".
- You set the primary color and the theme (
light/dark/auto, followingprefers-color-scheme) in the panel. The widget uses system fonts and does not download fonts. - Your page's styles do not enter the widget (Shadow DOM with a full reset), and the widget's styles do not leak onto the page. Even global rules such as
* { letter-spacing: 2px }have no effect. - A page with
dir="rtl"gets a mirrored layout of the header, the action row and the composer; the text direction of a message follows its content (dir="auto"), so a visitor's message in Arabic also displays correctly on a Polish page. The screen corner (bottom-right/bottom-left) is chosen in the panel and is not mirrored. - A consequence of
dir="auto"that is visible on an RTL page too: an empty field (the composer, the contact form fields) has no content from which a direction could be inferred, so its placeholder sits on the left even though the labels are on the right. It aligns with the first character typed. This is intentional: the direction comes from what the visitor writes, not from the language of your page. - The contact form is a card in the conversation, under the message where it appeared (section 12).
- On phones (below 640 px of width, or below 500 px of height in landscape) the chat window fills the screen and follows the on-screen keyboard (
visualViewport), so the input field does not hide under the keyboard. While the window is open, your page underneath does not scroll (the widget adds a stylesheet todocument.adoptedStyleSheetswithoverflow: hiddenon the element that scrolls the page and removes it on close; it does not touch the inline styles of<html>and<body>), and the input field is 16 px, so iPhone does not zoom the page when it is tapped. Withviewport-fit=coverthe window leaves room for the status bar, the screen notch and the home indicator. - The host's
z-indexis 2,147,483,000; sticky headers and footers with a highz-indexdo not cover the widget.
10. Compatibility with frameworks and CMSs
The widget works with WordPress (Elementor), Bootstrap, Tailwind and any page where you can paste a <script> tag. The styles of your page and of the widget do not mix: your page does not change how the widget looks, and the widget does not change how your page looks.
| Environment | How to paste |
|---|---|
| WordPress (Elementor) | the snippet in the page footer (wp_footer), for example with a custom-code plugin |
| Bootstrap, Tailwind | no changes, the tag before </body> is enough |
A dir="rtl" page | header and composer mirrored, screen corner unchanged |
If your theme has global rules such as * { letter-spacing: 2px }, they have no effect (the widget has a full reset with !important on the host). The only things the widget needs from your page: two hosts in the CSP (section 3) and, with your own avatar, its host in img-src; your page's X-Frame-Options does not matter, because the widget is not an iframe.
11. How to check that the widget works
Open the page with the pasted tag: the chat button should appear in the corner. Whether the widget has loaded is also visible in the panel under Settings → Installation → "Widget status". If there is no button, look at the browser console: the error says whether the domain is missing from the list (section 2), whether the CSP blocks a host (section 3), or whether the assistant is unpublished or paused (section 7). You publish an unpublished assistant in the panel: Settings → Installation → "Publish the assistant". The same file served from a different origin (for example opened from disk) does not start the widget.
12. Answer ratings and the contact form
You turn both on in the panel; in the snippet nothing changes, and there is no API here to call from your page.
Thumbs under an answer
When the agent has rating collection turned on, every assistant answer has two buttons under it (👍/👎). To keep the conversation uncluttered, on a computer they appear when the pointer is over the answer (or when you reach them with the Tab key), and on a phone they are visible only under the latest answer; a rating you have given stays visible. Clicking the same one a second time undoes the rating. Ratings appear in the panel in Conversations (the "thumbs down" filter); this is the only quality signal that comes from your visitors.
Turning ratings off in the panel really turns them off: the buttons disappear, and a request sent anyway gets 403. A thumb requires neither cookie consent nor signing in. We attach it to the same conversation in which the answer was produced, and only that browser can rate it.
Contact form (lead) and "talk to a human"
The form appears according to the trigger set in the panel:
| Trigger | When the widget shows the form |
|---|---|
after_messages | after N assistant answers (N from the panel) |
on_fallback | when the visitor asks for it (recommended; in the panel "when the visitor asks to get in touch"). The form never pops up on its own: a button with the form's title appears under the answer when the visitor writes that they want to get in touch, or the second time they get no answer. After every "don't know" the widget suggests related questions from your knowledge |
manual | never on its own; there is a button with the form's title above the input field |
The fields (labels, types, required flags; max 8) come from the panel. The form opens as a card in the conversation, under the message where it appeared; it covers and blocks nothing, so the visitor can keep writing to the assistant. Opened by a trigger, it does not take the cursor out of the message field; opened by a click, it puts the cursor in the first field. You close it with the cross or the Esc key. Closing it turns off the automatic trigger until the end of that conversation, so it does not come back after every message. After submission the visitor sees your thank-you text in the same card, and the cursor goes back to the message field. When the assistant is paused (section 7), the card opens by itself as soon as the window opens, whatever the trigger, because it is then the way to reach your team; with escalation on, the "talk to a human" form opens instead.
Escalation is the same form with an extra "Message" field. The widget does not keep it above the message field all the time: it has a small "person" icon in the header (always available, with your label as its name) and a pill under the answer that appears only when it is needed: at the second "don't know" in a conversation, or when the visitor writes that they want to talk to a person or get in touch (recognised in five languages, Polish also without diacritics). After a request is sent, the pill does not come back in that conversation. The conversation gets the "Escalated" status in Conversations, and Insights counts it as a conversation with a person involved (the "Handled without a human" metric).
If you entered the address of your privacy policy in the panel, both forms show a "Privacy policy" link above the "Send" button (§ 6).
Every submitted form goes to the panel and to email: the address from the action settings, and if there is none, the workspace notification address, and if there is none of those, the owner's email. The message contains the form fields and the last 10 messages of the conversation, so you can reply without opening the panel.
Limit: 5 forms per visitor per day (a UTC day). This is a safeguard for your inbox and for our sender reputation; it cannot be raised in the panel. A rejected form gets 429 with a message, and the content stays in the fields.
13. Widget languages and agent texts in other languages
The widget speaks English, Polish, German, French and Italian. The language is chosen in this order: the data-locale attribute in the snippet (or setLocale() from the page), then the "Widget language" setting in the panel (Appearance), and with "Automatic", the visitor's browser language. If none of them matches, the widget uses English. This language applies to the buttons and the messages, regardless of the language of your knowledge base. The assistant also answers in it when the visitor writes in a language outside these five or too briefly to tell ("ok"); when the visitor clearly writes in another of the five languages, the assistant answers in the visitor's language (section 15).
The texts you write yourself, that is the welcome message, the AI notice and the suggested questions, are in one language: the one you typed them in. In the panel (Appearance, the "Texts in other languages" section) you can give each of them a version for a specific language:
- the widget takes the version in the visitor's language field by field: if you translate only the welcome message, the AI notice and the questions stay in their main version. The questions are one field: a filled list in a language replaces all the main questions, and empty rows are skipped;
- an empty field means "use the main text", so you do not have to fill in every language or every field;
- the AI notice is never empty (EU AI Act, Art. 50): an empty language version shows the main text;
- language versions work on every plan and need no change to the snippet.
The texts of the contact form and of the talk-to-a-human button (section 12) work the same way: in the panel (Settings → Actions, "Texts in other languages") you can enter the heading, description, thank-you message and the label of every form field, and the button text, in each of the five languages. The widget takes them field by field, as above. A submitted form always has the same fields, whatever the visitor's language.
In Appearance → Texts you also set "Language of the main texts". That language's tab disappears from "Texts in other languages", and the panel tells you which visitors will see the main texts instead of their own, that is which languages have no welcome message.
14. Live chat
When someone on your team turns on "Take live chats" in the panel and has the panel open, the widget shows a strip under the header: "Anna from the team is online". Nothing changes in the snippet.
- Asking for a person. The person icon in the header and the pill under an answer (section 12) then do not open the form; they notify the team: the conversation shows "We’ve let the team know. Anna is online.", and the panel plays a sound and shows a notification. If nobody takes over within 90 seconds, the widget shows the contact form (when it is set up) or says that nobody can reply right now. The assistant keeps answering meanwhile. When nobody takes live chats, everything works as in section 12.
- Taking over. When someone on the team takes over, the visitor sees "Anna joins the conversation", and that person's replies carry their name and no AI badge; the assistant's answers always have it (AI Act, Art. 50). The assistant does not answer in a conversation that a person has taken over. After the hand-back the conversation shows "<assistant name> is back in the conversation".
- Nobody waits for someone who is gone. The conversation returns to the assistant on its own when the person closes the panel or does not reply to the visitor for 5 minutes.
- Continuity (on every plan, also without live chat). The widget remembers the current conversation for 2 days after the last message (
flowhelp:conversation:<key>in browser storage, next to the visitor identifier; only the conversation identifier, the transcript comes back from our server to the same browser only), so after moving to another page of your site or coming back to it the conversation is still in the window, with live chat including the team's replies. The “New conversation” button (a plus in the header, shown once there is a conversation) starts from scratch and forgets the previous conversation in this browser; it stays in your panel. Conversations verified withidentify()(section 5) resume only for the same signed user. Indeferredconsent mode (section 6) consent does not carry over to the next page, so the conversation returns to the window only after the visitor clicks “I agree” again. Until then the widget sends no request. A message typed before that click goes into the resumed conversation. - What the visitor sees. The first word of the account name and its initial. If the account has no name, the widget says "Someone from the team". Never an e-mail address.
- "Typing…". The team sees that the visitor is typing, not what they type before sending.
- Connections. The live channel is one SSE connection to
app.flowhelp.ai(the same host as the chat), opened only while the chat window is open and only when someone on your team takes live chats. The Content-Security-Policy from section 3 needs no change. - Team replies do not use messages from your plan. Only an assistant answer counts as a message.
- When the assistant is paused (section 7), live chat is the main way to reach your team: the "Talk to a person" button stands under the line "The assistant is unavailable right now.", and after a takeover the visitor writes as usual, because a conversation led by a person goes through despite the pause. If nobody takes over within 90 seconds, the widget shows a form (escalation or the contact form), and without any form the line "Nobody from the team can reply right now.", now without the invitation to keep asking.
15. What the assistant knows about itself
About your company the assistant speaks only from your knowledge (the sources in the panel). When an answer is based on a web page, links to it stand below the whole answer (section 8). About itself and about the chat it knows from a short assistant card that we build automatically from the agent's settings, never from the content of your website. That is why questions like "Who are you?", "Which languages do you speak?", "Can I talk to a person?" or "Does anyone read this conversation?" get answers that match how the chat really works, even when your knowledge says nothing about it (or says something else, for example terms that list the language versions of a document).
| What the assistant says | Where it comes from | How to change it |
|---|---|---|
| its name, and that it is an AI assistant, not a human | the assistant name; without a name: "the AI assistant on this website" | Appearance → "Assistant name". The fact that it is an AI cannot be turned off (AI Act, Art. 50) |
| which website it works on | the domain from the list of allowed domains (www. and subdomains are merged into the main domain); with several different domains: "this website" | Settings → Installation → "Allowed domains" |
| where its knowledge comes from | information shared by the company: pages, documents and the team's answers; it can be wrong, so binding matters (prices, contracts, orders, complaints) are worth confirming with you | fixed |
| which languages it speaks | the widget works in English, Polish, German, French and Italian; the assistant answers in the visitor's language when it is one of these five, and otherwise in the language of the chat window (section 13); it understands other languages and never says it does not speak them | Appearance → "Widget language", or data-locale in the snippet |
| how to reach a person | the agent's actions (section 12) and live chat (section 14): with escalation, the person icon in the header or a request in a message; with live chat, someone from the team joins when online; with the contact form, it says when the form appears. With none of these it says that this chat cannot hand the conversation over to a person, and gives your contact details only from your knowledge | Settings → Actions; "Take live chats" |
| what it will not do | it does not place orders, take payments, change bookings, reset passwords, send emails or links, or see accounts, orders or customer data; it does not promise such actions and does not ask for login details or card numbers; it can explain how to do these things when your knowledge describes it | fixed |
| what it remembers | the recent messages of this conversation, not earlier conversations; the conversation stays in the window for 2 days after the last message, also on other pages and after coming back, and “New conversation” in the header starts from scratch | fixed (section 14, “Continuity”) |
| privacy of the conversation | the conversation is processed by an AI provider and saved, and your team sees it in the panel; it advises against sharing passwords, card numbers and health data; it gives the address of your privacy policy | Appearance → "Privacy policy URL" (section 6). Without an address the assistant gives it only from your knowledge |
| what it runs on | "flowhelp", but only when the chat window shows "Powered by flowhelp"; with the line hidden (Growth plan and above) it does not name the provider. It never names the AI model | Appearance → "Hide the 'Powered by flowhelp' line" (Growth plan and above). On Trial and Starter the line always shows; after a move to a plan below Growth it comes back by itself |
Changes to the settings apply from the next message, with no change to the snippet. Every answer of the assistant counts as a regular message from your plan, including an answer from the card.
How the assistant handles a conversation:
- Follow-up questions ("and how much is it?", "only that one?") are understood in the context of the previous question, also when searching your knowledge: a short message is searched together with the visitor's previous question. Insights and the conversation history keep exactly what the visitor wrote.
- Numbers (prices, limits, dates) come only from the sources found for the current question; a number from an earlier answer is not a source for a new one, and when the number is not in your knowledge, it says so plainly instead of guessing.
- Source links appear only under answers based on a web page from your knowledge, not under an answer from the card, from a file, a note or a Q&A, a greeting or a clarifying question (section 8).
- An unclear question gets one short clarifying question instead of a guess.
- Greetings, thanks and goodbyes get one sentence and an offer to help, never a "don't know".
- Anything outside your company and website, whether questions (weather, general knowledge, homework) or requests (a song, a poem, a joke, a recipe, code, translating a text, role-play), gets one polite sentence that steers back: the assistant helps with matters of your website (it names the domain from your allowed domains) and asks what it can help with. It does not carry out such requests even in part, also when the visitor insists. Gibberish, a single meaningless word and rude messages get the same reply, without a clarifying question and without repeating the word. None of this goes to Insights as missing knowledge or opens the contact form. When in doubt, the assistant treats a question as one about your company.
- One language per reply: the assistant does not switch languages mid-reply or mix in words from another language; when the language of a message cannot be told (a single word, a typo), it writes in the window language.
- A question about your company that your knowledge does not answer still ends with "I don't have that information…" and an entry in Insights. The assistant answers questions about itself and greetings even while your knowledge is still empty (for example right after the agent is created).
16. Content the assistant should not read (data-flowhelp-skip)
The assistant learns from the content of your pages. If a page has a part that should stay out of its knowledge (an archived promotion, customer reviews with old prices, a sample conversation), add the data-flowhelp-skip attribute to its element:
<section class="archive" data-flowhelp-skip>
…
</section>The next time the page is read, the crawler skips that element and everything inside it; the rest of the page stays in the knowledge base. If almost nothing is left on the page after that, the assistant stops using the page altogether. Nothing changes for visitors or search engines. Content the assistant already knows disappears after the page is read again. The change takes effect at the next refresh of the page: the automatic one (weekly from the Starter plan) or the "Refresh" button next to the source in the panel → Knowledge (once a day; on the trial, once during the whole trial).