📨 Omnichannel — messaging & lead capture

Omnichannel brings all the ways customers reach you into one place inside TSync: web-form leads, phone calls, and messaging apps (Viber, WhatsApp, Facebook Messenger, Instagram Direct). Every message becomes a conversation attached to a lead, and every web-form or ad submission becomes a lead automatically — deduplicated, so you never get two records for the same person.

It is off by default. Nothing changes until an administrator turns it on.

Turning it on

Open Config Center → Omnichannel → Settings and choose the mode:

  • Off — completely inert. Only this Settings page exists; nothing is shown, sent or received.
  • Shadow — the console + menus appear so you can set things up safely; channels aren't live yet.
  • On — fully active. Channels send and receive.

On the same page you set the default country dial code (for Moldova use 373, for Romania 40). This makes local numbers like 069 123 456 resolve to the full international number automatically.

Meta API version (Graph). The same page carries the version used by every call to Meta — Messenger, WhatsApp, Instagram, Lead Ads and reading your own posts. It is a field (form vNN.N, for example v23.0) rather than something buried in a release, because Meta retires a version roughly two years after it appears and the calls then start failing without anything having changed on your side. There are two independent versions, and this is only one of them: each webhook field carries its own version, set in the Meta app console, which decides the shape of what Meta sends you. They can differ with no error at all — align both.

The right-click quick-action menu

Once the module is on, right-click any phone number anywhere in TSync — in a lead, a list, or a form field — and a small menu appears with:

  • WhatsApp · Viber · Telegram — opens a chat with that number in your app,
  • Call · SMS — starts a call or a text,
  • Copy number.

