On this page
Open your browser's developer tools (Console and Network tabs) first. The widget writes problems to the console, prefixed Recent Visits.
The widget does not appear#
| Check | What it means and what to do |
|---|---|
Console says Recent Visits: invalid key | The data-key is missing or mistyped. It must look like rvk_ followed by 22 to 64 letters, digits, _ or -. Copy it again from the portal. |
| No launcher and no console message | The script did not load or did not run. Check the Network tab for widget.js (a blocked or failed request). Check the src address, an ad blocker, and that the tag is on the page. |
widget.js is blocked by the browser | Your Content-Security-Policy does not allow the script or the API address. See Security. |
| Launcher appears but the chat says "The chat is not available right now" with a Retry button | The session was refused. Usually the page's domain is not the one registered, or the integration is switched off or revoked. Compare the address in your browser with the domain in Website widget → Install (a Test key only works on the Test domain). |
| "The chat is very busy right now" or "You have reached a limit for now" | A rate limit was reached. The message says how long to wait (the real time until that limit resets). Send and Retry stay off until then, and the visitor's message is kept, so Retry sends it afterwards. |
The chat cannot start and the Network tab shows a failed request to /widget-challenge | The human check could not load. Your Content-Security-Policy must allow https://recent-visit.com in frame-src; a strict content blocker can also stop it. See Security. |
| "Your earlier conversation is no longer available" | The visitor's session changed (it expired or was cleared), so the old conversation is not theirs any more. The widget starts a new one and sends the message again by itself; nothing to fix. |
| Only some pages show it | The tag is only on some pages or layouts. In a single-page app, load the script once at the root. |
The widget looks wrong (wrong branding)#
| Symptom | Cause and fix |
|---|---|
| Default colours and name instead of mine | The page could not fetch your settings (check the Network tab for a POST …/api/widget/v1/config that returned 403), or you have not saved any. The widget still works with defaults. |
| I changed the Studio but the site did not change | Settings reach your site within about a minute. Production shows only published settings: click Publish, not only Save draft. A Test site shows the saved draft. Hard-refresh the page: the widget script is cached for up to an hour. |
| Branding differs from the Studio | Options in your page (data-config, data-accent, init({...})) override the Studio field by field. Remove the page option you do not want. |
| My logo does not show | The Studio switch Show my agency logo is off, your profile has no logo (logos are managed by Recent Visits staff), or your Content-Security-Policy blocks the image's origin in img-src. |
| I see "Test mode" in the chat | You are using the Test key. Use the Production snippet on the live site. |
The assistant gives the wrong agency or wrong content#
- The widget shows the agency that owns the key. Check that the key on this site is yours and is the right environment.
- Answers come only from your published tours, Knowledge, Saved answers, profile and reviews. If a tour is missing, publish it. If an answer is wrong, correct the Knowledge document or add a Saved answer. New documents are available within moments; an item that shows failed in Knowledge needs removing and adding again.
- The assistant says "ask the agency" when your data does not cover a question: that is intended. Add the information.
A theme or option does not apply#
- Look in the Console for
Recent Visits widget:warnings. Each says which option was ignored and why (for exampletheme.primary is not a #rgb or #rrggbb colour). - Colours must be
#rgbor#rrggbb. Names (red) andrgb(...)are ignored. - Text limits are applied silently: launcher text 30 characters, assistant name 40, header title 60, welcome message 400.
- Colours that are not readable are adjusted on purpose (see Themes); choose a deeper shade.
data-configmust be valid JSON in single quotes with double quotes inside; otherwise it is ignored with a console message.- You cannot override the widget with your own CSS: it lives in a closed Shadow DOM.
- A feature set to
truein the page still stays off if your integration does not offer it (Studio Features tab for chat, tours and quote; Behavior → Talk to a person for talking to the agency).
You can check an options object without loading the widget: resolveConfig(options) returns the warnings.
Initialisation errors#
| Message | Cause |
|---|---|
Recent Visits: invalid key | Malformed key. |
apiBase must use https (http is allowed only on localhost) | data-api-base or apiBase is http:// on a real host. Use https. |
apiBase must be a valid URL / apiBase must not contain credentials | Fix the address. |
Calling init twice does nothing | By design: it returns the existing widget. Use update to change it, or destroy first. |
Network, authentication and permission errors#
| What you see | Meaning |
|---|---|
403 from config or session | Domain not registered for this key, integration inactive or revoked, or the agency is not active. The response does not say which, deliberately. |
429 | Rate limit. The response may include retryAfter (seconds). |
| Session errors after a long idle | The client renews expired sessions itself; if a session cannot be renewed it starts a new one. |
| CORS error in the Console | Usually a 403 with no CORS header (unregistered page) or a Content-Security-Policy blocking connect-src. |
network error | The request never arrived: offline, blocked by an extension, a firewall or connect-src. |
Next.js and hydration#
- Do not call
initduring server rendering or at module top level in a server component. Use theScriptcomponent, or callinitinsideuseEffectin a client component. - A hydration warning usually comes from rendering something that differs on server and client; the widget adds its own element to
document.bodyafter load and does not touch your React tree. - In development React strict mode runs effects twice. Return
() => widget.destroy()from the effect. - With
next/script, putstrategy="afterInteractive"and render the component once.
Mobile layout#
- At 480 px and narrower the chat opens full-screen and a launcher with text shrinks to its icon.
- If the launcher collides with your own floating button, set
positionoroffset. - The panel respects the device's safe areas. If the on-screen keyboard hides the message box on some device, report it with the device and browser.
Quote requests do not appear in my portal#
| Cause | Fix |
|---|---|
| The page uses the Test key | Test quote requests are validated and then dropped. Use the Production key. |
| The request is in Leads, not Conversations | Quote requests arrive under Work → Leads with source widget. Test chats never appear anywhere. |
| The visitor did not tick the consent box | The form refuses to send; the visitor sees an error. |
| The message has fewer than 10 characters or the name is one letter | The widget or the server refuses it; ask for a few more words. |
| The same person asked about the same tour within a day | A repeat request is refused as a duplicate; the first one is already in Leads. |
| You expected the visitor's email | It stays hidden until they accept your quote (Quote requests and leads). |
Widget Studio problems#
| Symptom | Cause and fix |
|---|---|
| "Only agency owners can change the widget settings." | You are a manager; ask an owner. See the Widget Studio field reference. |
| The Register website button is disabled | The domain is empty, not valid, or the same as the saved one. |
| The preview shows a sample tour and no real replies | By design: the preview is a stand-in and sends nothing. |
| The slider says "Default (14)" for corners | The widget's real default is 16 px; move the slider to 16 if you need it exactly. |
CSS conflicts#
Your page's CSS cannot reach into the widget (closed Shadow DOM) and the widget's CSS cannot leak out. If the widget looks cut off, check for a z-index or overflow: hidden on an ancestor of <body> content, a transform on body, or another fixed-position element in the same corner (use offset or position).
Local and production differ#
| Difference | What to check |
|---|---|
| Different keys | Test and Production have different keys and domains. |
| Different settings | Test shows the draft; Production shows published. |
| Different address | A local Recent Visits server needs data-api-base="http://localhost:3000". Production does not. |
127.0.0.1 vs localhost | A Test domain registered as localhost does not accept 127.0.0.1. |
| Chats | Test chats are deleted after 7 days and never reach the inbox. |
Still stuck#
Email partners@recent-visit.com (opens in a new tab) with: your page address, which environment (Production or Test), the exact console message and the failing request from the Network tab (without any real visitor data).
Last checked against the product:
Related articles
- SDK installation · Install the Recent Visits widget with a script tag, add Subresource Integrity, run it locally, and understand the current npm status.
- SDK configuration reference · Every option the Recent Visits widget accepts: type, default, limits and an example. Invalid values are replaced by safe defaults.
- SDK security and privacy · What is public and what is secret, how sessions and the domain check protect your agency, Content-Security-Policy settings, what data the widget sends and keeps, and visitor disclosure.
Still stuck? Contact us and tell us what you tried.