Documentation

Percepto installs in 60 seconds. Paste one script tag, configure your client ID, and Percepto handles the rest - visitor scoring, voice conversation, lead capture, and CRM sync.

Installation

Paste this script tag before the closing </body> tag on any page where you want Percepto active.

Your API endpoint: https://api.perceptoai.com
Replace your_client_id with the client ID from your Percepto dashboard.

B2B — converts visitors into demo bookings

<!-- Paste before </body> --> <script src="https://api.perceptoai.com/widget/scout.js" data-scout-api="https://api.perceptoai.com" data-scout-mode="b2b" data-scout-client-id="your_client_id" data-scout-sitemap='{"demo":"/demo","pricing":"/pricing","features":"/features"}' data-scout-trigger="delay" data-scout-delay="5000" async></script>

B2C — converts visitors into purchases

<script src="https://api.perceptoai.com/widget/scout.js" data-scout-api="https://api.perceptoai.com" data-scout-mode="b2c" data-scout-client-id="your_client_id" data-scout-sitemap='{"shop":"/shop","checkout":"/checkout","pricing":"/pricing"}' data-scout-trigger="delay" data-scout-delay="8000" async></script>

That is it. Percepto will automatically score the visitor, speak a personalised opening line, and handle the conversation.

B2B vs B2C mode

The data-scout-mode attribute controls Scout's goal and conversation strategy:

ModeGoalCTA Percepto works toward
b2bBook a demo callCalendar booking link
b2cDrive purchaseShop / checkout page

Percepto auto-detects enterprise vs SMB within B2B mode from conversation signals - compliance questions, team size, budget language. You never need to configure this. Use flow_override in your client config to hard-set if needed.

Widget attributes

All configuration is passed as data- attributes on the script tag. No JavaScript required.

Attribute Default Description
data-scout-api required Your Percepto API endpoint. E.g. https://api.perceptoai.com
data-scout-mode "b2b" Conversation mode: "b2b" (demo booking) or "b2c" (purchase).
data-scout-client-id required Your unique client ID from the Percepto dashboard. Determines which voice, prompts, and CRM config are used.
data-scout-input "voice" Input mode: "voice" (microphone) or "chat" (typed text).
data-scout-trigger "delay" When Scout activates: "delay" (after N ms) or "manual" (call window.__scout.open()).
data-scout-delay "5000" Milliseconds before Percepto auto-opens when trigger="delay". Set "0" for immediate.
data-scout-sitemap "{}" JSON map of page labels to URLs Percepto can navigate to. Used for CTA navigation actions. See Sitemap config.

Trigger modes

Delay trigger (recommended)

Scout opens automatically after the visitor has been on the page for data-scout-delay milliseconds. Best for most sites — gives the visitor a moment to orient before Scout speaks.

<!-- Open 5 seconds after page load --> data-scout-trigger="delay" data-scout-delay="5000" <!-- Open immediately --> data-scout-trigger="delay" data-scout-delay="0"

Manual trigger

Scout loads silently and waits. Call window.__scout.open() from your own code — useful for button clicks, exit-intent, or scroll triggers.

<!-- Widget tag --> data-scout-trigger="manual" // Open Percepto when the user clicks a button document.getElementById('talk-to-scout').addEventListener('click', () => { if (window.__scout && typeof window.__scout.open === 'function') { window.__scout.open(); } });

Sitemap config

data-scout-sitemap is a JSON map that tells Scout which pages it can navigate a visitor to. When Scout decides it's time to move a visitor to the demo page or checkout, it returns an action: "navigate" with the URL from this map.

<!-- B2B sitemap example --> data-scout-sitemap='{"demo":"/book-demo","pricing":"/pricing","features":"/features","case-studies":"/customers"}' <!-- B2C sitemap example --> data-scout-sitemap='{"shop":"/shop","product":"/products/main","checkout":"/cart","pricing":"/pricing"}'

Keys are human-readable labels Percepto references in its reasoning. Values are absolute URL paths on your site. At minimum include your primary CTA destination ("demo" for B2B, "shop" or "checkout" for B2C).

Percepto is built for GDPR, DPDP (India), and UAE PDPL compliance. The widget checks for consent before collecting any visitor data.

How consent works

Scout reads localStorage.getItem('scout_consent') before running:

Adding a consent banner to your site

