Skip to content

⚠️ Recent Visits is in beta. All listings and data shown are for demonstration purposes only and do not represent real or verified information. Tour listings are based on content from partner agencies’ websites and have not yet been confirmed by the agencies.

Recent Visits

SDK configuration reference

Every option the Recent Visits widget accepts: type, default, limits and an example. Invalid values are replaced by safe defaults.

On this page

Where options come from#

The widget's look and wording come from three places, strongest first:

  1. Options in your page: data-* attributes, data-config, or the object passed to init() or widget.update().
  2. Settings saved in the Widget Studio (your portal). The widget fetches them from Recent Visits when the page loads. Production shows the published settings; Test shows your draft.
  3. Built-in defaults.

Options are merged field by field: a value in your page replaces only that field, and anything you leave out falls back to the next layer. Everything is validated by the widget: an invalid value is replaced by the safe default and a warning is written to the browser console (Recent Visits widget: …). None of these options grants access to anything; the agency, its tours and what the assistant may say come from the server for your key.

Core options#

These control how the widget starts. They are available to init() (and, for the script tag, as the attributes shown).

OptionTypeDefaultRequiredDescription
key (data-key)string, rvk_…noneYesYour integration's public key. Must match rvk_ plus 22 to 64 letters, digits, _ or -; otherwise init throws Recent Visits: invalid key. It identifies your integration and is not a secret.
apiBase (data-api-base)URL stringhttps://recent-visit.comNoThe Recent Visits address. Only for staging or local development. Must be https, or http on localhost/127.0.0.1; no credentials.
storage'session' | 'memory''session'NoWhere the session and the visible chat are kept. session uses the tab's sessionStorage, so a reload or page change keeps the same conversation. memory keeps nothing across page loads. Never localStorage or cookies.
persistbooleantrue when storage is sessionNoSet false to stop saving the visible chat in the tab.
getChallengeToken() => Promise<string>noneNoRarely needed. The widget runs Recent Visits' human check itself when the server asks for it (see Security); only set this to supply the token yourself. Called after the server asks for a check, and once more with a fresh token if the first is refused.

Appearance and wording#

OptionTypeDefaultLimits and notes
appearance'light' | 'dark' | 'auto''auto'auto follows the visitor's system and changes live.
themeobjectsee ThemesColours, corner radius and font.
themeDarkobject{}Colour overrides for dark mode.
accentcolournoneLegacy shortcut for theme.primary.
position'right' | 'left''right'Which side of the screen.
offset{ x?: number, y?: number }{ x: 16, y: 16 }Distance from the screen edge in px, 0 to 200.
launcher.labelstringnone (icon only)Plain text, up to 30 characters.
launcher.sizenumber5644 to 72 px.
launcher.icon'compass' | 'chat' | 'sparkle''compass'Built-in icons.
launcher.avatarUrlURLnoneAn https image, or a small base64 PNG, JPEG or WebP.
agency.namestringyour agency name from the serverUp to 80 characters.
agency.logoUrlURLyour profile logo, if the Studio's logo switch is onhttps image or small base64 PNG, JPEG or WebP.
assistant.namestringAI Travel AssistantUp to 40 characters.
assistant.avatarUrlURLnoneAs launcher.avatarUrl. Shown in the chat header when there is no agency.logoUrl.
header.titlestringthe agency nameUp to 60 characters.
header.subtitlestringAI travel assistantUp to 80 characters.
welcomeMessagestringthe greeting set in the Studio, or a defaultUp to 400 characters.
suggestedQuestionsstring[]noneAt most 4, each up to 70 characters.
locale'en''en'English is the only supported language today.

Text options are plain text: control characters and angle brackets are removed and the text is clipped to the limit. Images must be https (or a small base64 raster image) and must be allowed by your site's Content-Security-Policy.

Features and page context#

