Skip to main content
ShieldLabs counts identifications against one included volume for your whole account, shared by every domain on it. Within one visit (while a page of your site stays open in the browser, across route changes in a single-page app and across open tabs), checkAnonymous and checkAuthenticatedUser run at most one identification every five minutes for the same user. A call inside that window posts nothing, counts nothing, and its onInitialized handler receives { status: "not_initialized" }. On a multi-page site, a full page load in the only open tab can start a new visit with its own identification. forceCheckAnonymous and forceCheckAuthenticatedUser run an identification every time, keep the current Session ID and restart the five-minute window. You read results on your server, from the webhook or the History API, and reading is free. So the cost lever is where you place forceCheck* calls; plain calls add at most one identification every five minutes per user within a visit. This page has two parts: tune your integration before it ships, and localize a usage spike if one shows up.

Optimize proactively

The goal is two things: steady coverage of your signed-in users, which builds each account’s risk, linked devices and High-Risk Events, and one fresh identification at each point where you act on the result, with the connection already warm so that call is fast.

Warm the connection early

ShieldLabs talks to three web hosts: the module loads from cdn.shieldlabs.ai, the identification posts to rest.shieldlabs.ai, and the network check calls webrtc.shieldlabs.ai. Hint them early so the TLS handshake is done before you ever call. Put these in <head>:
These hints never count toward your plan. They only shave latency off the call you are about to make. If your site sends a strict Content-Security-Policy, the snippet’s hosts need allowlisting under Content Security Policy.

Cover signed-in pages, force a check at decision points

Load the snippet on every signed-in page and call checkAuthenticatedUser(hashedUserId) there. Calls inside five minutes of the last identification for that user in that browser count nothing within the same visit, so this keeps each account covered at a predictable cost. On a page where you act on the result (a checkout, a withdrawal, a password change), call forceCheckAuthenticatedUser in place of the plain call when the page opens, for one fresh identification. onInitialized fires when the check starts, before the snippet has sent the identification, so store the request ID in the form and let the form submit normally.
Calling checkAuthenticatedUser(hashedUserId) on every signed-in page is the recommended setup. Users, account-level risk and all four High-Risk Events are built on it. Within one visit (while a page of your site stays open in the browser, across route changes in a single-page app and across open tabs), the snippet runs at most one identification every five minutes for the same user. On a multi-page site, a full page load in the only open tab can start a new visit and run a new identification, so watch your usage in the analytics dashboard after launch. The calls that add up fastest are the forceCheck* variants, so keep those at decision points. The snippet page shows the signed-in call for each framework.

Map each touchpoint to one call

Plain calls run at most one identification every five minutes for the same user in the same browser, within a visit; each forceCheck* call is one identification.
The forceCheck* variants run an identification every time, keep the current Session ID and restart the five-minute window. Each one is one identification, so call them at meaningful moments (right after login, before a high-stakes action), not in a loop. The four exports are detailed on the snippet page.

Diagnose a usage spike

If identifications climb faster than your traffic explains, it is almost always one of three things: forceCheck* calls firing too often, scripted traffic against your public key, or a genuine traffic burst. Work through them in that order.

Implementation causes

Most unexpected usage is a forced call firing more often than intended. Check for:
  • forceCheck* on page load. A forceCheckAnonymous or forceCheckAuthenticatedUser in a shared layout or on every route change runs an identification on every navigation. Use the plain checkAnonymous / checkAuthenticatedUser on page load and keep forceCheck* for decision points.
  • Looping forceCheck* calls. A component effect without a stable dependency that calls forceCheck* runs an identification on every re-render. Pin the dependency list so each mount calls once; the plain calls are already limited to one identification every five minutes within a visit. The snippet framework examples show the mount-once pattern.
  • forceCheck* where nothing is decided. A forced identification pays off only where you act on its result. Plain calls on signed-in pages are different: they feed each user’s risk and High-Risk Events even when you do not read them.

Scripted-traffic cause

The public key works only for the domain it is registered to: a call from another site is refused with 401 before anything counts. Usage you cannot attribute to your own pages is most likely scripted traffic that presents your domain. It typically shows up in the analytics dashboard as identifications carrying risk signals such as Browser Automation or JavaScript Disabled, often from a few public IPs.
If you suspect your public key is being replayed, rotate it in the analytics dashboard under Integration > API keys and update the snippet in the same change. Each domain has its own API keys and its own domain registration.

Traffic cause

If the integration is clean, a spike is real volume: a campaign, a referral surge or a wave of automated traffic. Each identification counts whoever is behind it, so check what the new traffic is: the analytics dashboard shows its channel and campaign, and automated visitors carry the Browser Automation or JavaScript Disabled risk signals. Legitimate growth calls for more included volume; automated traffic calls for acting on those visitors. On Overview, the Unique visitors panel counts Good bots (search-engine crawlers) and Bad bots (automated browsers) for the period.

How to investigate

The analytics dashboard lists every identification with its User HID, Device ID, Visitor ID, IP and traffic source, and reading or exporting it is free. Use it to localize the spike:
1

Export the spike window

On Analytics in the analytics dashboard, set the period to the spike window, pick the domain if you run several, and Export the identifications as CSV. Export covers every identification in the current filter, up to 10,000 rows. Reading and exporting never count toward your plan.
2

Group to find the source

In your own tooling, group the export by User HID, Device ID, Visitor ID and public IP, then by entry page and channel. One account, device or page dominating the count points at a loop or a forced call on a hot page; a broad spread across many accounts and IPs points at a real traffic surge.In the analytics dashboard, the Users, Devices, Unique visitors and Public IPs tabs of Analytics group the period’s identifications for you, each row with its Identifications count. Open a row’s card to see its linked devices, visitors and IPs.
3

Watch your included volume

Follow your plan and usage in the analytics dashboard. When your account reaches its included volume, the identification request returns HTTP 402 until the billing cycle resets or you change plan; History API and profile reads never return 402. The Billing page covers included identifications, and the rate limits page covers the gateway 429.
Searching identifications by one identifier (User HID, Device ID, Visitor ID, IP, request ID, Session ID or Cookie ID) over the spike period is the fastest way to confirm whether one account or device is generating the extra calls. In code, the History API gives the same view: read every identification of one account by user_hid, or of one device by device_id. The troubleshooting page covers the broader integration issues you might surface along the way.

Next

Wire results into your backend with Acting on results, and confirm what counts toward your plan on the Billing page.