You must show a consent banner before Percepto activates. Set consent in localStorage from your banner's Accept/Decline buttons:

// On Accept: localStorage.setItem('scout_consent', 'accepted'); window.__scoutConsent = true; // On Decline: localStorage.setItem('scout_consent', 'rejected'); window.__scoutConsent = false;
Percepto's prelaunch and product pages include a GDPR/DPDP/UAE PDPL-compliant consent banner you can copy from /prelaunch. See Privacy Policy and Terms of Service for the full legal framework.

GET /health

GET /health

Returns service status. Use for uptime monitoring and pre-deploy smoke tests.

Response

{ "status": "ok", "routes": 14 }

POST /intelligence/score

POST /intelligence/score

Scores a visitor's intent from browser and IP signals, then returns a personalised opening line. Called automatically by the widget on every page load.

Request body

FieldTypeDescription
visitor_idstring requiredFirst-party cookie value (_scout_vid, format: sv_<random><ts>)
modestring required"b2b" or "b2c"
landing_pagestring optionalCurrent page path, e.g. "/pricing"
referrerstring optionalHTTP Referer header value
utm_sourcestring optionalUTM source from query string
utm_campaignstring optionalUTM campaign from query string
browser_localestring optionale.g. "en-US"
device_typestring optional"desktop", "mobile", or "tablet"
hour_of_dayinteger optional0–23 in visitor's local time
day_of_weekinteger optional0=Monday … 6=Sunday
client_idstring optionalYour client ID — enables per-client voice and prompt config

Response