OptionTypeDefaultDescription
features{ chat?, tours?, quote?, talkToAgency? } (booleans)all trueSet one to false to hide it. It cannot turn on a feature your integration does not offer (the Studio's Features tab decides that for chat, tours and quote; Behavior → Talk to a person decides it for talkToAgency).
pageContext.tourSlugstring (a slug)noneOn a page about one of your tours, pass its slug to get tailored suggestions. The server accepts it only if it is your published tour. A malformed slug is ignored.
pageContext.titlestringnoneUp to 100 characters. Context you choose to share; it is never scraped from the page.

Notifications and invitations#

The widget never uses browser push notifications and never asks for permission. A small invitation next to the launcher is off unless you turn it on.

OptionTypeDefaultLimits
notifications.enabledbooleanfalseMust be true to show any invitation.
notifications.welcomestring | falsePlanning a trip? Ask me anything.Up to 120 characters; false turns the welcome text off.
notifications.delayMsnumber100001,000 to 120,000.
notifications.invitationsarraynoneUp to 5 contextual invitations; first match wins. Each has text (up to 120 characters) and one of pathStartsWith, pathEquals (needs useLocation) or tourPage: true; optional delayMs.
notifications.useLocationbooleanfalseAllows path rules to read location.pathname (nothing else is read from your page).
notifications.maxPerSessionnumber10 to 3.
notifications.cooldownHoursnumber240 to 720.
notifications.dismissCooldownHoursnumber1680 to 2160; after the visitor closes it.
notifications.autoHideMsnumber150003,000 to 60,000.
notifications.showOnMobilebooleanfalseSmall screens are skipped unless true.
notifications.persist'session' | 'local' | 'none''session'Where frequency and mute state are kept (only flags and timestamps, no text).
notifications.unreadIndicatorbooleantrueA dot on the launcher for a real unread reply, never a count.

An invitation is never shown once the visitor has opened the chat, never in a background tab, and hides itself after autoHideMs.

Example#

ts
import type { InitOptions } from '@recent-visits/widget'

export const options: InitOptions = {
  key: 'rvk_AAAAAAAAAAAAAAAAAAAAAAAA',
  appearance: 'auto',
  theme: { primary: '#0b5c4a', accent: '#b45309', radius: 14 },
  position: 'right',
  launcher: { label: 'Ask our travel guide', icon: 'compass' },
  assistant: { name: 'Trek Buddy' },
  header: { title: 'Ask Alpha Treks' },
  welcomeMessage: 'Namaste! Ask me about treks and tours.',
  suggestedQuestions: ['Explore tours', 'Create my trip plan'],
  features: { talkToAgency: false },
}

As a script tag the same values go in data-config as JSON:

html
<script
  src="https://recent-visit.com/widget/1/widget.js"
  data-key="rvk_AAAAAAAAAAAAAAAAAAAAAAAA"
  data-config='{"theme":{"primary":"#0b5c4a","radius":14},"launcher":{"label":"Ask our travel guide"},"assistant":{"name":"Trek Buddy"}}'
  async
></script>

If data-config is not valid JSON the widget logs data-config is not valid JSON and was ignored and carries on.

Limits inside the chat and the quote form#

These are fixed in the built-in interface and are not options.

ItemLimit
Chat messageUp to 2,000 characters; Enter sends, Shift+Enter adds a line.
Visitor first nameOptional, up to 60 characters; anything that looks like an email, phone number or link is refused.
Quote form messageAt least 10 and at most 3,000 characters.
Quote form phone, travellersPhone up to 40 characters; travellers 1 to 50.
Tours tabShows up to 12 of your published tours.

Script tag notes#

  • apiBase must be given as data-api-base; a value inside data-config is overridden by the attribute (which is empty when absent).
  • getChallengeToken is a function and cannot be passed as JSON; use init() if you need it.
  • data-config must be a JSON object; an array or a non-object is ignored.

Last checked against the product:

  • Themes and agency branding · Colours, dark mode, corner radius, fonts, launcher and logo for the Recent Visits widget, how contrast is enforced, and what cannot be styled.
  • Widget Studio field reference · Every screen, tab, field and button of the Website widget page in the agency portal: websites and keys, settings, draft and publish, live preview, and what owners and managers can see.
  • SDK API reference · The public surface of the Recent Visits widget package: init, the widget handle, the headless client, errors, types and the HTTP endpoints they use.
  • SDK examples · Copy-and-paste integration examples for the Recent Visits widget: minimal, agency configuration, themed, Next.js, React with the package, and a headless quote request.

Still stuck? Contact us and tell us what you tried.