The chat widget
A chat bubble for your own website where every conversation becomes a ticket in a table — the same thread your team answers from the record page. Anonymous conversations, the visitor's own credential, polling, rate limits and framing rules, a designer to configure it and a one-line snippet to paste on your site.
The third door into a table
A form takes a submission and stops. An email address takes a message and can carry on. The widget is the third way in and is deliberately the same shape as both: an unguessable token is the address, the table it files into is fixed when the view is created, and it starts switched off so minting one never silently opens an anonymous write endpoint on somebody's data.
What makes it different is that the conversation keeps going. One chat is one record, and that record's thread holds the chat, any email about it, and your team's internal notes together.
A messenger, not a live chat
This is the distinction the whole widget is built around. It is not a live-chat queue where someone sits waiting and an answer is expected in seconds. A visitor leaves a message, it becomes a record in your table, somebody works it, and the reply arrives — here if they are still around, by email if they are not. That is a perfectly good experience, but only if it is the one they were led to expect.
So the widget never pretends otherwise. There is no typing indicator and no presence dot, because either would claim someone is at the other end when nobody may be. Instead you get two honest signals:
• An expected reply time, set in the Widget view and shown in the header before the visitor types a word — Typically replies in a few hours. Say it, then keep it.
• Progress, so they can watch the ticket move instead of watching an empty box.
Try it before your customers do
The Widget view carries a live example beside the settings: the real chat window, rendered from the same markup and stylesheet your visitors get, with your branding already applied. Type into it and it plays the whole round trip — the message sent, the reply promise, the ticket moving through your published statuses, and the reply arriving after a visible gap.
It is driven by a scripted conversation, not the live endpoint, so designing a widget never files a real ticket into your table. Edits to the title, opening message, reply time and status labels appear in it as you type, before you save.
Answers from your own knowledge base
While someone types, the widget can offer answers drawn from a table of yours — so the commonest questions never become a ticket at all. The answer opens inside the chat; nothing links away from your site.
In the Widget view, open Answers. If you have no knowledge base yet, Create a knowledge base for me builds one — a table with an Answer, a Published tickbox, a Category and Keywords — and points the widget at it in one step. You can also nominate any table you already have, then choose which field holds the question, which holds the answer, and which field marks a row as published.
Because it is an ordinary table, everything else in RowFold applies: edit answers in the grid, import them from a spreadsheet, filter and sort them, and let automations keep them fresh.
What is public, and what is not
Nominating a table publishes part of it. The widget's snippet sits on your public website, so anything the widget can read can be read by anyone who opens the chat.
That is why publishing is opt-in per row rather than per table. You choose a field — usually a tickbox called Published — and the value that means published. Only rows matching it are ever offered, and only through the two fields you mapped: the question and the answer. Nothing else on the row travels, not the record's id, not your other columns, not how many rows the table has. A draft stays a draft, and a private table cannot be nominated at all.
Add a Widget view
The quickest route is + New → Run a help desk, which sets up the bubble along with an address and the columns a desk needs. To add one to a table that is already a queue, open the table and click + View → Chat widget. RowFold mints the token and maps the obvious fields — the visitor's email, their name, and the opening message — but only where the answer is unambiguous: one Email field on the table means one candidate, and several means it maps nothing and leaves the choice to you in the designer.
The view is created switched off. Its designer carries the snippet to paste on your site, what the visitor sees, which fields a conversation lands in, who gets told, and where the widget is allowed to run.
What happens when a visitor opens the chat
Your page loads a small launcher and an iframe pointing at /w/{token} on RowFold's own origin. Everything that touches data runs inside that iframe, same-origin with us, so the conversation's credential never enters your page's JavaScript, a hostile site hosting the widget cannot read it, and no cross-origin API surface has to exist at all.
The first message creates the ticket through the ordinary write path — Auto number stamps a reference, automations fire, a chat ticket is not a second-class ticket. The record is named after the question actually asked, trimmed at a word, because that is what an agent scans in the grid.
Where the chat came from
How do I cancel this? is unanswerable without knowing what this is. Every conversation carries the page the visitor was standing on and its title, shown at the top of the thread — and if they move around mid-chat, a moved to marker appears between the messages, so a wandering conversation reads as a trail rather than a mystery. Point Put the page in at a field and it becomes a column too, so you can filter and group the queue by where chats are coming from.
You can attach your own details as well. Call RowFoldChat.setContext({ plan: 'pro', orderId: 'A-1183' }) anywhere on your site and those values ride along with the conversation. Send what identifies the customer to you — not passwords, card details, or anything you would not put in an email about them, because everyone who can open the ticket can read them.
The query string is dropped unless you ask for it. Plenty of real URLs carry a session token, a sign-in link or a customer's email address after the ?, and copying that into a ticket table — and into the notification emails about it — is not a thing to do by accident. Turn it on when you need it, on the widget that needs it.
One honest limit. The chat window runs on RowFold's origin, so it cannot see the page around it; your site tells us, which means the address is reported by the page rather than proven. The one thing we can check is the site the browser loaded the chat from, and where that disagrees with the reported address the thread says so and stops offering it as a link.
How the conversation stays live
The widget polls rather than holding a socket open, and its cursor is a sequence number the database assigns rather than a timestamp. Two messages committed at the same moment can disagree with the clock, and a cursor that disagrees with commit order silently steps over a customer's message. A couple of seconds of latency is the price; not losing what somebody said is what it buys.
Show them where their ticket has got to
Every conversation shows Received the moment it lands — that one is automatic and needs no setup, because it is true the instant the record exists.
Beyond it, progress comes from the Select field your team already works in the grid. In the Widget view, pick that field and write what each option should say to a customer: In progress might read Working on it; Tier 2 might read Escalating to a specialist. Moving the card is then the same act as telling the customer — there is no second status to keep in step.
Publishing is per option, and blank means never shown. Leave Spam, Waiting on legal or Duplicate empty and a visitor sitting on one of those simply keeps seeing the last published state. An option you never label can never leak.
When a published status changes, the visitor sees it in the header and gets a line in the conversation saying so. It is the one "something happened" signal an async conversation has between messages — and unlike a typing indicator, it is true.
What a visitor is allowed to read
Every message carries an explicit visible to the visitor flag, set when it is written and never inferred from who wrote it. The distinction is the whole point: an agent emailing a supplier about the same ticket produces a message from your side, and filtering on who wrote it would hand that supplier correspondence to the anonymous stranger who opened the chat. Internal notes are excluded for the same reason — nobody set the flag on them.
The visitor sees you and them and never a staff name. They came to talk to a business rather than to Sarah in support, and the widget renders your side as your brand.
Leaving an address, and ending the chat
A visitor can leave an email address mid-conversation so a reply still reaches them after the tab is closed. It is strictly a delivery target: it never resumes a conversation, because type an address to pick up where you left off is an account-takeover primitive dressed as a convenience.
End conversation retires their credential immediately — the point of which is a shared machine — and can email them the transcript first. The transcript contains exactly the messages they could already read, and nothing else. The ticket and everything said on it stays with your team; the team's record of a conversation is not the visitor's to delete.
Answering from the record
There is nothing new to learn. A chat ticket opens in the same Conversation panel as an emailed one, and each message is labelled by how it travelled, so you are never told a chat reply went out as an email. A ticket with an open chat and an address gets both at once — you type once and reach the person wherever they actually are.
Tips
• Point the widget at the same table your form and your email address already use — one queue, three doors.
• List your own site's origins on the widget and a phishing page can't wear your support chat; leaving it blank means anywhere, which is the honest default for something built to be embedded.
• Give the table an <strong>Auto number</strong> field so chat tickets carry the same reference as everything else in the queue.
• Map the opening message to a Long text field and the grid shows what was asked without anyone opening the ticket.
• Promise the reply time you can actually keep. "A few hours" kept beats "a few minutes" missed - the point of stating it is that nobody sits watching an empty box.
• Label only the statuses a customer benefits from seeing. Three good ones read better than every option in your workflow.
• Answers come from your table, never from RowFold's own help — your visitors should never be reading our documentation.
• Start with the ten questions your team answers most. A knowledge base earns its keep at about that size, not at a hundred articles.
Good to know
• Chat is rate-limited per IP address at 60 requests a minute and 300 an hour — generous for a real conversation behind an office connection, deliberately short of a grind.
• A visitor's conversation stops being readable from their browser 30 days after it starts, and the instant they end it.
• Every page in RowFold refuses to be framed except the public form and widget paths, so the app itself cannot be embedded in your site.
• An origin list restricts who may FRAME the widget, which is the attack that matters — it is not a list of who may call the endpoints, because every call comes from RowFold's own iframe and so always carries RowFold's origin, never yours.
• A status option with no label is never shown - that is the safety property, not a bug. If a customer seems stuck on an old status, check whether the option the ticket is now on was left blank.
• Progress needs a Select field on the table. If the Widget view offers nothing to pick, add one (New, Reviewing, In progress, Escalated, Resolved) and it will appear.
• Nothing is suggested until a table, an answer field, a published field AND the value that means published are all set. A half-configured knowledge base stays silent rather than guessing.
• If you delete or retype a mapped field, or make the table private, suggestions stop rather than erroring — check the Answers card if they go quiet.
Who can do what
• Only workspace admins can create a Widget view, for the reason forms are admin-only: it is a standing anonymous write endpoint.
• A new widget is off until somebody switches it on.
• A visitor's credential reads exactly one conversation, and only through the widget it was minted on — a token from one customer's widget can never read a thread through another's.
• An email address a visitor supplies is a delivery target and never proof of who they are, so it can't be used to read somebody else's conversation.
• Deleting the Widget view retires the endpoint on every site it is embedded on, immediately and permanently; conversations already received are untouched.