{ "intent_level": "high", // "high" | "medium" | "low" "segment_lean": "enterprise", // "enterprise" | "smb" | "consumer" "visitor_type": "returning", // "new" | "returning" | "hot_lead" "opening_strategy": "direct", // "direct" | "warm" | "curious" "opening_line": "Back again — I noticed you checked our pricing page. Ready to talk specifics?", "intro_line": "Hi, I'm Percepto.", "context_summary": "Returning visitor from Stripe in San Francisco, high intent, 3rd visit." }

POST /session/start

POST /session/start

Creates a conversation session in Redis, seeded with the visitor's intent context and opening line. Returns a session_id used for all subsequent turns.

Request body

FieldTypeDescription
visitor_idstring requiredMust match the visitor_id used in /intelligence/score
client_idstring requiredYour client ID
modestring required"b2b" or "b2c"
opening_linestring optionalOpening line returned by /intelligence/score
context_summarystring optionalContext summary returned by /intelligence/score
intent_levelstring optionalIntent level from /intelligence/score
visitor_typestring optionalVisitor type from /intelligence/score
opening_strategystring optionalOpening strategy from /intelligence/score

Response

{ "session_id": "sess_a1b2c3d4e5f6" }

POST /conversation/turn

POST /conversation/turn

Processes one conversation turn. Accepts the visitor's message (text or transcribed speech), returns Percepto's reply and optional navigation action. Percepto selects enterprise or SMB flow automatically based on conversation signals.

Request body

FieldTypeDescription
session_idstring requiredSession ID returned by /session/start
messagestring requiredVisitor's message text (plain text or speech transcript)

Response

{ "reply": "Got it — sounds like your team is evaluating demo booking tools for your sales process. What does your current SDR workflow look like?", "action": "navigate", // null | "navigate" | "book_demo" | "show_calendar" "nav_target": "demo", // key from your sitemap config "nav_url": "/book-demo", // resolved URL from sitemap "intent_signal": "high" // updated intent assessment for this turn }
When action is "navigate", the widget automatically navigates the visitor to nav_url after reading the reply. No extra code needed — it's handled by scout.js.

POST /voice/transcribe

POST /voice/transcribe

Accepts audio chunks from the browser (WebM/WAV format), transcribes using Groq Whisper, extracts voice signals via librosa, and returns the transcript. Called automatically by the widget when input mode is "voice".

Request

Multipart form data with an audio field containing the audio file (WebM or WAV).

Response

{ "transcript": "We have a team of about twenty salespeople and we're looking to automate the demo booking process", "avg_energy": 0.042, "pitch_variance": 18.3, "speech_rate_wpm": 142, "voiced_ratio": 0.78 }

POST /voice/speak

POST /voice/speak

Converts text to speech using ElevenLabs and streams audio back. Uses the per-client voice_id stored in Supabase (configured during onboarding).

Request body

FieldTypeDescription
textstring requiredText to synthesise
client_idstring optionalUses per-client voice ID if provided

Returns an audio stream (audio/mpeg). The widget plays it directly in the browser.


Slack alerts

Percepto fires a Slack alert when a high-intent visitor is detected (or on every session, depending on your config). Set these two environment variables on your Percepto backend:

SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T.../B.../... SLACK_ALERT_MODE=hot_lead # "hot_lead" = high-intent only | "all" = every session

Get a Webhook URL from your Slack App settings → Incoming Webhooks. Percepto sends a rich message with visitor company, intent level, page, and a Claim link for human handoff.

HubSpot & Salesforce

Percepto pushes a lead summary to your CRM automatically at the end of each high-intent conversation. Configure during onboarding or via the dashboard:

CRM push is included in the Growth plan and above.

Content crawl (RAG)

Percepto crawls your website and indexes your content into a vector store so its answers are grounded in your actual product, pricing, and case studies.

# Trigger a crawl via API curl -X POST https://api.perceptoai.com/rag/crawl \ -H "Content-Type: application/json" \ -d '{"url":"https://your-site.com","client_id":"your_client_id"}'

Crawls are also triggered automatically when you update your website URL in the dashboard. Content is chunked, embedded, and stored in Supabase pgvector under your client ID.


Visitor signals

Percepto collects 15+ signals before the first word is spoken. These power the intent score and personalised opening line.

// Signals sent to /intelligence/score on every page load { "visitor_id": "sv_abc123def456", // first-party cookie (_scout_vid), 365-day TTL "landing_page": "/pricing", "referrer": "https://google.com", "utm_source": "linkedin", "utm_campaign": "q1-outbound", "browser_locale": "en-US", "device_type": "desktop", "hour_of_day": 14, // visitor's local time, 0–23 "day_of_week": 1, // 0=Mon … 6=Sun "mode": "b2b" }

IP intelligence

The backend enriches every request with IP-derived data — company name, city, and country — via ip-api.com (1,000 req/day free, no key needed). This lets Percepto open with "I see you're coming from Stripe in San Francisco" when confidence is high.

Returning visitor memory

Visit history is stored in Upstash Redis under visitor:{visitor_id} with a 30-day TTL. On each return, Percepto reads the previous intent level and last page, then adjusts tone — warmer for cold returners, more direct for high-intent ones.

Conversation flows

Percepto uses two pre-built conversation flows that reduce LLM calls for predictable paths. Flow selection is automatic — based on signals detected in real-time:

Enterprise flow

Triggered when Percepto detects: compliance questions, large team mentions, multi-stakeholder language, procurement signals, or long evaluation timelines.

SMB flow

Default for smaller teams and individual buyers.

Hard-override the flow for a specific client by setting flow_override: "enterprise" | "smb" in their client config in Supabase. Percepto will skip auto-detection and use the specified flow.

Troubleshooting

Percepto doesn't appear on my site

Check in order:

  1. Open browser DevTools → Console. Look for errors from scout.js.
  2. Check that data-scout-api is set and the URL is reachable. Test: curl https://your-api/health.
  3. Check localStorage.getItem('scout_consent') in the browser console. If it's 'rejected' or null, Scout won't load. Either show a consent banner or set it to 'accepted' for testing.
  4. Confirm data-scout-client-id matches a client record in Supabase.
  5. If data-scout-trigger="delay", wait for data-scout-delay ms after page load.

Percepto loads but voice doesn't work

  1. Check that the browser has been granted microphone permission.
  2. Ensure ELEVENLABS_API_KEY is set on your backend and the client has a voice_id configured.
  3. Try data-scout-input="chat" to confirm the conversation loop works without voice.

Percepto replies don't mention my product

Run a content crawl so Percepto's answers are grounded in your actual site. See Content crawl (RAG).

CRM push isn't working

Verify your HubSpot token or Salesforce OAuth credentials in the Percepto dashboard. CRM push requires the Growth plan or above. Check the /crm/summaries/{client_id} endpoint to confirm summaries are being generated.

Testing without real visitors

Use the Percepto test page at /test on your backend. It loads Percepto with trigger=immediate and client_id=demo so you can have a full conversation without any real traffic.

Note: For local testing, set localStorage.setItem('scout_consent', 'accepted') in your browser console first — Scout won't run without consent, even locally.