Skip to content

Embedding fp-token.js

Signup Protection compares the visit that obtained a page token with the request that submits your form. fp-token.js obtains the token through the separately served fp-probe.js file. Your page writes the returned value into a hidden field. The served file owns the request, browser assessment and optional WebTransport session, so Emvero can update them independently of the small token wrapper in your bundle.

Replace the client code and page key with the values from your account:

<form method="post" action="/signup">
<input type="email" name="email">
<input type="hidden" name="fp_token">
<button>Create account</button>
</form>
<script src="/fp-token.js"></script>
<script src="https://probe.tlsatlas.com/fp-probe.js?client=your_client_code"></script>
<script>
let visitToken;
async function onSignupFormShown(vid) {
const field = document.querySelector('input[name="fp_token"]');
if (typeof FpToken !== 'function') return '';
visitToken = new FpToken(
'https://fp.tlsatlas.com/_fp/token',
'fp_key_your_page_key',
{ quic: true },
);
const token = await visitToken.fetch(vid);
field.value = token;
return token;
}
</script>

Call const tokenPromise = onSignupFormShown(vid) from your form-show handler, after applicable consent. For a form visible from the start, use your page-ready handler; for a dialog, wait until it opens. Script loading makes the library available; it does not itself trigger initialization.

vid is an optional opaque identifier for this visit, supplied as a string or a Promise. Do not pass an account or user ID, email address or phone number. The handler returns a Promise<string> resolving to the token or ''. The library returns the value; the handler assigns it to the hidden field. A missing wrapper or missing/incompatible served probe leaves no token.

Keep the hidden field inside the form. Your server sends its current value as token, alongside the submitted address and request details it observed. A public page key cannot replace the secret API key used by that server call.

URLhttps://docs.emvero.io/js/c535799/fp-token.js
Integritysha384-BscMW37DO5GnwOEP3UejPSWnRR+7WQ/KCgfpmYFEvVxWJWYgIcHgNnWIpHG+s+Yo
Size10,226 bytes
Revisionc53579916601, copied byte for byte from Emvero’s internal token-script source

Each release has its own URL and its bytes stay unchanged. Older releases stay available. Download this file, check its integrity and serve it from your own origin as /fp-token.js, as the example above assumes:

Terminal window
curl -sSo fp-token.js https://docs.emvero.io/js/c535799/fp-token.js
echo "sha384-$(openssl dgst -sha384 -binary fp-token.js | base64)"

Alternatively, load that version from the documentation host:

<script src="https://docs.emvero.io/js/c535799/fp-token.js"
integrity="sha384-BscMW37DO5GnwOEP3UejPSWnRR+7WQ/KCgfpmYFEvVxWJWYgIcHgNnWIpHG+s+Yo"
crossorigin="anonymous"></script>

crossorigin="anonymous" is required for a browser to check the integrity of a script loaded from another origin. Do not edit a pinned copy and retain its old integrity value.

The current token script is also available at https://probe.tlsatlas.com/fp-token.js. That URL follows service updates; use the versioned file above when you need fixed bytes and an integrity value.

new FpToken(endpoint, key, options)
Argument Meaning
endpoint The token endpoint shown in your account, such as https://fp.tlsatlas.com/_fp/token.
key A public page key: fp_key_ and 43 more characters. It is accepted only on its configured origins.
options Optional settings below.
Option Effect
{ timezone: false } Omits the browser’s time-zone statement; the related comparisons report themselves not evaluated.
{ probe: false } Disables the browser probe and its WebTransport session, even if the probe script is loaded.
{ quic: true } Opts into a WebTransport session through the probe. It is off by default and needs a compatible probe and a node that supports the session.
{ preconnect: false } Disables connection prewarming when collection runs.

Load fp-probe.js?client=… with your public client code. Do not substitute the page key for that code. Its current interface is window.FpProbe with API contract 3; FpToken.fetch() delegates to its token() method. The file is required even with { probe: false }: that option skips browser assessment, while the served file still performs the token request. Keep the probe on its service URL so its build can update independently.

