Documentation menu

Visitor tracking

How Nevox measures visits, events, and conversions on your site and app, with consent and privacy.

The same widget script, with the publishable key, measures visits to your site. No extra code needed. The numbers show up in analytics.

html
<script
  src="https://nevox.ai/widget.js"
  data-key="nvx_pk_live_..."
  data-agent="agt_8f2k1x"
  data-track="true"
  data-consent="auto"
  async
></script>

Want to measure the site without showing the chat on a page? Use data-widget="false".

What is measured automatically

EventWhen
page_viewEach page opened, including route changes in single-page apps (React, Next.js, Vue)
session_startStart of a visit, with source, UTMs, and landing page (derived: the visit ends after 30 minutes of inactivity)
widget_openThe visitor opened the chat
conversation_startThe visitor's first message
leadThe visitor left a phone number or email, or was qualified by the agent (derived from conversations, in analytics)
appointment_requestedThe agent collected an appointment request (derived from the calendar, in analytics)
handoffThe conversation went to your team

Each event includes: page (path only, without URL parameters, which may contain personal data), title, referrer (where the visitor came from), UTMs, device type, browser, operating system, and language. We do not collect form contents, what the person types outside the chat, or clicks in general.

Custom events and conversions

js
Nevox.track("plan_viewed", { plan: "family" });

Nevox.track("consultation_paid", {
  value: 8900,       // cents
  currency: "USD",
  order_id: "order_5531"
});
  • Names: lowercase letters, numbers, and _, up to 64 characters.
  • Properties: up to 20, with string, number, or boolean values.
  • value (in cents) and currency in the properties become the conversion value.
  • For an event to count as a conversion, mark its name in Dashboard → Analytics → Conversions.

Identify a visitor

When the visitor logs in or signs up, link the visitor to the contact:

js
Nevox.identify("patient_1042", { name: "Mary Smith", email: "mary@example.com" });

From then on, this browser's past and future visits go into the contact timeline, and Nevox fires the visitor.identified webhook.

If you already use the session token in the widget, identification is automatic.

Events sent from your server

Some conversions happen outside the browser: a confirmed payment, a completed appointment, a signed contract. Send them from your server:

POST /v1/events · scope events:write

bash
curl https://api.nevox.ai/v1/events \
  -H "Authorization: Bearer $NEVOX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "name": "consultation_paid",
        "contact_external_id": "patient_1042",
        "occurred_at": "2026-11-03T15:00:00Z",
        "value": 8900,
        "currency": "USD",
        "properties": { "order_id": "order_5531" },
        "dedupe_key": "order_5531"
      }
    ]
  }'
json
{ "accepted": 1, "rejected": [] }
  • Up to 100 events per call.
  • Identify the person with contact_external_id or visitor_id.
  • dedupe_key prevents counting the same event twice (for 7 days).
  • occurred_at accepts up to 7 days in the past.
  • Counts toward the plan's monthly event limit (Pro - 3 Agents: 10,000; Ultimate - 5 Agents: 100,000). Test-key events don't count.
  • The response lists rejected events with the reason (duplicate, contact_not_found, invalid_param), without rejecting the whole batch.

You choose how tracking behaves before the visitor accepts cookies:

data-consentBefore consentAfter Nevox.consent("granted")
auto (default)Measures anonymously, without cookies: visits are included in the counts, but the same person isn't recognized on another dayPersistent identifier in the browser; the visitor appears individually
requiredMeasures nothingPersistent identifier
grantedYou've already collected consent in your own banner—

Connect Nevox to your cookie banner:

js
myBanner.onAccept(() => Nevox.consent("granted"));
myBanner.onReject(() => Nevox.consent("denied"));

Nevox.consent("denied") deletes the identifier from the browser and goes back to anonymous mode (or to no tracking at all, in required).

The chat works normally in every mode. Talking to the agent doesn't depend on cookie consent.

Privacy

  • IP: used only to determine country, state, and city, then discarded. It is never stored.
  • Anonymous mode: uses a daily identifier computed with a secret value that changes every day and is deleted. It can't be used to work out who the person is.
  • Browser signals: we honor Global Privacy Control (GPC). With GPC on, the visitor stays in anonymous mode.
  • Bots: visits from known bots and crawlers are discarded.
  • Persistent identifier: stored in your own domain's storage (nvx_vid), for up to 13 months.
  • Retention: events are kept for your plan's retention period (Pro - 3 Agents: 90 days; Ultimate - 5 Agents: 13 months) and then deleted. Aggregated daily counts, which don't identify anyone, are kept.
  • Deletion: DELETE /v1/contacts/{external_id} also deletes the events linked to the contact.
Sensitive data: don't send information such as diagnoses, ID documents, card numbers, or passwords in events, properties, or identify. See security and privacy.

Direct sending (advanced)

The script sends events to POST https://api.nevox.ai/v1/collect with the publishable key. You normally don't need to call this endpoint. If your app doesn't run the script (e.g. a native app), use events from your server.