> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getzenstep.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Targeting Overview

> Show flows only to the right users, on the right pages, at the right time — an introduction to Zenstep's targeting system.

## How targeting works

Every Zenstep flow has a **targeting configuration** — a set of rules that determine whether the flow should be shown to the current user on the current page.

The targeting engine runs **client-side in the browser** (inside the Zenstep snippet) every time a page loads or the URL changes (SPA navigation). This means:

* No server round-trip per evaluation — instant decision
* Rules are evaluated against the current browser context (URL, user attributes, device, behaviour)
* Targeting is evaluated against all published flows simultaneously

***

## Anatomy of a targeting rule

Every rule has a **type** and evaluates to `true` or `false`. Rules are combined with `and` (all must match) or `or` (any must match) logic.

```json theme={null}
{
  "operator": "and",
  "rules": [
    { "type": "url_path", "operator": "starts_with", "value": "/dashboard" },
    {
      "type": "user_attribute",
      "attribute": "plan",
      "operator": "equals",
      "value": "free"
    }
  ]
}
```

This targeting config shows the flow on any URL starting with `/dashboard` **and** only to users with `plan = "free"`.

***

## Rule types

| Type                                                                    | Description                                   | Plan      |
| ----------------------------------------------------------------------- | --------------------------------------------- | --------- |
| [`url_path`](/targeting-reference/rules#url-path)                       | Match the current page URL path               | All plans |
| [`user_attribute`](/targeting-reference/rules#user-attribute)           | Match a user attribute from `identify()`      | All plans |
| [`device`](/targeting-reference/rules#device)                           | Match device type (desktop / mobile / tablet) | All plans |
| [`query_param`](/targeting-reference/rules#query-parameter)             | Match a URL query parameter                   | All plans |
| [`always`](/targeting-reference/rules#always)                           | Show to everyone, always                      | All plans |
| [`behavior`](/targeting-reference/rules#behavior)                       | Match based on `track()` event history        | Grow+     |
| [`segment`](/targeting-reference/rules#segment)                         | Match a saved reusable segment                | Grow+     |
| [`audience_membership`](/targeting-reference/rules#audience-membership) | Match a GA4 or Clarity-imported audience      | Scale+    |

***

## Combining rules

Rules are combined at two levels:

1. **Top-level operator** (`and` / `or`) — how the rules in the root array are combined
2. **Group rule** — a nested rule that can contain its own rules and operator

```json theme={null}
{
  "operator": "or",
  "rules": [
    { "type": "url_path", "operator": "equals", "value": "/pricing" },
    {
      "type": "group",
      "operator": "and",
      "rules": [
        {
          "type": "url_path",
          "operator": "starts_with",
          "value": "/dashboard"
        },
        {
          "type": "user_attribute",
          "attribute": "plan",
          "operator": "equals",
          "value": "free"
        }
      ]
    }
  ]
}
```

This shows the flow on `/pricing` OR (on any dashboard page AND if the user is on the free plan).

***

## Environments

You can restrict a flow to specific environments (staging vs production):

```json theme={null}
{
  "operator": "and",
  "rules": [...],
  "environments": ["production"]
}
```

Zenstep detects the environment automatically based on hostname. You can override this by setting `data-env` on the snippet script tag:

```html theme={null}
<script
  async
  src="https://cdn.getzenstep.com/v1/snippet.js"
  data-zenstep="YOUR_KEY"
  data-env="staging"
></script>
```

***

## Frequency controls

Targeting determines **if** a flow is shown. **Frequency** controls determine **how often**:

| Frequency         | Behaviour                                                         |
| ----------------- | ----------------------------------------------------------------- |
| `once`            | Show at most once per user (checked via `flow_completions` table) |
| `every_session`   | Show on every new browser session                                 |
| `until_completed` | Show on every page load until the user completes the flow         |

Frequency is set per-flow in the flow editor, not in targeting rules.
