About conditions and the logic engine
A condition decides whether a visitor sees something. One rule format covers every one of those decisions, both in the dashboard and in code. This page covers why there is one engine, and what it can reach.
One rule format, many places
The dashboard uses the visual condition builder in four places, and the SDK evaluates the same rules in each:
- Condition nodes decide which branch a flow takes.
- Experience conditions decide whether an experience starts for a visitor.
- Initialize-open conditions decide whether an experience opens by itself.
- Field option conditions show or hide one option in a field.
One format means one model to learn. Learn how a rule reads in the flow builder, and you can read the rule that gates an experience.
What a rule looks like below
A rule is JSON Logic. The visual builder writes it for you, and you can also write it directly in SDK code:
{
'==': [{ var: 'responses.country' }, 'US']
}Rules sit in groups, and each group is an AND or an OR. Put a group inside another group to build a larger rule.
The format is data, and not code. That is the point. A rule travels from the dashboard to the browser inside the published snapshot. A function cannot travel that way.
What a rule can read
| Source | What it holds |
|---|---|
| Responses | The values your visitors send through the fields of the current experience. |
| Actions | The actions that ran during the flow. |
| Feature flags | Whether Picked allocates this visitor to a flag. |
| Location | The parts of the current URL: pathname, search parameters, hostname, and hash. |
Each one is state the SDK already holds, which is why a rule evaluates without a network request.
Predicates are the escape hatch
The four sources above cover what Picked knows. They do not cover what your application knows: a cart total, an account level, or the profile of a signed-in user.
A predicate gives you that. It is a function that you register on the client, and a rule invokes it by name:
{ invoke: { var: 'predicates.has-items-in-cart' } }The predicate receives a frozen state snapshot and returns a boolean, a string, an array
of strings, or undefined. Because a rule can invoke one, the visual builder in the
dashboard reaches your application data, and nobody writes JSON Logic by hand.
A predicate must stay pure and fast. The SDK can invoke it many times while it evaluates a flow, and everything that waits on the rule waits on the predicate.
Why a precondition is not a condition
The client takes two gates, and they answer different questions:
| Gate | Question |
|---|---|
| Precondition | Must Picked start at all? |
| Condition | Is this visitor eligible? |
A precondition runs at startup, and that has a result which catches people out. A precondition that points at a feature flag reads the bucket of that flag, and a read is what allocates the visitor. Every visitor is therefore allocated to that flag before anything else happens, and that includes a visitor who never reaches the experience the flag controls. See About feature flag allocation.
Related
- Condition builder — the visual editor.
- SDK conditions — the JSON Logic shapes.
- Predicates — the state snapshot and the return types.
