Visitor and customer analytics
Metrics, funnel, traffic sources, conversation topics, and each customer's timeline.
Nevox brings together two things that usually live apart: who visits your site or app and what those people talk about with the agent. That lets you answer questions like:
- Where do the visitors who become leads come from?
- How many visitors open the chat, how many start a conversation, and how many book?
- What do people ask most, and what couldn't the agent answer?
- What path did a specific customer take before closing?
The same numbers show up in Dashboard → Analytics. The API lets you bring this data into your own dashboard, spreadsheet, or BI tool.
For site visitors to show up, turn on tracking. Conversations from every channel are measured automatically.
Definitions
| Term | What it counts |
|---|---|
| Visitor | A unique browser or device in the period |
| Session | One visit. It ends after 30 minutes of inactivity. |
| Pageview | Each page opened, including route changes in single-page apps |
| Chat open | The visitor opened the widget |
| Conversation | A conversation with at least one customer message, on any channel |
| Lead | A contact who left a phone number or email, or who answered the agent's qualifying questions |
| Appointment requested | The agent booked a time slot through the Nevox calendar |
| Handoff | The conversation went to your team |
| Resolved by the agent | A conversation that was not handed off to your team (resolution_rate = 1 − handoffs ÷ conversations) |
| Conversion | An event you marked as a conversion in the dashboard (e.g. consultation_paid), sent from your site or your server |
Common parameters
All analytics endpoints use the analytics:read scope and accept:
| Parameter | Description |
|---|---|
from, to | Dates in YYYY-MM-DD, inclusive. Default: last 30 days. |
timezone | IANA time zone (e.g. America/New_York). Default: the account's time zone. |
agent_id | Filters conversations by agent (API and widget conversations; channel conversations follow the channel's agent) |
channel | widget, api, whatsapp, site, sms, voice |
compare | previous_period also returns the previous period of the same length |
filters | Filters on visitor dimensions, e.g. filters=device:mobile;utm_source:google |
The maximum period per query is 366 days and is subject to your plan's retention (Pro: 90 days; Ultimate: 13 months).
Overview
GET /v1/analytics/overview
curl "https://api.nevox.ai/v1/analytics/overview?from=2026-10-01&to=2026-10-31&compare=previous_period" \
-H "Authorization: Bearer $NEVOX_API_KEY"{
"period": { "from": "2026-10-01", "to": "2026-10-31", "timezone": "America/New_York" },
"metrics": {
"visitors": 8420,
"sessions": 11903,
"pageviews": 30117,
"widget_opens": 1210,
"conversations": 964,
"leads": 311,
"appointments_requested": 142,
"handoffs": 88,
"conversions": 61,
"conversion_value": 543900,
"resolution_rate": 0.91,
"avg_first_response_seconds": 3.2,
"unanswered_questions": 37,
"feedback_incorrect": 9
},
"previous": {
"visitors": 7105,
"conversations": 802,
"leads": 240
},
"currency": "USD"
}conversion_value is the sum of the value of conversion events, in cents.
Time series
GET /v1/analytics/timeseries?metric=conversations&interval=day
| Parameter | Values |
|---|---|
metric | Any overview metric. Separate multiple metrics with commas. |
interval | hour (max. 7 days), day, week, month |
{
"interval": "day",
"data": [
{ "date": "2026-10-01", "conversations": 28, "leads": 9 },
{ "date": "2026-10-02", "conversations": 35, "leads": 12 }
]
}Breakdown by dimension
GET /v1/analytics/breakdown?dimension=utm_source&metrics=visitors,leads,conversions&limit=10
| Dimension | Example |
|---|---|
source | direct, organic_search, paid_search, social, referral, email, whatsapp_link |
referrer_domain | google.com, instagram.com |
utm_source, utm_medium, utm_campaign, utm_content, utm_term | UTM parameters from the visitor's first visit in the period |
landing_page, page | Page path (/pricing) |
device, browser, os | mobile, Chrome, iOS |
country, region, city | Derived from the IP address, which is then discarded |
language | Browser or contact language |
channel, agent_id | The conversation's channel and agent |
handoff_reason | Reason for the handoff to a human |
topic | Conversation topic, classified by AI (conversations without a topic yet show up as (none)) |
conversion_name | Conversion event name |
contact_tag (coming soon) | Contact tags |
{
"dimension": "utm_source",
"data": [
{ "value": "google", "visitors": 3120, "leads": 140, "conversions": 31 },
{ "value": "instagram", "visitors": 2210, "leads": 96, "conversions": 14 },
{ "value": "(none)", "visitors": 2004, "leads": 51, "conversions": 12 }
]
}Funnel
GET /v1/analytics/funnel
The default funnel shows how many site or app visitors (measured by tracking) went through each step and all the previous ones in the period:
{
"steps": [
{ "step": "visited", "count": 8420, "rate_from_previous": null },
{ "step": "opened_chat", "count": 1210, "rate_from_previous": 0.144 },
{ "step": "conversed", "count": 690, "rate_from_previous": 0.570 },
{ "step": "lead", "count": 311, "rate_from_previous": 0.451 },
{ "step": "converted", "count": 61, "rate_from_previous": 0.196 }
]
}Pass steps=visited,opened_chat,lead,conversion:consultation_paid to build your own funnel (up to 8 steps). Use conversion:<name> for steps based on your events.
Topics and gaps
GET /v1/analytics/topics
The AI gives each conversation a short topic, and the list groups conversations by topic, with how many the agent resolved without handing off to your team. It also lists the questions the agent couldn't answer (conversations that went to your team for lack of information), grouping together questions worded differently. This is your priority list for teaching the agent.
- The topic is assigned once, half an hour after the conversation's last message, and reuses the topics you already have.
- Only live-environment conversations get a topic: with a test key,
topicscomes back empty. limit(1 to 100, default 20) applies to both lists.
{
"topics": [
{ "topic": "Rescheduling an appointment", "conversations": 212, "resolution_rate": 0.97 },
{ "topic": "Consultation price", "conversations": 180, "resolution_rate": 0.99 },
{ "topic": "Refund", "conversations": 41, "resolution_rate": 0.22 }
],
"unanswered": [
{
"question": "Do you see children?",
"occurrences": 14,
"last_seen_at": "2026-10-30T19:12:00Z",
"example_conversation_id": "conv_k2m1"
}
]
}Quality
The overview already includes resolution_rate, handoffs, avg_first_response_seconds, and feedback_incorrect. To dig deeper:
GET /v1/analytics/breakdown?dimension=handoff_reason&metrics=handoffs: why conversations went to a human.GET /v1/analytics/breakdown?dimension=topic&metrics=conversations,resolution_rate: which topics the agent handles better or worse.GET /v1/analytics/breakdown?dimension=channel&metrics=conversations,resolution_rate: which channel the agent resolves the most on.
Visitors
| Endpoint | Description |
|---|---|
GET /v1/visitors | Lists visitors. Filters: identified (true/false), has_conversation, is_lead, first_seen_after, utm_source, country |
GET /v1/visitors/{id} | A single visitor, with sessions, pages, source, and conversations |
{
"id": "vis_92hd1",
"identified": true,
"contact": { "id": "ctc_4hq81", "external_id": "patient_1042" },
"first_seen_at": "2026-09-14T17:55:00Z",
"last_seen_at": "2026-11-03T14:28:00Z",
"sessions_count": 6,
"pageviews_count": 23,
"first_touch": {
"source": "paid_search",
"utm_source": "google",
"utm_campaign": "online-consultation",
"landing_page": "/online-consultation"
},
"last_touch": { "source": "direct", "landing_page": "/" },
"device": "mobile",
"country": "US",
"region": "FL",
"conversations": ["conv_7mk2p9"],
"is_lead": true
}Visitors who haven't given consent are included in the counts but don't appear individually in this list.
Contact timeline
GET /v1/contacts/{external_id}/timeline
Everything that happened with a customer, in order: visits, pages, conversations on any channel, handoffs, appointments, and conversions.
{
"contact": { "id": "ctc_4hq81", "external_id": "patient_1042", "name": "Mary Smith" },
"data": [
{ "at": "2026-09-14T17:55:00Z", "type": "session_started", "source": "paid_search", "landing_page": "/online-consultation" },
{ "at": "2026-09-14T17:57:10Z", "type": "conversation_started", "conversation_id": "conv_1a2b", "channel": "widget" },
{ "at": "2026-09-14T18:02:00Z", "type": "lead" },
{ "at": "2026-09-14T18:03:30Z", "type": "appointment_requested", "conversation_id": "conv_1a2b" },
{ "at": "2026-09-15T12:00:00Z", "type": "conversion", "name": "consultation_paid", "value": 8900, "currency": "USD" },
{ "at": "2026-11-03T14:30:00Z", "type": "conversation_started", "conversation_id": "conv_7mk2p9", "channel": "api" }
],
"has_more": false,
"next_cursor": null
}Export
Available on the Ultimate plan.
POST /v1/analytics/exports
{
"dataset": "conversations",
"from": "2026-10-01",
"to": "2026-10-31",
"format": "csv"
}dataset values: conversations, messages, visitors, sessions, events, contacts.
The export runs in the background and responds 202 right away:
{
"id": "exp_5f0c9a1e2b7d4c3a8e6f1b2c3d4e5f60",
"dataset": "conversations",
"from": "2026-10-01",
"to": "2026-10-31",
"status": "queued",
"row_count": null,
"failure_reason": null,
"download_url": null,
"expires_at": null,
"created_at": "2026-11-01T12:00:00Z"
}Poll GET /v1/analytics/exports/{id} or wait for the analytics.export_ready webhook. The status goes through queued and running and ends as ready (with download_url) or failed (with failure_reason). The download link is valid for 24 hours; after that the file is deleted and the status becomes expired.
| Dataset | One row per |
|---|---|
conversations | Conversation created in the period, with channel, status, handoff reason, topic, contact, and summary |
messages | Message sent in the period |
visitors | Consenting visitor who visited the site in the period, with the source of their first visit |
sessions | Site session (visits less than 30 minutes apart) |
events | Event tracked in the browser or sent from your server |
contacts | Contact created in the period |
- The file is a UTF-8, comma-separated CSV with a header in the first row. It opens directly in Excel and Google Sheets.
- Dates are in UTC (ISO 8601); the period (
from,to) follows the account's time zone, or thetimezoneyou pass. - Up to 100,000 rows per file: above that, the export fails and asks for a shorter period.
- Up to 20 exports every 24 hours.