Why we give you tags, not a score

A risk score tells you a number. A tag tells you what happened, how sure we are, and what to do next. Here is why Ordent is built around tags, and what that changes for a team without a fraud analyst.

Ordent team3 min read

Every fraud vendor returns a score. Ordent returns a score too, but we treat it as a footnote. The thing we actually want you to read is the list of tags underneath it.

This post is about why.

A score is an answer to the wrong question

A risk score answers "how suspicious is this user, on a scale?" That is a reasonable question for a fraud analyst who reads scores all day and has a feel for what 81 means on this product, this month, with this traffic.

Most of the businesses we work with do not have that person. They have an engineer who shipped signup last week and wants to know one thing: what should the code do now?

A score does not say. Eighty-one could mean "a bot from a datacenter" or "a real customer on a hotel VPN". The right action is different in each case, and the score erased the difference on its way to becoming a number.

What a tag carries

A tag is a fact about the user, with three things attached:

{ "tag": "email.disposable", "confidence": 0.99, "action": "require_phone" }
  • The fact. email.disposable means the email domain is a throwaway service. Not "risky", not "suspicious": a specific thing we observed.
  • How sure we are. Confidence is per tag, not per user. We can be certain about the email and unsure about the device at the same time, and you can set different thresholds for each.
  • What to do. The suggested action comes from the policy preset for your vertical. It is a default you can override, not a verdict.

Tags also accumulate. A user who looked clean at signup and starts sharing a device with a banned account six months later gets device.shared_with_banned on the day it happens, with the event that produced it. The timeline is the record of everything we ever learned about that user, in order.

Why this matters for a small team

Three practical consequences.

You can explain every decision. When support asks why a withdrawal was held, the answer is a list of tags, not "the model said 0.81". The user can be told "confirm your phone number", because the tag says so.

You can delegate selectively. Autopilot on card.testing_pattern is an easy call: the pattern is unambiguous and the cost of a false positive is one retry. Autopilot on cluster.size_5plus is a harder call, because clusters have legitimate explanations (a family, an office). Tags let you hand over the first and keep the second on review. A single score would force you to pick one setting for everything.

Your feedback lands somewhere specific. When you report false_positive on a user, we know which tag was wrong, and the threshold for that tag on your account moves. A score would have to absorb the correction into a model you cannot see.

What we lost, and why we kept the score anyway

Scores are convenient for one thing: sorting. A review queue ordered by score is easier to work than one ordered by "number of tags". So the score stays in the response as risk.score and risk.band, and the review queue uses it.

But the score is derived from the tags, never the other way around. If you only read one field, read decision. If you read two, read the tags.

Try it

Send one signup event from the sandbox and look at the response. The tags will tell you more about that user than any number could.

const { decision, tags } = await ordent.events.send({
  type: "signup",
  user: { id: user.id, email: user.email },
  device: req.ordentDevice,
  ip: req.ip,
});

Get a sandbox key, or read how it works first.

tagsdecisionsproduct

See it on your own traffic.

$99 a month, 10,000 events, sandbox before you pay, money back in 14 days if it doesn't fit.