Right-click a document (where it's tagged for sharing) and you'll get Share (system) — which uses your device's native share sheet (great on a phone, where it can attach the actual file) — plus per-app "copy the link & open" options.

You choose which apps appear, in Settings → Quick actions.

The floating contact widget

While the right-click menu is a tool for your team, the floating contact widget is an always-visible button for your visitors and clients to reach you. It's a small round button pinned in a corner of the page; clicking it opens a fan of channel icons. It's the modern successor to the old support-contact widget.

Turn it on in Config Center → Omnichannel → Settings → Contact widget:

  • Enable widget, and choose where it shows — the client portal, the admin area, or both.
  • Set the button position (which corner of the screen) and its colour.
  • Fill in the channels you offer — WhatsApp, Viber, Telegram, Messenger, phone, e-mail. A channel button appears only when you fill in its value, so you show exactly the ways you want to be reached.

A visitor sees the round button, clicks it, and picks a channel: WhatsApp / Viber / Telegram / Messenger open a chat with you, phone starts a call, and e-mail opens a new message. It all happens on the visitor's own device — nothing is sent until they choose to contact you.

Connecting a channel (Accounts)

Go to Omnichannel → Accounts and click New. Pick the channel and fill in its details — each channel gives you a secure webhook URL to paste into the provider:

  • Tilda — for website forms. Paste the URL into Tilda → Site Settings → Forms → Webhook. Every submission arrives in the inbox as a thread; no lead is created by default — see below. After connecting the webhook, republish the pages in Tilda: the list of destinations is written into the already-published pages, so otherwise the forms keep sending only where they sent before.
  • Viber — paste your Viber Bot auth token; register the URL with Viber (set_webhook).
  • WhatsApp — Cloud API: enter the phone-number id, access token, app secret and a verify token; paste the URL + verify token into the Meta app webhook.
  • Meta Lead Ads (Facebook/Instagram ads) — enter the page id, page access token, app secret and verify token; subscribe the app's leadgen field.
  • Messenger / Instagram Direct — same Meta page fields. Two subscriptions are required, and missing the second one is the usual reason nothing arrives: subscribe the Page to the app and subscribe the app itself to the messages field (Meta app → Webhooks). The "Configure webhooks" screen verifies your callback but can leave the field list empty — if messages is not in it, Meta sends nothing at all. For comments on posts and ads, also subscribe the instagram object to comments and the Page to feed.

Each account also lets you set the default lead status, source and assignee for leads it creates.

The inbox

Omnichannel → Inbox is one list of all your conversations across every channel: who it's from, the last message, an unread badge, and a link to the lead. Filter by All / Unread, by channel, or search by name, phone or email.

Open a conversation to see the full message timeline (incoming and outgoing bubbles). For channels that support replies (Viber, WhatsApp, Messenger/Instagram) there's a reply box — you can type a message or pick a canned response and send it straight from TSync. Each lead's card also shows a compact Omnichannel timeline of that person's messages.

Pictures, voice notes and files arrive too. A photo, sticker, GIF, voice note or document sent by a customer is downloaded and kept with the conversation, so you see the image in the timeline and play the voice note without leaving TSync — on Messenger, Instagram, Viber and WhatsApp alike. The sender's name and profile picture are shown wherever the channel gives them; when it doesn't, the conversation is labelled with its channel and the tail of the sender's id — Messenger · #a1b2c3 — so two strangers never look like the same person.

Which ad paid for the conversation. If somebody wrote to you by clicking a Facebook or Instagram "send message" ad, the inbox shows the source as Messenger (ad) or Instagram (ad), and inside the conversation a From ad chip names the ad itself. That is how you tell paid traffic from organic without opening Ads Manager. Non-ad referrals (a short link, the website chat plugin) are recorded too, but deliberately not labelled as ads.

A reaction is an answer. When somebody puts a 👍 or a ❤️ on one of your messages, the conversation shows it on that message, not as a new line — so a thumbs-up on a quote is visible instead of reading as silence. If they remove the reaction it disappears here too. Only reactions on messages the inbox already holds are shown; nothing is invented for a conversation that started before the channel was connected.

Instagram stories. A reply to one of your stories is labelled Replied to your story, with a link to open the story it answers, and somebody who puts your business in their own story arrives as Mentioned you in a story — they showed you to their own followers. Those two are the most valuable events in an Instagram inbox, and they used to look like any other picture.

When a reply can't be sent, you're told why. Before your message leaves, TSync checks that the person hasn't opted out and that the channel still allows a message: on Messenger and Instagram the free window is 24 hours from their last message to you. Past it, a reply you typed still goes out under Meta's allowance for human answers (up to 7 days). Past that, or on a channel with no such allowance (a free-form WhatsApp message), the send stops with a plain reason instead of a provider error code — use an approved template instead.

Deleting a conversation. Spam, a mis-routed message or your own test rows can be removed: open the conversation and press Delete conversation. The messages and their files are gone for good. The contact and any lead stay — a conversation is evidence, a lead is a commercial record, and removing the first must never quietly take the second. The confirmation says exactly that before you press it.

Replying with tappable buttons

Under the reply box there is a collapsed Quick replies (optional) panel. Open it, press + for each answer you want to offer and type a short label (up to 20 characters). Send as usual, and those labels appear under your message as buttons the customer can tap instead of typing.

It is worth doing whenever the answer is one of a few known options — Yes / No / Call me back. A tap cannot be misspelled, and it tells you something a typed word cannot: a tapped answer is marked tapped in the conversation, so the "Yes" somebody chose never looks like the "Yes" they happened to type.

Leave the panel closed and your reply goes out exactly as before. An empty row is ignored.

Not every channel carries everything, and you are told when something was left out. WhatsApp allows at most three buttons; Instagram shows them only in the phone app; Telegram will not accept two kinds of keyboard at once. TSync fits the message to the channel and then reports the difference — "2 element(s) were not supported on this channel and were left out". This matters because a message can be sent successfully and still arrive without its buttons, which is precisely the case you would otherwise never discover. A label that is too long is shortened rather than dropped: a shorter button still works, while a missing one breaks the answer that referred to it.

You can also send a picture or a file with no text at all — a photo without a caption is a normal thing to send, and it now goes through.

Which message a reply refers to

When somebody answers one specific message — using the reply gesture in the Messenger app, say — the conversation shows In reply to with a quote of the original above their words. On a thread with several open questions that is the only way to tell which one was answered: the link cannot be reconstructed afterwards from the timing or the order of the messages.

If the original is older than the part of the conversation on screen, it says In reply to an earlier message rather than showing nothing — so a reply always looks like a reply, even when the quote itself cannot be resolved. A message that arrives while you are watching the conversation shows its quote straight away; you no longer have to reload the page to see what it answered.

Answering one specific message

You can do the same from your side. Point at the customer's message and press the reply arrow beside the bubble — Reply to this message. A Replying to strip appears above the reply box with the text you are answering; write your answer and send as usual, and the customer sees it attached to that message, exactly as if you had used the reply gesture in their own app. Press on the strip to go back to answering the conversation as a whole.

Use it whenever a thread has drifted across several topics: "yes, that one is in stock" means nothing three questions later.

Messenger, Instagram, WhatsApp and Telegram carry it. On Viber the send is refused with a plain reason, rather than arriving detached from the message it was meant to answer.

One small thing that went away with it: sending a reply no longer raises the browser's "Leave site? Changes that you made may not be saved" dialog. It used to appear on every single send, and pressing Cancel threw the message away.

Sending a file from your computer

Under the reply box there is Attach a file. Choose an image, video, audio clip, PDF or Office document up to 25 MB, add a message if you want, and send it with the reply.

The file is never published. It is uploaded from your server straight to the platform, so there is no public web address anybody with the link could open. That distinction matters the day you send a signed contract instead of a product photo. What may be sent is a fixed list of file types, and the type is read from the content of the file, not from its name.

Today only Messenger and Instagram can send a file from your computer. On Telegram, WhatsApp and Viber the send is refused with a sentence saying so — instead of sending your text and quietly losing the file.

If a file fails a check, nothing is sent at all: you fix it and press Send again. And if your server refuses an upload before TSync ever sees it (a common limit is well under 25 MB), you are told that too — "nothing happened" is the worst possible answer to pressing Send with a 30 MB file.

When a message becomes a lead

By default, it does not. A message, a comment or a submitted form arrives in the inbox as a thread, and a lead is created only once you decide it is a real customer — with the Create lead button on the thread.

The reason is simple: not every message is a qualified request. A phone number left in a "call me back" bar, a question under a comment, a "hello" on Messenger — these are conversations, not customers. If each one became a lead automatically, the pipeline would fill with records nobody vetted, and your sales figures would stop meaning anything.

Nothing is lost: the thread is kept in full, with the messages, the phone number and whatever was filled in. You can search it, reply from it, and promote it at any point later.

If qualification happens before things reach the system in your setup — a bot that only forwards pre-filtered requests, say — tick the box on that account under Omnichannel → Accounts:

  • Create a lead for every form submission (Tilda),
  • Create a lead for every chat (Messenger, Instagram, Viber, WhatsApp),
  • Create a lead for every commenter (Facebook/Instagram comments).

Each channel has its own switch, so you can leave comments as a journal while turning every form into a lead.

Phone calls in the inbox

If you use the Moldcell PBX connector, calls show up here too: each call becomes an entry on the contact's conversation with the direction, duration, status and — when there's one — an inline audio player for the recording. An incoming call from an unknown number can open a new lead automatically.

Comments on Facebook and Instagram posts

Comments under your posts and ads land in the inbox as conversations, just like direct messages — but they get there by being fetched, not by Meta pushing them to you. Meta does not deliver comment notifications until your app has passed Advanced Access review, while reading comments works from day one. So TSync fetches them.

A Scheduler job, Comment poll (Facebook / Instagram) (omni.comment_poll, every 15 minutes by default), looks at your recent posts and files any new comment. It is bounded on purpose, so one busy page can never crowd out the others: the 10 most recent posts per account, published within the last 30 days, and at most 300 comments per run. Your own replies are recognised and never filed as customer messages, and a comment already in the inbox is never filed twice — so it makes no difference if the job runs again.

You'll find it in the Scheduler (Scheduler in the sidebar), where you can also run it by hand with Run now. It needs the pages_read_user_content permission on your Meta app. If comment webhooks are approved for you later, they take over automatically and this job stays on as a safety net for the delivery gaps webhooks quietly have.

Answering a commenter privately

A public comment can be turned into a private conversation. Open the comment in the inbox and use Private reply: the person receives your message in Messenger or Instagram Direct, and the thread continues normally if they answer. Meta allows exactly one private reply per comment, within 7 days — the confirmation says so, because it cannot be undone or repeated.

It can also happen by itself. On Omnichannel → Keyword replies, tick Answer new comments privately, automatically. From there:

  • a comment that matches one of your keyword rules gets that rule's answer — somebody who writes "price" receives the price list, somebody who writes "demo" receives the booking link;
  • the Automatic private reply text below is what everybody else receives;
  • leave that text empty and only the people whose comment matched a rule are answered. That is the quieter setting, and usually the right one: a private message to someone who merely wrote "nice" is unsolicited in a way an answer to "price" is not.

It is off until you switch it on, one reply per commenter is enforced, only comments that came in are answered, and a failure here never costs you the comment itself.

Entry points — links that remember where they came from

Omnichannel → Entry points builds a link (and a QR code) that starts a conversation with you, and tags it with the campaign it came from. Put the same tag on every place you publish the link — a poster, an ad, a newsletter — and the inbox will tell you which one people actually used.

You choose where the link opens, the page/account/number it opens, and a campaign tag. Nothing is saved: the page just builds the link, and you copy it or print the QR code.

The four channels do not behave the same, and the screen says so on every link:

Opens in The tag Worth knowing
Messenger travels invisibly
Instagram travels invisibly only on a phone — on a computer the tag is lost
WhatsApp there is no hidden tag it goes into the message the person sends, so they can see and edit it
Telegram travels invisibly accepts fewer characters, so a long tag may be shortened

If your tag has to be changed to fit a channel — spaces become hyphens, unusual characters are removed — the page tells you the new tag. That matters: once a link is on a poster, a tag that quietly changed shape no longer matches the one you are looking for in reports.

Field mapping (optional)

Omnichannel → Field mapping lets you decide exactly how a form's fields become lead data. As leads arrive, TSync learns the field names a form sends; open the profile and map each one to a lead field (name, email, phone, company, …) or a lead custom field. Anything you don't map still lands in the lead notes. This is optional — without it, TSync detects name/phone/email automatically.

Routing rules (optional)

Omnichannel → Routing rules send incoming leads to the right place automatically. A rule matches by channel + form / UTM source / UTM campaign / ad id and then sets the lead's status (pipeline), source, assignee and tags. The highest-priority active rule wins; a rule with no conditions is a catch-all. Rules override the account defaults — e.g. "leads from the Google campaign → status Hot, assigned to Ana, tag google."

Canned responses

Omnichannel → Canned responses is your library of reusable quick replies (title + message, optionally scoped to one channel). They appear in a dropdown above the reply box so your team answers fast and consistently.

Automatic replies (keyword replies)

Omnichannel → Keyword replies lets the inbox answer by itself. Someone writes "price" at 22:40 and gets your answer straight away, instead of the next morning when a colleague opens the inbox.

It is deliberately simple: one incoming message, one prepared answer. No branching bot conversations — just the questions you already answer ten times a day.

A rule is a set of keywords plus the answer to send:

  • Matchis exactly · contains · contains the whole word · starts with · is a thumbs-up · contains none of.
  • Keywords — up to ten, separated by commas. Accents are ignored, so pret also matches preț and you never have to type both spellings of a word. (Russian is matched letter for letter, where accents carry meaning.)
  • Answer with — either text you type, or one of your saved canned responses.
  • Channel — one channel, or all of them.
  • Priority — the lowest number is checked first. The first rule that matches replies, and only one reply is ever sent.

A default reply at the bottom of the same page answers anything no rule matched — useful for "thank you, we've received your message and answer between 9:00 and 18:00." Switch it off, or leave its text empty, and nothing is sent.

The safety rails

These are not settings you have to find — they are how the feature behaves:

  • It is off until you switch it on. Upgrading never makes your install start talking to customers on its own. When automatic replying is off, the rules page says so at the top instead of quietly doing nothing.
  • It never answers twice in a row. Five messages in a row get one answer. You set the wait between two automatic replies to the same person — 5 minutes by default, anywhere from 1 to 240.
  • It only ever answers an incoming message. An outgoing message never triggers a reply, so two systems can't talk each other into a loop. A public comment is answered only through Answer new comments privately above — a separate switch, off by default — and never with a public reply under the post.
  • It stays inside the messaging rules. An automatic reply goes out inside the ordinary 24-hour window, which is open by definition since it answers a message that has just arrived. TSync never uses Meta's "human agent" allowance for automation — that one is reserved for text a person typed.
  • An automatic reply is marked as automatic in the conversation, so you can always tell it from an answer your team wrote.

A rule with no keywords never matches anything — including under contains none of, where it would otherwise answer every message ever sent.

Ice breakers & menu (Messenger and Instagram)

Omnichannel → Ice breakers & menu sets what a person sees before they type anything.

  • Ice breakers — up to four questions offered on a conversation with no history: "What are your prices?", "Where are you?", "I want an offer". Somebody who has never written to you gets a choice instead of an empty box, which is the difference between a conversation and a page they close.
  • Persistent menu — up to three entries always available under the composer. Each one either sends a message or opens a link (https only).

A tap arrives in the inbox as a normal message whose text is the question the customer saw, so your keyword rules answer it exactly as they answer a typed question — and you read the same words they pressed.

This is set per Page. A company with two Pages publishes different questions on each; there is no single global list.

Saving and publishing are two different things. Save keeps a draft — nothing changes for your customers. Publish to the Page is what puts it in front of them. Under the form, What Meta actually holds is read back from Meta after each publish, so you see what is live rather than what you typed. If Meta cannot be reached, that section says unknown rather than showing an empty list.

Reports — measuring the inbox

Three Omnichannel reports register themselves in Reports (the platform reports console), so they inherit everything reports there can do: filters, columns, export to XLSX/CSV, charts, and e-mail schedules.

Report Answers
Omnichannel — conversation volume new conversations and messages per day and channel, with the share sent automatically shown separately from what a person typed
Omnichannel — time to first answer per conversation: when the customer first wrote, when somebody answered, and how long they waited
Omnichannel — where conversations came from conversations grouped by the ref tag or ad that started them, and how many became leads

Two things are deliberate and worth knowing when you read the numbers. An unanswered conversation has no duration at all — not a zero, which would read as "answered instantly" and quietly improve your average. And a conversation that carries no attribution is counted as such, rather than dropped from the report: otherwise the entry-point table would flatter whichever campaign happened to be tagged.

The reports appear only while Omnichannel is on, and they respect the same permission as the inbox.

WhatsApp templates — the only way to write first

On a real WhatsApp number you cannot simply start a conversation. Free text needs a customer who wrote to you in the last 24 hours; outside that window WhatsApp accepts nothing but a template Meta has reviewed and approved. So "which templates do I have, and are they approved" is not a detail — it is the complete list of openings your business has.

Omnichannel → WhatsApp templates answers it. The list shows each template with its language, its real status at MetaAPPROVED · PENDING · REJECTED — and, when it was refused, Meta's own reason, which is the one sentence that tells you what to change.

Creating one

New template builds all three languages from a single form:

  • Name — lowercase letters, digits and underscores. One name carries all three language versions.
  • CategoryUTILITY means "about an existing request or order". Meta re-classifies what you submit and refuses a mismatch, so keep the wording transactional. A body containing something like nr. {{2}} can be read as an authentication code and refused before you ever use it.
  • Message — write it with {{1}}, {{2}} where the values go. A variable may not open or close the message.
  • Sample values — one per variable. Meta reviews the rendered message, not the skeleton. Invent them: they travel to Meta, so never use a real customer's name or number.

A language left empty is simply not created, and each language gets its own verdict — Romanian approved while English is refused for wording is an ordinary outcome, and a single joint "done" would hide it. Answers usually come back within minutes.

Doing this here rather than in Meta's console is deliberate: that editor auto-closes braces (typing {{1}} produces {{1}}1}}), its example inputs look like their own labels so sample text lands inside the message, and the wizard has to be walked once per language.

Using an approved template

Import the approved ones copies what Meta has approved into your local library, so nobody has to retype a name that must match exactly — a single typo answers "no template" at send time and explains nothing further. Only APPROVED ones are imported (a pending one is a name that fails when used), and re-running refreshes rather than duplicates.

From then on the template can be sent:

  • to one person, from the conversation. When more than 24 hours have passed since their last message, the thread offers Send an approved template: pick one, fill in the values for {{1}}, {{2}}, send. Their reply reopens the free window. Without those values Meta delivers the placeholder literally and the customer reads "Bună ziua, {{1}}" — so they are asked for, not optional;
  • to a segment, through Campaigns (the section below).

The control appears only when it is both needed and possible — the window is closed and at least one approved template exists. While free text still works it is faster, free and reads like a person wrote it.

Campaigns (compliant broadcast)

Omnichannel → Campaigns sends a message to a segment of your contacts on a messaging channel — controlled and compliant:

  • You pick the channel, the message (or a canned one), a segment (e.g. a lead status) and a throttle (messages per minute).
  • Build recipients creates the list and checks each one: anyone who opted out is skipped; for a free-form message, only contacts inside the 24-hour window (since their last message to you) are eligible; a template message needs an explicit opt-in.
  • Start sends in throttled batches — automatically each minute (via the Scheduler job omni.campaign_dispatch) or immediately with Send a batch now.
  • Every recipient is checked again at the moment of sending, not only when the list was built. The 24-hour window is a moving deadline, so a campaign prepared today and sent tomorrow does not write to someone whose window closed in between — nor to anyone who opted out after the list was made.
  • The delivery report shows total / pending / sent / delivered / read / failed / skipped (with the reason). Someone the rules excluded at send time is reported as skipped, never as failed: nothing was attempted, and Retry failed must not push them back into the queue.

Consent & opt-out. An incoming message counts as opt-in; if someone replies STOP (or unsubscribe / dezabonare / отписаться) they are opted out and never messaged again. This keeps your outreach within WhatsApp/Viber rules.

Event log — see what arrived, and recover what failed

Omnichannel → Event log lists every event a provider delivered to you: which channel, what type, whether it was processed — and, when something went wrong, the exact error.

This page exists because of one hard fact: a provider does not send a message twice. To keep Facebook, Viber or WhatsApp from retrying in a storm, TSync confirms receipt immediately. If the message then failed to be filed (a temporary database problem, a mis-configured account), it used to be gone for good — and you would never know a customer had written to you.

Now every event is stored, so you can bring it back:

  1. Open Omnichannel → Event log and click the Failed filter (the Health page also warns you when something failed in the last 24 hours).
  2. Click an event to read the error and see exactly what the provider sent.
  3. Fix the cause, then press Replay — the message is processed again and appears in the inbox as normal. Replay all does the whole failed queue at once.

Replaying an already-processed event would file the message a second time, so it is blocked by default. If you are sure the first attempt did not actually store anything, you can force it from the event page, with a confirmation.

Events received before you upgraded to this version were not stored and cannot be replayed — the page says so rather than pretending otherwise.

Keeping the list tidy. A daily job deletes settled events (processed, skipped, rejected) older than the retention window you set at the bottom of the page (90 days by default). Failed and still-pending events are never deleted automatically — those are the ones that still need you.

Security

Everything that comes in from a channel is treated as untrusted data — validated and mapped, never executed. Each webhook is authenticated (a secret token in the URL, plus the provider's signature where one exists) and is idempotent, so a provider retry never creates duplicates. All actions are audited.