Weights live in the configuration, keyed by rule code. An empty map means the built-in weights are used, which is the right place to start.
'scoring' => [
// The built-in ruleset is version 5. Raise it by one on every hand edit.
'rule_version' => 6,
'weights' => [
// A technical audience blocks the beacon far more often than average.
'no_js_on_html' => 40,
// We are behind a corporate VPN; everyone's timezone is wrong.
'tz_mismatch' => 0,
],
'thresholds' => [
'bot' => 80, 'likely_bot' => 60, 'unknown' => 40, 'likely_human' => 20,
],
// The five-address floor for the proxy fleet rule. Raise it on a site with a
// large NATed corporate audience; lower it only if you like false positives.
'fp_fleet_min_ips' => 5,
// Distinct User-Agents from one address in 24 hours before User-Agent rotation fires.
'ua_rotation_min_uas' => 10,
],The rule codes and their built-in weights are on Rules decisive alone and Rules that stack. All 26 can be overridden.
- An unknown rule code is a hard error. The scorer throws rather than start with a typo’d key that silently does nothing, so a misspelt override stops the scorer instead of quietly leaving a rule at its default.
- A weight is clamped to 0–200, so a deliberate override can exceed a hundred when you want one signal decisive on its own.
- Setting a weight to 0 disables the rule, and its reason code stops being emitted — which is the intended behaviour, because a rule contributing nothing should not appear in the explanation.
- Thresholds must descend. The panel form refuses a save where they do not.
- The fleet floor has a minimum of 2, the User-Agent rotation floor a minimum of 3. Neither is in the shipped example configuration; add the key yourself if you want to change it.
The Scoring weights card in Settings shows the rules and the four thresholds, but its number inputs stop at a hundred and it does not show either floor. Anything beyond that is set in the file.
The rule version is written onto every visit record, and it is what lets you tell which ruleset produced a verdict instead of comparing incomparable numbers. Saving the Scoring weights card raises it for you; editing the file by hand does not.
A weight change applies to sessions scored after it. That is why the version number is on the document: without it, a chart spanning the change would be averaging two different rulesets and nothing would say so.
- Run for a week without changing anything.
- Open Bot forensics and look at the signal facet. The reason codes are ranked by how often they fire.
- Take the most frequent one and pull twenty sessions that fired it. Read them.
- If they are humans, lower that weight. If they are bots, leave it alone.
- Bump the rule version. Write down what you changed and why.
There is no correct number. Sites in the same industry, of the same size, legitimately differ by an order of magnitude — and tuning until the number looks reasonable is how you end up with a detector that reports whatever you already believed.
Two overrides worth considering before anything else, because they are the two most common genuine mismatches between the defaults and a real audience: lower the no-JS rule if your audience is technical and blocks the beacon far more than average, and zero the timezone rule if everybody reaches you through a corporate VPN. False positives is the catalogue of who else the defaults get wrong.