Traffic Classification
ClickStream labels every accepted event with a traffic classification. The label tells you which lane the event belongs in:
- Human interaction
- AI/search coverage
- Preview/accessibility
- Monitoring/site health
- Automation/QA
- Review/security
Non-human traffic is not automatically bad. It is measured, labeled, and kept separate so you can use it without letting it distort human usage, support routing, or reporting.
The Two Labels You Will Use Most
visitor.bot.isBot // true when this event is bot-classed
visitor.behavioralClass // "human", "suspicious", "likely_bot", or "bot"
Use them together:
if (!visitor.bot.isBot && visitor.behavioralClass === 'human') {
showHumanOnlyExperience();
} else {
keepOutOfHumanMetrics();
}
How Classification Works
ClickStream combines several kinds of evidence. No single signal decides the final label by itself.
| Signal family | What it helps catch |
|---|---|
| Edge request signals | Known crawlers, preview renderers, monitoring checks, suspicious network context. |
| User-agent recognition | Search crawlers, answer agents, SEO tools, previews, monitors, scanners, and automation tools. |
| Browser automation signals | Controlled browsers, test harnesses, and scripted review sessions. |
| Human interaction confidence | Clicks, scroll depth, form use, timing, hesitation, page sequence, and session diversity. |
| Consistency checks | Sessions that claim to be ordinary browsers but have mismatched device, timing, or interaction evidence. |
The result is a bot.score from 0 to 100. Think of it as automation likelihood: higher means less person-like.
Behavioral Buckets
| Bucket | Meaning | Typical action |
|---|---|---|
human | Strong person evidence and low automation likelihood. | Eligible for human-only UI and human analytics. |
suspicious | Some automation-like or low-confidence signals. | Measure, but avoid human-only actions until more evidence appears. |
likely_bot | Strong automation-like behavior without a definitive named match. | Keep out of human-only actions; review if important. |
bot | Classified as non-human. | Route to the right non-human lane. |
For support, personalization, and human-only reporting, prefer behavioralClass === 'human' plus bot.isBot === false.
Bot Categories
When ClickStream can name the non-human purpose, visitor.bot.category uses this taxonomy:
| Category | Meaning |
|---|---|
search_crawler | Search indexing crawler. |
seo_tool | SEO analysis or audit crawler. |
ai_agent | Answer-engine, retrieval, or AI-reading agent. |
social_preview | Link preview or embed renderer. |
monitoring | Uptime or synthetic monitoring check. |
scraper | Programmatic downloader or generic scraper. |
scanner | Security scanner or probe-like traffic. |
automation | Controlled browser, QA run, or scripted review session. |
stealth_bot | Bot-like behavior that avoided simple name-based recognition. |
kiosk | Internal display, passive screen, or long-lived unattended browser lane. |
unknown_bot | Bot-shaped traffic with no specific category yet. |
The category tells you the safest lane. For example, ai_agent and search_crawler are discovery coverage; automation is QA/review; monitoring is site health.
How To Use It
Human-Only UI
import { getVisitorOrNull } from '@clickstreamhq/signals';
const visitor = await getVisitorOrNull();
if (visitor && (
!visitor.bot.isBot &&
visitor.behavioralClass === 'human' &&
visitor.scores.conversionReadiness >= 70
)) {
showHumanOnlyAction();
}
AI/Search Coverage
const isDiscoveryAgent =
visitor.bot.category === 'ai_agent' ||
visitor.bot.category === 'search_crawler';
if (isDiscoveryAgent) {
addStructuredDataForMachineReaders();
}
For non-JavaScript crawlers and answer agents, install Edge capture. Page code only runs when the requesting client executes JavaScript.
Automation And QA
if (visitor.bot.category === 'automation') {
window.dispatchEvent(new CustomEvent('clickstream:qa-coverage', {
detail: {
page: location.pathname,
sessionId: visitor.session.sessionId,
score: visitor.bot.score,
},
}));
}
This lets test traffic prove coverage without being treated as human demand.
Signals Feed
ws.addEventListener('message', (event) => {
const msg = JSON.parse(event.data);
if (msg.type !== 'event') return;
if (msg.behavioralClass === 'human' && (msg.scores?.intent ?? 0) >= 70) {
forwardToSupportWorkflow(msg);
}
if (msg.bot?.category === 'automation') {
forwardToQaCoverage(msg);
}
});
See Signals Feed for the full subscriber pattern.
What Not To Do
- Do not block every bot-classed request by default. Some non-human traffic is useful discovery, monitoring, preview, or QA evidence.
- Do not count crawler, monitor, or automation visits as human demand.
- Do not count bot-classed visitors in human-only reports.
- Do not hide suspicious traffic entirely; keep it visible for review and coverage analysis.
In The Dashboard
Intelligence -> Human + AI Traffic groups traffic into the same lanes used by the Signals API. Use it to answer:
- Which pages do humans use most?
- Which pages do search and answer agents reach?
- Which non-human traffic should be treated as monitoring or QA?
- How much bot-classed traffic was measured separately from human traffic?
Signals coverage proof turns those same labels into coverage proof, lane separation, and AI/search coverage gaps.
See Also
- Signals API: read
visitor.bot.*from page code - Edge capture: measure non-JavaScript traffic
- Signals coverage proof: prove coverage and lane separation
- Signals Feed: stream every labeled event