Measure Traffic Quality
Standard analytics measures volume: how many sessions, how many pageviews, how many “new” users. It cannot tell you how much of that traffic is masked, spoofed, or coordinated. ShieldLabs measures quality: every visit carries an explainable Risk Score (0-100) and the signals behind it, so you can split a noisy number like “10,000 visits” into traffic you can trust and traffic you cannot. This recipe shows how to read the dashboard to grade traffic, how to rank each acquisition source by the anonymous-traffic share it delivers, and how to export the raw Data into your own BI to compute cost per real visitor. ShieldLabs scores the request; your reporting and budget decisions stay yours.The Risk Score is 0-100, hard-capped at 100, in four bands: Clean (0-9), Low (10-29), Medium (30-59), High (60-100). A higher score means more anonymous or masked traffic, not a confirmed verdict: a legitimate visitor can score high behind a corporate proxy, a VPN, or a privacy browser. For traffic-quality reporting you are looking at the shape of the distribution across many requests, where individual false positives wash out.
Volume vs quality, in one number
A dashboard that only reports volume treats every session as equal. ShieldLabs attaches a per-request risk dimension, so the same 10,000 visits become a quality breakdown you can act on.| Standard analytics | ShieldLabs | |
|---|---|---|
| Unit counted | Sessions, pageviews | Identified requests + Risk Score |
| ”10,000 visits” means | 10,000 equal sessions | A distribution across Clean / Low / Medium / High |
| Can it see VPN, proxy, Tor, anti-detect routing | No | Yes, as named signals in Details |
| Returning visitor after cleared cookies | Counted as new | Recognized by DeviceID (same browser) |
| Per-source verdict | Volume and conversions | Volume, conversions, and risk share |
| Bucket | Bands | What is usually in it |
|---|---|---|
| Clean | Clean (0-9), Low (10-29) | Direct connections, ordinary browsers, the bulk of healthy traffic |
| Suspicious | Medium (30-59) | VPN, proxy, privacy relay, datacenter IP, timezone mismatch (one or two overlapping signals) |
| Dangerous | High (60-100) | Tor, anti-detect browsers, OS mismatch, port-scan proxying (strong anonymity or abuse signals) |
Read the dashboard
Two cards on the Overview tab give you the whole-traffic picture, and Traffic Sources breaks it down by where the traffic came from. Filter both by project and date range using the controls at the top of the page.Read the Traffic Score card
On Overview, the Traffic Score card shows a gauge with the band label, a Traffic Risk metric (the average request risk for the period, where 0 is ideal and 100 is very bad), and Requests Checked (how many requests were analyzed). Below the gauge, a stacked bar and legend show the count and percent of requests in each band: Clean, Low Risk, Medium Risk, High Risk. This is your quality split for all traffic at a glance.
Rank sources by risk
Open Traffic Sources. The Channels table lists Google Ads, Meta, TikTok, LinkedIn, X, Organic Search, Referral, Direct, and Other. Each row shows requests, traffic share, and a Risk Badge rendered as
<score> <level> (for example 71 High or 8 Clean). Sort by Traffic Risk to find the channel sending the most masked traffic.Drill into referrers and UTM
The Source details table toggles between Referrers and UTM Parameters. Under UTM you can inspect Source, Medium, Campaign, Term, or Content, each with its own request share and Risk Badge. This is how you isolate the single affiliate, creative, or campaign delivering the anonymous traffic inside an otherwise healthy channel.
Export the raw records for BI
Go to the Data tab and use Export to pull the per-request records as JSON or CSV. Exports are free (they do not bill requests). Load them into your warehouse or BI tool to join risk against spend, conversions, and revenue. The next section covers the columns you get.
Why these counts beat cookie analytics
Google Analytics and Vercel Analytics count by a first-party cookie or client id. Clear cookies, open an incognito window, switch devices, or rotate your IP, and they count a brand-new user every time. That inflates “new visitors” and quietly loses your returning ones. ShieldLabs counts by a fingerprint-derived identity. The DeviceID is derived from dozens of stable browser components (canvas, WebGL, audio, fonts, screen, navigator, timezone, and more), not stored in a cookie, so a returning person on the same browser keeps the same identity even after clearing cookies or using incognito. They are not miscounted as new.| GA / Vercel count by | ShieldLabs counts by | Result | |
|---|---|---|---|
| Identity basis | First-party cookie / client id | DeviceID (derived from the browser environment) | Survives cookie clear and incognito |
| Cleared cookies | New user each time | Same DeviceID | Returning visitors stay returning |
| Rotated IP | Often a new user | Same DeviceID | One person, one identity |
| Different browser, same machine | New user | New DeviceID | Counted separately (honest boundary) |
Capture the source on every visit
The snippet already collects channel, referrer, and UTM attribution for every request, so the Traffic Sources tables populate without extra work. You only need the standard install on the page that receives the traffic.utm_source, utm_medium, utm_campaign, utm_content, utm_term, the referrer_domain, and the resolved channel for each request. See Snippet for the framework variants and CSP requirements.
Compute cost per real visitor
The point of grading traffic by source is to stop paying click prices for masked traffic. “Cost per real visitor” reweights spend against the share of a source’s traffic you can actually trust. Export the Data records, group by source, and divide spend by the Clean-bucket count instead of the raw count.affiliate_x looks cheaper. On a cost-per-real-visitor basis it is more than twice as expensive, because most of its traffic is masked. That is the reallocation decision standard analytics cannot surface. The same pattern applies to paying out conversions, covered in Affiliate Fraud.
Pull the data programmatically
You have two programmatic paths, and they carry different fields. The Data export (JSON or CSV from the Data tab) is the one that includes the per-request source attribution:channel, referrer_domain, and the utm_* fields, alongside the Score and signal columns. That is the export to join against ad spend for cost-per-real-visitor reporting. Exports are free.
The History API is for reading scored records by identifier in real time. Query by identifier and the response returns newest-first snapshots with the Score, the Details behind it, and the network-intelligence fields, but not the channel/UTM attribution. Use it to reconcile or enrich, then join back to the export on RequestID when you need source attribution. The History API bills one request per returned row (an empty result still bills one), while dashboard views and exports are free.
channel and utm_*) and use the History API to pull fresh per-identifier records as needed. If you would rather build the report in real time as traffic arrives, consume the webhook instead and aggregate the score per source in your own store, capturing the attribution from the inbound request yourself. Webhooks are at-most-once with no retries, so make the handler idempotent on RequestID, and for guaranteed completeness reconcile against the History API.
What to do with the answer
- A channel or campaign with a high Dangerous share is the first place to cut or renegotiate spend, especially affiliate and referral sources.
- A source that looks expensive per click but is mostly Clean may be your best traffic once reweighted to cost per real visitor.
- Rising Medium and High share over time on Direct or Organic Search is a signal to look at the Abuse Patterns tab for coordinated activity behind the volume.
- Pair this report with the Visitors view to separate genuinely returning people from cookie-churned “new” sessions, so your retention numbers reflect reality.