A missing or incompatible probe file leaves no token. Individual browser checks can remain not evaluated while a usable token is obtained; in that case the operation can remain evaluated and include fp_probe_not_evaluated. Automation findings can require confirmation; property-tampering findings are informational. See the signal-code reference.

Create the FpToken instance and call fetch(vid) when the person can see the form, after applicable consent. For a form visible from the start, initialize when the page is ready; for a dialog, wait until it opens. Calling it only on submission can produce fp_fast_submission.

The token script makes no request before fetch(). A remotely loaded script tag still downloads its file before that call. If your consent flow must defer those downloads too, insert the script tags only after consent.

The method’s contract is:

fetch(vid?: string | PromiseLike<string>): Promise<string>

The return value is always a Promise. It resolves to the token string on success or to '' if no token was obtained. Your page writes that value into its field. The library does not stop the person filling or submitting the form, and uses no cookies, localStorage or sessionStorage.

A token lives for 15 minutes in the current profile. After the form-show handler has created visitToken, schedule refreshes before expiry:

const field = document.querySelector('input[name="fp_token"]');
const timer = setInterval(async () => {
field.value = await visitToken.fetch();
}, 10 * 60 * 1000);
field.form.addEventListener('submit', () => clearInterval(timer));

A repeated fetch() uses a live token kept by the served probe in page memory. The node preserves the first issue time only if the previous token is usable, the IPv4 address or IPv6 /64 is unchanged, the browser family, major version and platform match, and the visit is no older than 24 hours. Otherwise the timing starts again; a submission soon afterwards can produce the fast-submission finding. Schedule the call before expiry and update the field with its result. An expired token can require confirmation; refresh after expiry cannot be relied on to preserve an earlier visit interval. The wrapper has no timers of its own.

If your application uses an opaque visit identifier, pass its string value or a Promise to fetch(vid). Use a visit-scoped value with no embedded account or user ID, email address or phone number. The raw value can enter the token request query; it is not a field for customer identity. The served probe can collect while it resolves; an unavailable or late identifier is omitted. A later fetch() keeps the previous page identifier, fetch(vid) replaces it and fetch('') removes it. Every call returns Promise<string>; no identifier is created by omitting it.

The script creates no visitor identifier. Emvero’s public checking API accepts no vid field and does not compare the submitted request against that digest. Passing an identifier does not provide cross-visit identity detection.

With a compatible served file, fetch() initiates a cross-origin GET for a token, with credentials: 'omit' and cache: 'no-store'. Its query can contain the page key, browser time zone, previous token, customer-supplied vid, probe result and WebTransport receipt. No custom headers or CORS preflight are used.

With { quic: true } and a compatible probe, collection also attempts a WebTransport session. Its failure does not prevent the TCP token request. Current opaque tokens use format v14; forward the value without decoding it. The internal processing runs within Emvero’s EU infrastructure; the website’s privacy policy explains data and retention.

For the example with a locally served token script and remotely served probe:

Content-Security-Policy: default-src 'self'; script-src 'self' https://probe.tlsatlas.com 'wasm-unsafe-eval'; worker-src 'self' blob:; connect-src 'self' https://fp.tlsatlas.com

The probe needs its script host, 'wasm-unsafe-eval' for WebAssembly and worker-src blob: for its Worker checks. The token endpoint belongs in connect-src. Loading the pinned token script from this documentation host also needs https://docs.emvero.io in script-src.

Put the initialization in your own script file, or authorize the inline block with a nonce or hash. A blocked probe script prevents token collection. Restrictions on individual Worker or WebAssembly checks can leave those comparisons incomplete; inspect the returned assessment limits. A WebTransport attempt uses the capture node’s origin.

The account area accepts up to 20 origins per key and 20 live keys per account. An origin can be an exact HTTPS origin, including a port, or a subdomain zone such as https://*.example.com. Paths, queries, HTTP, a bare * and https://*.com are refused. Hostnames are normalized to lowercase and IDN to Punycode.

A revoked key cannot be restored. Key changes take effect after synchronization; a ready connection is separate from a working integration. Complete a real server check and read its result as described in Signup Protection.