Receives tawk.to webhooks, stores the full message body of every chat, scrapes contact details out of what the visitor typed, and checks whether that person is already in Salesforce.
Free and ungated — this uses tawk webhooks, not the beta REST API, and needs no plan upgrade.
POST / | webhook receiver. Put this URL in tawk Admin → Webhooks. |
GET /enrich.js | agent-facing enrichment script for your website (public, no secrets) |
GET /?key=… | list of chats |
GET /?key=…&chat=<id> | one chat: full transcript, what was scraped, Salesforce match |
- In tawk: Admin → Webhooks → add a webhook pointing at this val's URL.
Subscribe to chat:transcript_created (the one carrying the message body);
chat:startandticket:createare also handled. Set a secret. - Set the env vars below.
| Key | Required | What it does |
|---|---|---|
TAWK_WEBHOOK_SECRET | yes | The secret from step 1. Requests failing HMAC are rejected with 401. |
VIEW_KEY | to read anything | Any random string. Transcripts are customer PII, so the viewer stays shut until this is set. Use letters and digits only — it goes in a URL. |
SALESFORCE_AGENT_URL | for matching | Endpoint of tribeca-salesforce-agent. Copy from tribeca-outbound-sales-call. |
SALESFORCE_AGENT_KEY | for matching | That val's API_SHARED_SECRET. |
Without the Salesforce pair, transcripts still land — matches just report error.
Add this to tribecabeverage.com above the tawk embed (tawk reads its
Tawk_API callbacks at init, so load order matters):
<script src="https://tribeca-tawk-transcripts.val.run/enrich.js"></script> <!-- your existing tawk embed goes below this -->
It hooks onChatMessageVisitor and onPrechatSubmit, scans what the visitor
types, and writes these into tawk's visitor attributes so they show in the
agent's Details panel:
| Attribute | Source |
|---|---|
visitor-phone | scraped from the visitor's own messages |
visitor-email | scraped |
mentioned-zip | scraped (phone digits stripped first so they can't be mistaken for a ZIP) |
sf-status | existing customer / existing customer - multiple accounts / no account match |
sf-account | Salesforce account name, when exactly one matched |
Values accumulate across the conversation, so a number given in message one is still on screen when an agent joins at message six.
Custom attributes need no Secure Mode — only name/email do, which is why
these use dashed custom keys.
sf-status and sf-account require a lookup the visitor's browser performs,
so /enrich-lookup cannot carry a secret. Anything it returns is readable by
anyone who finds the URL: feed it phone numbers, learn which are customers and
what those accounts are called.
That was accepted deliberately. The controls that bound it:
- phone only — Salesforce exposes no email field to this integration user
- minimal response —
known,ambiguous,account_name. Never a delivery date, address, other contact, or record id. Do not widen this. - per-IP rate limit — 15/hour (verified: 16th request returns 429)
- Origin allow-list — non-Tribeca origins get 403 (friction only; a header is trivially forged with curl)
- every call logged with IP and outcome, so abuse is visible
The clean fix, if it ever matters: tawk's REST API (beta, gated behind their
access-request form) would let this val set visitor attributes server-side, and
/enrich-lookup could then be deleted entirely.
Only visitor messages are scraped for contact details. Agents paste the
office number and support address constantly; scraping the whole transcript
would match every single chat to Tribeca itself. Verified: given a thread where
Michael pastes 973-913-4568 and info@tribecabeverage.com, the scraper returns
only the visitor's own dana@acmedeli.com / 2015550147.
Matching is by email and phone, never by name. Names aren't unique and a confident wrong match is worse than no match.
The Salesforce match here is safe because the result is only ever shown to your own team. Wiring the same lookup into a bot that tells a visitor whether an account exists would let anyone probe your customer list — type a name, learn whether that business is a customer, then get handed their address. If that capability is wanted in Apollo, it needs to match on something the real customer would know before revealing anything.
tribeca-afterhours-chat— the standalone after-hours widget (superseded if tawk's Apollo AI agent gets turned on)tribeca-salesforce-agent— the read-only SOQL proxy this queries