Visitor Data Reference
Audience: Engineering · QA · Support · Where in app: Internal · Plan availability: All plans
The records that describe a visitor, a visit, and what they did. This is where Nox spends most of its query time, and where QA/support look when verifying "why does the dashboard say X". Field-level reference for each core record, plus the keys that connect them.
See Collections & tables for the full store catalogue and join-key cheat sheet, and Identity Graph / Session Recording for how these records get written.
UserSession (user_sessions — backend MongoDB)
One row per visit.
| Field | Type | What |
|---|---|---|
_id | ObjectId | |
company_id | ObjectId | Tenant |
widget_user_session_id | string | The kk_user_session_id from localStorage — cross-visit join key |
person_id | ObjectId | Set when verified |
claimed_person_id | ObjectId | Set when claimed but not yet verified |
verified_person_id | ObjectId | Definitive verified Person |
sessions[] | array | Page visits during this session |
lead_score | embedded | Per-component scoring totals |
products_searched[] | array | Product RAG hits |
bookings[] | array | Bookings made during this session |
contact_information | embedded | Email/phone/name captured this session |
traffic_source | embedded | UTM, referrer, source |
ip_info | embedded | IP, country, city |
device | embedded | type (desktop/mobile/tablet), browser, OS |
hubspot_contact_id | string | If linked |
ghl_contact_id | string | If linked |
notifications_sent[] | array | Notification audit |
knox.device / geo / session_date / duration / engagement / traffic_source | embedded | Stage-2 knox enrichment fields |
created_at, updated_at | Date |
VisitorProfile (visitor_profiles — ms-sessions MongoDB; mirrored to ms-ai Postgres knox_visitor_profiles)
Per-visitor cumulative rollup. Unique on (company_id, user_session_id) where user_session_id = the widget's kk_user_session_id.
| Field | What |
|---|---|
company_id, user_session_id | Tenant + widget identity |
first_seen_at, last_seen_at | Lifetime bounds |
visit_count | Total visits |
recent_sessions[] | Cap 20. Each: file_id, started_at, duration, page_trips_summary, intent, key_pages |
cumulative.active_ms | Total active time |
cumulative.unique_pages_visited | Distinct URLs |
cumulative.page_frequency | { url: count } |
recurring_topics[] | Topics across multiple visits |
recurring_friction[] | Friction patterns across visits |
intent_trajectory[] | Intent per visit (newest last) |
engagement_score | Numeric — higher = more engaged |
conversion_signals.had_chat / had_call / had_booking / shared_contact / repeat_visit_with_same_intent / intent_progression | Booleans + ints |
devices[] | Device fingerprints seen across visits |
country_code, ghl_contact_id, pipeline_stage | When known |
status | pending / narrated / failed |
narrative_summary | Selectively LLM-generated cross-visit prose |
created_at, updated_at |
Nox's
knox_visitor_profiletool reads this;devices[]is what answers "did Sarah switch devices?".
SessionAnalysis (session_analyses — ms-sessions MongoDB; mirrored to ms-ai Postgres knox_session_analyses)
One row per recording (file_id).
| Field | What |
|---|---|
file_id | PK — matches session_files._id |
company_id, user_session_id | Tenant + visitor |
started_at, ended_at, duration_ms | |
page_trips[] | Per-URL visits within the session |
clicks[] | All clicks with target, coords, dead/rage flags |
scroll[] | Per-page-trip scroll metrics |
forms[] | Per-form: fields, focus_ms, backspaces, abandoned |
hovers[], idles[], selections[], errors[] | |
viewport | dims, orientation, zoom |
intent_primary | The synthesized intent |
intent.confidence, intent.evidence[] | |
friction_points[] | rage / dead / abandoned / error / fast-back |
high_intent_signals[] | Per-tenant configurable hints |
hour_of_day, day_of_week | UTC |
device_type, country_code | Coarse buckets; NULL = unknown |
narrative_prose | Selectively LLM-generated |
action_recommendations[] | Selectively LLM-generated |
status | pending / narrating / narrated / failed |
Nox's
knox_session_analysistool reads this byfile_id.
SessionFile (session_files — ms-sessions)
Raw recording metadata.
| Field | What |
|---|---|
_id (file_id) | PK |
company_id, user_session_id | |
recording_status | active / finalized / analyzing / analyzed / failed / msai_handoff_failed |
chunks[] | S3 keys + first/last event timestamps |
first_event_at, last_event_at | |
total_events, total_bytes | |
created_at, finalized_at |
PersonProfile (person_profiles — backend MongoDB)
Per-tenant view of a Person.
| Field | What |
|---|---|
_id, person_id, company_id | |
extracted_facts[] | Each: text, importance (1..5), source, created_at |
form_submissions[] | By type: contact_info / pre_call / booking / custom |
bookings[] | Deduplicated meetings across all sources |
crm_enrichment.{hubspot_contact_id, ghl_contact_id, clearbit_id, lifecycle_stage, deals[], tags[], notes[], last_refresh_at} | Cached CRM data |
verification_signals.{ips[], subnets[], devices[], soft_sigs[], fp_hashes[]} | History of verification signals |
audit_log[] | Identity events (verified_at, claimed_by, conflicts, manual_merges) |
created_at, updated_at |
extracted_facts[]is what Nox'sknox_extracted_factstool surfaces (budgets, objections, competitors…).
Person (people — backend MongoDB)
Global identity record (cross-tenant).
| Field | What |
|---|---|
_id, name, email, phone | |
match_keys[] | sha256 of normalized email/phone — the cross-tenant match key |
first_seen_at, last_active_at |
Chat (chats — backend / ms-communication MongoDB)
| Field | What |
|---|---|
_id, company_id, user_session_id, room_id | |
agent_id, transfer_to, transferred_by | |
messages[] | Full message array |
ended_at, transcript_email_sent | |
contact_information | Captured in this chat |
fact_extraction_state | pending / queued / complete / skipped |
knox.{visitor_id, duration, turn_count, sentiment, outcome, topics_covered, questions_asked_by_visitor, agent_failed_to_answer_count, trigger_page_url} | Enrichment fields |
Call (inbound_outbound_calls — ms-communication) + knox_call_transcripts (ms-ai)
Fields on knox_call_transcripts:
| Field | What |
|---|---|
conversation_id | ElevenLabs/Ultravox conversation reference |
company_id, visitor_id | |
duration_seconds, turn_count | |
transcript (JSONB) | Turn-by-turn ({role, message}) |
topics_covered[], questions_asked_by_visitor[] | |
quality_score 0..1, quality_method (heuristic / llm_judge / skipped), quality_rationale | |
outcome, sentiment, termination_reason |
Nox reads these via
knox_call_transcripts(ranked summaries) andknox_call_transcript_full(verbatim).
Booking (bookings — backend)
| Field | What |
|---|---|
_id, company_id, user_session_id | |
booking_date, booking_time, duration_minutes | |
user_email, user_phone, full_name, business_name | |
source (google / calendly / ghl / manual), meeting_url | |
status (scheduled / completed / cancelled / no-show) | |
outcome (when filled) |
Nox reads these via
knox_recent_bookings(tenant window) andknox_visitor_bookings(one visitor).
How these connect
| Want | Path |
|---|---|
| Person → their sessions | people._id → person_profiles.person_id → user_sessions.person_id |
| Session → its recording | user_sessions.widget_user_session_id ← session_files.user_session_id (_id = file_id) |
| Recording → its analysis | session_files._id = session_analyses.file_id = knox_session_analyses.file_id |
| Session → visitor profile | (company_id, widget_user_session_id) = visitor_profiles.(company_id, user_session_id) |
| Booking → full journey | bookings.user_session_id → user_sessions |
Related
- Collections & tables — full store catalogue + join keys
- Company configuration — the tenant config that drives capture
- Identity Graph · Session Recording
- Nox tools — which tool reads which record