Browser Telemetry
Use this when your backend already calls /api/v1/score and you want to add device/behavior signals collected on the page the visitor lands on afterward (e.g. a "thank you" or dashboard page). This sharpens results without changing your backend request.
1. Store the request ID
After /api/v1/score returns, make its request_id available to the browser before the script below runs — for example by rendering it into the page.
<script>
localStorage.setItem("revylta_request_id", "REQUEST_ID_FROM_SCORE_RESPONSE");
</script>2. Install the script on the next page
<script src="https://cdn.revylta.com/revenueshield.js"
data-api-key="YOUR_BROWSER_KEY"
data-mode="postscore"></script>The script automatically reads the stored revylta_request_id and reports telemetry against it using your browser key.
Tap and device measurements
The collector also records bounded summaries of tap timing, touch force and contact size, and motion/orientation readings when the browser makes them available. These measurements are collected for analysis only and do not change the risk score. Unavailable or constant readings are not proof of automation.
Collection uses passive listeners, asks for no sensor permission, and stops after at most 30 seconds of active observation or an earlier terminal event. Device motion and orientation share a 200-event limit. No new raw sensor traces or touch-property sample arrays are sent.
To disable these measurements, add data-hardware-signals="false" to the script tag, or pass hardwareSignals: false to RevyltaTelemetry.init(). To stop them during a page visit, call RevyltaTelemetry.stopHardwareCollection(); subsequent snapshots omit the measurements. This does not remove previously sent data.
With data-auto-init="false", the new measurement listeners start only after explicit initialization. The controls above apply to the new measurements; existing browser telemetry retains its existing behavior. You can inspect the summaries under “Browser and input measurements” on the request detail page.
Browser comparisons and input timing
The collector also compares available browser properties across the page, a short-lived worker, and a hidden frame. It sends comparison names and availability states, not new copies of the compared values. Restricted or unavailable contexts are not mismatches. Extensions and privacy settings can affect these observations.
For input timing, it summarizes up to 16 clicks or taps and 120 eligible key presses, within the capture window capped at 30 seconds. It sends aggregate position and timing statistics, not typed text, key identities, field names, or new raw coordinate arrays. Password inputs, fields declared as password/payment/one-time-code fields, and fields or forms marked autocomplete="off" are excluded. These exclusions depend on the form's markup.
These additions are collected for analysis and do not change normal API risk scores. Inspect their summaries under “Browser and input measurements” on the request detail page. Missing readings are not evidence of automation.
Disable them independently with data-cross-context="false" and data-interaction-dynamics="false", or the initialization options crossContext: false and interactionDynamics: false. During a visit, RevyltaTelemetry.stopCrossContextCollection() and RevyltaTelemetry.stopInteractionCollection() stop the corresponding feature and omit it from future snapshots. They cannot recall previously queued or sent data.
With data-auto-init="false", both additions wait for explicit initialization. These feature controls are independent of the hardware controls above and do not disable existing legacy telemetry.
Doing it manually (no script)
If you'd rather collect and send telemetry yourself:
| Field | Description | |
|---|---|---|
request_id | required | The ID from the original score response. Sent as the X-Request-ID header or as a body field. |
browser_telemetry | required | An object of device/behavior signals. |
curl -X POST "https://revylta.com/api/v1/browser_telemetry" \
-H "Content-Type: application/json" \
-H "X-API-KEY: YOUR_BROWSER_KEY" \
-d '{
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"browser_telemetry": {
"behavioral_session": {
"page_context": "postsignup"
}
}
}'const response = await fetch("https://revylta.com/api/v1/browser_telemetry", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": "YOUR_BROWSER_KEY"
},
body: JSON.stringify({
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"browser_telemetry": {
"behavioral_session": {
"page_context": "postsignup"
}
}
})
});
const result = await response.json();
console.log(result);import requests
response = requests.post(
"https://revylta.com/api/v1/browser_telemetry",
headers={
"Content-Type": "application/json",
"X-API-KEY": "YOUR_BROWSER_KEY"
},
json={
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"browser_telemetry": {
"behavioral_session": {
"page_context": "postsignup"
}
}
}
)
print(response.status_code)
print(response.json())require "net/http"
require "json"
require "uri"
uri = URI("https://revylta.com/api/v1/browser_telemetry")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"
request = Net::HTTP::Post.new(uri)
request["Content-Type"] = "application/json"
request["X-API-KEY"] = "YOUR_BROWSER_KEY"
request.body = JSON.generate({
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"browser_telemetry": {
"behavioral_session": {
"page_context": "postsignup"
}
}
})
response = http.request(request)
puts response.code
puts response.body<?php
$payload = [
"request_id" => "550e8400-e29b-41d4-a716-446655440000",
"browser_telemetry" => [
"behavioral_session" => [
"page_context" => "postsignup"
]
]
];
$ch = curl_init("https://revylta.com/api/v1/browser_telemetry");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"X-API-KEY: YOUR_BROWSER_KEY"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status . PHP_EOL;
echo $response . PHP_EOL;Response
{
"status": "accepted",
"queued": true,
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}Telemetry is processed asynchronously — it enriches later reads of this request but doesn't hold up the response.