Getting Started
This guide will help you add Noxtica to your web application in just a few minutes.
Prerequisites
- A Noxtica account (request access via contact)
- Your Site Key (provided after account setup)
Quick Integration
Once your account is set up and you have your Site Key, add the two scripts below. The recorder-head script must be synchronous and the first executable script in <head>; the full collector stays asynchronous.
Automatic Collection (Recommended)
<head>
<script
src="https://collect.noxtica.com/collector/noxtica-recorder-head.d9ae068e.js"
integrity="sha384-0aarRZ9aHZq4csV3R+MzJUTnerNzrddznWNV/KoKPkKp2Qh40kGsrFiPiMAuvmg9"
crossorigin="anonymous"
></script>
<script
src="https://collect.noxtica.com/collector/noxtica.js"
data-site-key="pk_prod_your_site_key_here"
data-auto-init
data-auto-check-once
async
></script>
</head>
The 1,601-byte gzip recorder-head asset queues a bounded pre-attach window in memory so session replay does not lose initial resources, fetch/XHR completions, performance entries, console/errors, or the count of DOM mutations before the full recorder attaches. It has no transport. The asynchronous collector drains it only after the existing replay policy, legal-basis, DNT/GPC, sampling, and consent gates admit recording; deny/disable destroys the queue. Sites without session replay may omit it, and existing async-only installations remain supported.
The integrity value above belongs to the immutable d9ae068e asset. When upgrading to a newer hashed asset, copy its matching SHA-384 value from /collector/asset-manifest.json; never combine a new URL with an old integrity value.
Strict CSP: inline nonce variant
If policy forbids third-party scripts but permits response-specific nonces, copy the exact minified contents of noxtica-recorder-head.d9ae068e.js into the first script in <head> and attach the nonce generated for that response:
<script nonce="{{csp_nonce}}">
/* exact contents of noxtica-recorder-head.d9ae068e.js */
</script>
<script
nonce="{{csp_nonce}}"
src="https://collect.noxtica.com/collector/noxtica.js"
data-site-key="pk_prod_your_site_key_here"
data-auto-init
data-auto-check-once
async
></script>
Do not fetch and inject the head asset from inside the nonce block: that makes it asynchronous and reopens the early-load gap. The nonce must be unpredictable and unique per HTTP response; include 'nonce-{{csp_nonce}}' in script-src.
This will:
- Assess a visitor on their first visit
- Reuse that result for repeat visits within the cache window (default: 7 days)
- Quietly record return visits without redoing the full assessment
- Coordinate across open tabs so a visitor is only assessed once
Results are available via:
// Listen for results
document.addEventListener('noxtica:collected', function (e) {
console.log('Fingerprint collected:', e.detail);
console.log('Risk score:', e.detail.score);
console.log('Risk level:', e.detail.risk_level);
});
// Or access directly after collection
console.log(window.noxticaResult);
Manual Collection
For more control, use the JavaScript API:
<script src="https://collect.noxtica.com/collector/noxtica.js"></script>
<script>
// Create a client with your Site Key
const client = NoxticaCollector.createClient({
siteKey: 'pk_prod_your_site_key_here',
});
// Collect and submit in one call
client.collectAndSubmit().then((result) => {
console.log('Risk score:', result.score);
console.log('Risk level:', result.risk_level);
console.log('Flags:', result.flags);
});
</script>
Smart Collection with checkOnce()
For the lightest footprint, use checkOnce() — it respects the collection interval you configure on the server, so visitors aren’t reassessed more often than they need to be:
const client = NoxticaCollector.createClient({
siteKey: 'pk_prod_your_site_key_here',
});
// Only collects if outside the check interval window (default: 7 days)
// Otherwise records a visit and returns cached result
const result = await client.checkOnce();
if (result.fromCache) {
console.log('Using cached result, next collection in:', result.nextSubmitIn, 'days');
} else {
console.log('Fresh collection submitted');
}
console.log('Risk level:', result.risk_level);
Performance & Site Impact
The collector is designed to have minimal impact on page load and user-visible latency:
| Metric | Value |
|---|---|
| Recorder-head script | 4,305 B minified / 1,601 B gzip / 1,424 B brotli |
| Async collector | Loaded in the background |
| Time to collect (median, fp) | <50 ms on modern desktop / <120 ms on mid-tier phones |
| Time to risk-scored response | <150 ms median (collector edge → API edge) |
| Cached visit (post-first-load) | <10 ms (no fingerprinting work; just a beacon) |
| Parser blocking | One dependency-free 1,601 B gzip synchronous head asset |
How we keep it light:
- A strict recorder-head budget — the synchronous dependency-free asset is limited to approximately 3 KB gzip and only queues bounded memory.
asynccollector attribute — the full collector loads in the background.- Run-once mode (
data-auto-check-once) — after the first assessment, repeat visits within the cache window only send a tiny visit ping (~150 bytes). - Cross-tab coordination — multiple open tabs collapse to a single assessment.
- Cached after first load — the tamper-resistant Sealed Runtime is cached by the browser, so it loads instantly on later visits.
- Background processing where supported, so the work stays off the main thread and your page stays responsive.
If you notice a slowdown after adding the SDK, capture a profile with await client.collectAndSubmit({ telemetry: true }) — the returned result.telemetry includes a timing breakdown.
Sandbox vs Production
You’ll have two Site Keys: one for development and staging, one for production. Each runs under its own policies and keeps its data fully separate.
| Aspect | Sandbox (pk_sand_*) | Production (pk_prod_*) |
|---|---|---|
| Site Key prefix | pk_sand_ | pk_prod_ |
| Origin allowlist | Localhost + your staging origins | Strict — your registered origins only |
| Rate limit | Generous (~1000/min/IP) | Per-plan limits enforced |
| Risk scoring policy | Permissive — minimum bot blocking | Production policies applied |
| Data retention | 7 days | Per-tenant config (default 90 days) |
| Audit log retention | 7 days | Per-tenant config (default 90 days) |
| Step-up MFA | Optional | Required for destructive ops |
Always switch the Site Key per environment. Never use a pk_sand_* key in production traffic — sandbox data won’t appear in your production dashboards and risk scoring will be too lenient. Conversely, using a pk_prod_* key in development burns through production rate-limit budget.
A common pattern keeps the early loader static while choosing the Site Key dynamically:
<script
src="https://collect.noxtica.com/collector/noxtica-recorder-head.d9ae068e.js"
integrity="sha384-0aarRZ9aHZq4csV3R+MzJUTnerNzrddznWNV/KoKPkKp2Qh40kGsrFiPiMAuvmg9"
crossorigin="anonymous"
></script>
<script>
// Pick the key by hostname; fall back to sandbox in dev.
const KEY = location.hostname === 'www.example.com' ? 'pk_prod_REPLACE_ME' : 'pk_sand_REPLACE_ME';
const s = document.createElement('script');
s.src = 'https://collect.noxtica.com/collector/noxtica.js';
s.async = true;
s.dataset.siteKey = KEY;
s.dataset.autoInit = '';
s.dataset.autoCheckOnce = '';
document.head.appendChild(s);
</script>
Tag Manager Compatibility
The async collector works inside Google Tag Manager, Adobe Launch, Tealium, and Segment, but a tag manager cannot recreate the parser-start window. For full session-replay coverage, place the recorder-head tag directly in the document <head> and use the tag manager only for the async collector.
Tag managers — works, with caveats:
- ✅ Most modern tag managers (GTM Custom HTML, Adobe Launch Custom Code, Segment Custom Source) load the async collector successfully.
- ⚠️ An async-only install remains supported, but replay network history starts when the collector attaches; earlier resources are absent.
- ⚠️ Consent gates that block the full collector until a visitor accepts delay the first assessment. The recorder-head helper may remain loaded because it has no transport; the collector drains it only after admission and discards it on deny.
- ⚠️ Some older tag managers drop custom
data-*attributes. Ifdata-site-keydoesn’t reach the script tag, auto-init won’t start. Set it up yourself in code instead:NoxticaCollector.createClient({ siteKey: 'pk_prod_...' }).checkOnce(); - ❌ A few heavily sandboxed tag containers (rare) prevent the tamper-resistant runtime from starting. The SDK keeps working with a lighter form of collection and logs a console warning.
If you must use a tag manager for the collector, configure its trigger according to your consent platform. Do not configure the recorder-head helper in a DOM Ready or Window Loaded trigger; by then the early interval it exists to preserve has already passed.
Content Security Policy
If your site uses a content-security-policy, you’ll need to allow Noxtica to load, run its tamper-resistant runtime (the Sealed Runtime), and talk to our API. The example below covers all three:
Content-Security-Policy:
default-src 'self';
script-src 'self' 'wasm-unsafe-eval' https://collect.noxtica.com;
connect-src 'self' https://collect.noxtica.com;
If the policy leaves out the 'wasm-unsafe-eval' token, the browser blocks the tamper-resistant runtime and you’ll see a related warning in the console. Noxtica keeps working — it falls back to a lighter form of collection — but with weaker tamper protection. Adding the token above restores the full experience.
Site Keys
Your Site Key (pk_...) is a public identifier that authenticates requests from your domain. Each domain you add in the Backoffice gets a unique Site Key.
Important notes:
- Site Keys are public and can safely be embedded in your HTML
- Each Site Key is tied to a specific origin (e.g.,
https://example.com) - The API will reject requests where the origin doesn’t match the Site Key’s registered domain
Configuration Options
const client = NoxticaCollector.createClient({
// Your Site Key (required)
siteKey: 'pk_prod_your_site_key_here',
// API endpoint (defaults to production)
apiUrl: 'https://collect.noxtica.com',
// Collection mode: 'max' (default), 'standard', or 'minimal'
// Omit to use max mode (recommended)
// mode: 'standard', // Uncomment to opt out of max-only signals
});
Initializing the Script with Parameters
Every attribute on the <script> tag and every createClient()/init() option resolves to the same underlying parameters, whether you embed the raw <script data-*> tag, call NoxticaCollector.createClient() directly, or use @noxtica/sdk’s init()/framework wrappers. This section is the single reference table — do not guess at other attribute or option names.
Script attributes (<script data-*>)
| Attribute | Values | Notes |
|---|---|---|
data-site-key | pk_... string | Required for auto-init to run. |
data-auto-init | presence-only | Required gate — without it, auto-init ignores the tag entirely. |
data-auto-check-once | presence-only | Recommended: run-once via checkOnce() (see Smart Collection above). |
data-auto-collect | presence-only | Legacy: collectAndSubmit() on every load. Ignored when data-auto-check-once is also present. |
data-log-level | silent | error | warn | info | debug | Highest-precedence log-level source. Invalid or absent falls through to the next source. |
data-debug | presence-only | Legacy boolean toggle; lowest-precedence debug mapping, superseded by data-log-level. |
data-api-url | HTTPS URL (or localhost/127.0.0.1) | Non-HTTPS values are rejected; the default collector origin is used instead. |
data-check-interval-days | positive number | Client-level cache TTL override. |
data-ttl-seconds | positive integer | Per-checkOnce() TTL override, in seconds; read only when data-auto-check-once is present. |
The two-script head-snippet pattern (noxtica-recorder-head.js + noxtica.js) that these attributes go on is documented above under Automatic Collection — it isn’t repeated here.
Programmatic options (createClient() / @noxtica/sdk)
@noxtica/sdk’s loader injection sets only data-site-key and data-log-level as real script attributes; every other option below is passed programmatically to createClient() after the loader script loads — there’s no data-mode, data-account-id, etc.
| Option | Values | Also a script attribute? |
|---|---|---|
siteKey | string (pk_...) | data-site-key |
apiUrl | HTTPS URL | data-api-url (raw script embed only) |
mode | 'max' (default) or a reduced value (@noxtica/sdk’s CollectionMode type: 'max' | 'lite') — see Collection Modes below | — |
checkIntervalDays | positive number | data-check-interval-days (raw script embed only) |
signatureMode | 'require' | 'warn' | 'disabled' (default 'require') | — |
accountId | string (≤256 chars) | — |
debug | boolean | data-debug (presence-only) |
logLevel | 'silent' | 'error' | 'warn' | 'info' | 'debug' | data-log-level (second-highest precedence) |
onChallenge / onBlock | callback functions | — |
release / buildId / subjectHandle | strings (≤128 chars each) | — |
scriptUrl | URL (@noxtica/sdk-only) | — |
pinnedLoader | { integrity, version? } (@noxtica/sdk-only) | — |
Precedence for data-log-level / logLevel
Highest wins: the script’s data-log-level attribute → the logLevel createClient()/init() option (or client.setLogLevel()) → your tenant’s “Client log level” Domain setting in the Backoffice → the SDK default (silent unless the legacy data-debug/debug: true toggle is set, in which case it behaves like debug). An absent or invalid value at any source falls through to the next one rather than breaking collection.
Recipe: silent in production, verbose in staging
Mirroring the dynamic Site Key pattern from Sandbox vs Production above, pick data-log-level the same way you pick the Site Key:
<script
src="https://collect.noxtica.com/collector/noxtica-recorder-head.d9ae068e.js"
integrity="sha384-0aarRZ9aHZq4csV3R+MzJUTnerNzrddznWNV/KoKPkKp2Qh40kGsrFiPiMAuvmg9"
crossorigin="anonymous"
></script>
<script>
const isProd = location.hostname === 'www.example.com';
const s = document.createElement('script');
s.src = 'https://collect.noxtica.com/collector/noxtica.js';
s.async = true;
s.dataset.siteKey = isProd ? 'pk_prod_REPLACE_ME' : 'pk_sand_REPLACE_ME';
s.dataset.autoInit = '';
s.dataset.autoCheckOnce = '';
s.dataset.logLevel = isProd ? 'silent' : 'debug';
document.head.appendChild(s);
</script>
CSP and SRI
See Content Security Policy below for the script-src/connect-src header and the recorder-head SRI upgrade note — the same policy covers data-log-level, since it’s just another attribute on the same tag.
Framework examples
Plain HTML:
<script
src="https://collect.noxtica.com/collector/noxtica.js"
data-site-key="pk_prod_your_site_key_here"
data-auto-init
data-auto-check-once
data-log-level="silent"
async
></script>
React (@noxtica/sdk/react):
import { NoxticaProvider } from '@noxtica/sdk/react';
<NoxticaProvider siteKey="pk_prod_your_site_key_here" logLevel="silent">
<App />
</NoxticaProvider>;
Next.js (@noxtica/sdk/next):
import { NoxticaScript } from '@noxtica/sdk/next';
<NoxticaScript siteKey="pk_prod_your_site_key_here" logLevel="silent" />;
Vue (@noxtica/sdk/vue):
import { createNoxtica } from '@noxtica/sdk/vue';
app.use(createNoxtica({ siteKey: 'pk_prod_your_site_key_here', logLevel: 'silent' }));
Collection Modes
| Mode | Signals | Best For |
|---|---|---|
minimal | A small core set of signals | Fastest collection, lowest footprint |
standard | A broad set of signals | Sites that prefer a lighter-touch set of signals |
max | The full set of signals | Maximum accuracy (default) |
Response Format
After collecting and submitting, you receive:
{
"success": true,
"fingerprintId": "abc123...",
"score": 15,
"risk_level": "minimal",
"confidence": 0.5,
"flags": [],
"details": {
"summary": "Detected 0 risk indicator(s)."
}
}
Risk Levels
| Score | Level | Meaning |
|---|---|---|
| 0-19 | minimal | Very low risk, likely legitimate |
| 20-39 | low | Low risk, minor anomalies |
| 40-59 | medium | Moderate risk, some flags |
| 60-79 | high | High risk, likely automation |
| 80-100 | critical | Very high risk, confirmed bot |
Authentication
The SDK authenticates each visit with short-lived, automatically rotated credentials tied to your Site Key. It requests them, refreshes them, and attaches them to every submission for you.
You don’t need to manage any of this — the SDK handles it automatically.
Onboarding Process
- Request access: Contact us to request a demo or get started
- Account setup: We create your tenant account in the platform
- Add domains: Log into Backoffice, go to Domains, and add your origins
- Copy Site Key: Each domain gets a unique Site Key
- Integrate: Add the script with your Site Key to your pages
- Monitor: View fingerprints and analytics in the Backoffice dashboard
Managing Multiple Domains
Noxtica supports multiple domains per account:
- Production:
https://www.yoursite.com - Staging:
https://staging.yoursite.com - Mobile:
https://m.yoursite.com
Each domain has its own Site Key. You can:
- Enable/disable domains without regenerating keys
- Rotate Site Keys if compromised
- View analytics filtered by domain
SDK Version
Current SDK version: 3.3.0 (Schema: 2026-05-24)
What’s new in 3.3.0
- Lightweight behavioral signals (always-on) — simple timing cues like how long a session lasts and how quickly a visitor first interacts. No biometric data, and no end-user consent required.
- Behavioral biometrics (opt-in) — when you turn it on in Backoffice → Settings → Behavioral Biometrics, Noxtica also looks at the rhythm of mouse movement, click timing, and scrolling. This counts as biometric data under strict privacy regulation, so explicit end-user consent is required. See Behavioral Biometrics below.
- Apple Pay consistency check — confirms that a device claiming to be an iPhone actually behaves like one, catching a common spoofing trick.
- Network-fingerprint matching — recognizes the tell-tale connection patterns of common automation tools, so traffic from scripts and bots stands out even when the browser looks convincing.
- IP reputation — flags visitors arriving from networks with a poor reputation, with the option to plug in your own preferred threat-intelligence feed.
Behavioral Biometrics (Optional, Opt-In)
Noxtica can also study the rhythm of how someone moves the mouse, clicks, and scrolls. It’s an opt-in feature, turned off by default.
Why opt-in? This kind of behavioral data counts as sensitive personal data under strict privacy regulation, so capturing it requires explicit consent from your end user. We make it opt-in so you stay in control of when and how it’s used.
To enable:
- Log into Backoffice → Settings → Behavioral Biometrics
- Review the compliance notice with your privacy or legal team
- Update your privacy policy and consent banner to disclose this capture
- Toggle the feature on
Once enabled, Noxtica automatically factors these behavioral signals into future assessments, and your dashboard shows the resulting behavioral score per domain.
Next Steps
- Read the Backend Integration guide for server-side lookups
- Access the dashboard to explore collected data