Skip to content

Object reference

Detailed reference for the four complex objects used in pipeline definitions and queries: event filters, metrics, dimensions, and filters. Each section explains the logic and then provides the field tables.


Event filters

An event filter is one object inside a step's events list. It describes a set of field conditions that must all match a row simultaneously. At least one field must be present; omitted fields are unconstrained.

AND within a single filter

All fields in one filter object are AND-ed:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "category": "widget",
  "action": ["start", "open"],
  "label": "$interaction-ids"   ← resolved to ["id-1", "id-2"] at query time
}

Matches rows where:
  category = "widget"
  AND action IN ("start", "open")
  AND label IN ("id-1", "id-2")

OR across multiple filters

A step can have multiple event filter objects. The step matches a row if any of them matches. Use this when different event shapes should all count for the same step:

1
2
3
4
5
6
7
8
{
  "name": "Positive outcome",
  "events": [
    { "category": "widget", "action": "openchat",  "label": "$interaction-ids" },
    { "category": "widget", "action": "leadform",  "label": "$interaction-ids" },
    { "category": "widget", "action": "starttask", "label": "$interaction-ids" }
  ]
}

This is equivalent to a single filter with a list for action, but multiple objects are useful when the cases need different field combinations, not just different values for the same field.

Filter fields

Field Type Semantics
vendor string, list, or $ref Event vendor. Exact match (or IN list).
category string, list, or $ref Event category. Exact match (or IN list).
action string, list, or $ref Event action. Exact match (or IN list).
label string, list, or $ref Event label. Exact match (or IN list).
room_ids string, list, or $ref Room IDs. Uses hasAny — a row matches if any of the event's room IDs appear in the filter list.
properties list of "key=value" strings Matched against the event's properties array using has(). All entries AND-ed. No $ref support.

Value set references

vendor, category, action, label, and room_ids each accept a value set reference: a string starting with $. At query time the API replaces it with the stored list for the requesting organization. If the value set doesn't exist, that field contributes no filter condition and the step is unconstrained on it.

Form Example
String "action": "click"
List of strings "action": ["start", "click"]
Value set reference "label": "$interaction-ids"

The properties field

properties is a list of "key=value" strings. Each entry is checked with has(properties, 'key=value') and all entries must pass (AND). It does not support value set references.

1
2
3
4
5
{
  "category": "shopping-cart",
  "action": "purchased",
  "properties": ["with_real_conversation=true", "currency=EUR"]
}

Metrics

Metrics are optional sub-queries attached to a step. They are only evaluated by the step-detail endpoint — the counts endpoint ignores them entirely.

While a step's count answers "how many distinct visitors matched this step?", a metric answers a deeper question: "of those visitors, how were they distributed by goal?" or "what was the total cart value?".

Metric object

Attribute Type Description
name string Label for the metric. Used as the key in the step-detail data response. Optional.
measure object What to aggregate. Required.
group_by array Event field names to group results by. Empty list produces a single aggregate row.
mapping_functions object Maps group_by field names to ID-to-name translation functions. All keys must also appear in group_by.

Measure

The measure object specifies what to aggregate and how.

Attribute Type Description
field string The event field to aggregate. Required.
aggregations array Non-empty list of aggregation functions to apply. Required.

Supported fields and their allowed aggregations:

Field Allowed aggregations
event_id count, count_distinct
visitor_id count, count_distinct
session_id count, count_distinct
user_id count, count_distinct
value count, count_distinct, sum, avg, min, max
dim1dim5 count, count_distinct, sum, avg, min, max

You can request multiple aggregations on the same field in one metric. This produces one result row with a column for each:

1
2
3
4
{
  "name": "Cart value",
  "measure": { "field": "value", "aggregations": ["sum", "avg"] }
}

Result row: { "sum_value": 14200.0, "avg_value": 142.0 }

group_by

group_by splits results into one row per distinct combination of the listed field values. Omitting it (or passing an empty list) produces a single aggregate row.

Supported group_by fields: action, category, label, vendor, room_ids, dim1dim5, geo_country, geo_city, device_type, browser_name, os_name

1
2
3
4
5
{
  "name": "Visitors by country and device",
  "measure": { "field": "visitor_id", "aggregations": ["count_distinct"] },
  "group_by": ["geo_country", "device_type"]
}

Result rows:

1
2
3
4
5
[
  { "geo_country": "FI", "device_type": "desktop", "count_distinct_visitor_id": 320 },
  { "geo_country": "FI", "device_type": "mobile",  "count_distinct_visitor_id": 180 },
  { "geo_country": "SE", "device_type": "desktop", "count_distinct_visitor_id": 95  }
]

mapping_functions

Raw event data often contains opaque IDs in fields like label (goal IDs, interaction IDs). mapping_functions instructs the step-detail endpoint to translate those IDs to human-readable names before returning results. Unknown IDs are kept as-is.

1
"mapping_functions": { "label": "f$goals" }

The key is the group_by field to translate; the value is a registered function ID:

Function ID Translates
f$goals Goal IDs → goal names
f$interactions Interaction IDs → interaction names

Before translation:

1
{ "label": "goal-abc-123", "count_distinct_visitor_id": 42 }
After translation:
1
{ "label": "Newsletter signup", "count_distinct_visitor_id": 42 }


Dimensions

Why dimensions?

Filtering by a property like "interaction" across a multi-step pipeline has two complications:

  1. Which field carries the value? The matching field can differ per step, or the same field can carry different values on different event types — so you can't blindly filter every step on the same field.
  2. What if a step's events don't have the field at all? Goal events don't have interaction IDs in their label; widget events don't have goal IDs. There is no field to filter on directly, yet you still want those steps to be narrowed to only sessions that matched on another step.

A dimension declaration solves both at definition time: for each step you specify either which field to match directly (field), or which other step's matching sessions to inherit (cohort_from_step). At query time you pass a single filter value and the API applies the correct logic per step automatically.

This separates what to measure (the pipeline definition) from how to slice it (the query-time filter value).

Dimension object

Attribute Type Description
name string Unique identifier within this pipeline. Required.
label string Optional human-readable label.
partial boolean If true, this dimension covers only a subset of steps. Default false.
step_mappings array Required. One entry per step (full dimension) or per covered step (partial).
pageview_cohort_from_step integer Optional. Step index whose matching session_ids are used to filter pageview counts. Not allowed on partial dimensions.

Step mappings — two modes

Each entry in step_mappings tells the query engine how to apply the dimension's filter to one step. Exactly one of field or cohort_from_step must be present per mapping.

Attribute Type Description
step_index integer Zero-based index of the step this mapping belongs to. Required.
field string Direct event field to filter by (e.g. geo_city, geo_country). Mutually exclusive with cohort_from_step.
cohort_from_step integer Step index whose matching session_ids restrict this step (cohort join). The referenced step must have a direct field mapping in the same dimension. Mutually exclusive with field.

Supported field values: action, category, label, vendor, room_ids, dim1dim5, geo_country, geo_city, device_type, browser_name, os_name

Direct field mapping

The step is filtered directly on the named event field. Use this when the field carries the values you want to filter by on every step.

Consider a two-step widget pipeline where both steps are widget events and label holds the interaction ID. Both steps can be mapped directly:

1
2
3
4
5
6
7
8
9
{
  "name": "interaction",
  "label": "Interaction",
  "step_mappings": [
    { "step_index": 0, "field": "label" },
    { "step_index": 1, "field": "label" }
  ],
  "pageview_cohort_from_step": 0
}

Cohort mapping

Some steps don't carry the field you want to filter by. In a three-step pipeline — Impressions (widget), Engaged (widget), Goals reached (goal) — the widget steps use label for interaction IDs, but the goal step uses label for goal IDs. You can't filter the goal step directly by interaction ID, but you can restrict it to sessions that matched the interaction filter on an earlier step:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "name": "interaction",
  "label": "Interaction",
  "step_mappings": [
    { "step_index": 0, "field": "label" },          // widget events: label = interaction ID
    { "step_index": 1, "field": "label" },          // widget events: label = interaction ID
    { "step_index": 2, "cohort_from_step": 0 }      // goal events: label = goal ID, so inherit sessions from step 0
  ],
  "pageview_cohort_from_step": 0
}

The reverse — a goal dimension that slices by goal ID — works the same way in the opposite direction: the goal step gets a direct field mapping, and the widget steps get a cohort from it:

1
2
3
4
5
6
7
8
9
{
  "name": "goal",
  "label": "Goal",
  "step_mappings": [
    { "step_index": 0, "cohort_from_step": 2 },     // widget events: no goal IDs in label
    { "step_index": 1, "cohort_from_step": 2 },     // widget events: no goal IDs in label
    { "step_index": 2, "field": "label" }            // goal events: label = goal ID
  ]
}

Cohort isolation

When a cohort source step is evaluated, it is filtered only by the dimension that defines the cohort. Other active dimension filters don't bleed into that subquery, preventing unintended cross-dimension interactions.

Partial dimensions

By default (full dimension), every step must have exactly one mapping — step_index values must form the complete sequence 0, 1, ..., N-1. Setting "partial": true removes that requirement: the dimension only covers the steps listed in step_mappings, and all other steps are completely unaffected when this dimension is used as a filter.

1
2
Full dimension (3-step pipeline):    step 0 ✓   step 1 ✓   step 2 ✓
Partial dimension:                   step 0 ✗   step 1 ✗   step 2 ✓

Combining partial dimensions to filter "by project"

The real power of partial dimensions is applying multiple of them together in a single query so that they collectively cover all steps. Because each partial dimension only filters the steps it declares, you can compose them without one bleeding into the other's steps.

A practical example: you have a three-step pipeline — Impressions (widget), Engaged (widget), Goals reached (goal). Each project in your system has its own set of interaction IDs and goal IDs. Defining two partial dimensions lets you filter the whole pipeline by project at query time:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[
  {
    "name": "interaction",
    "label": "Interaction",
    "partial": true,
    "step_mappings": [
      { "step_index": 0, "field": "label" },
      { "step_index": 1, "field": "label" }
    ]
  },
  {
    "name": "goal",
    "label": "Goal",
    "partial": true,
    "step_mappings": [
      { "step_index": 2, "field": "label" }
    ]
  }
]

At query time, pass both filters populated with IDs from a single project:

1
2
3
4
"filters": [
  { "dimension_name": "interaction", "values": ["int-aaa", "int-bbb"] },
  { "dimension_name": "goal",        "values": ["goal-zzz"] }
]

Steps 0 and 1 are restricted to the project's interaction IDs; step 2 is restricted to the project's goal IDs. Together, the two partial dimensions act as a single "filter by project" — without any full-dimension cohort wiring needed.

Additional rules for partial dimensions:

  • At least one step_mapping required.
  • step_index values must be unique and within [0, N-1].
  • Only direct field mappings — no cohort_from_step.
  • pageview_cohort_from_step not allowed.

Validation rules (full dimensions)

  • step_mappings must contain exactly one entry per pipeline step (step_index values 0, 1, ..., N-1).
  • field and cohort_from_step are mutually exclusive per mapping.
  • A cohort_from_step source must have a direct field mapping in the same dimension.
  • pageview_cohort_from_step must reference a step with a direct field mapping in this dimension.
  • Dimension names must be unique within a pipeline.

Filters

Filters are passed in the body of a counts or step-detail request and do not modify the pipeline definition. Two types can be combined in the same request.

Base filters

A global pre-filter applied to all steps before any step-specific event matching. Useful for restricting an entire query to a geographic region or a set of rooms.

Supported fields: geo_country, geo_city, room_ids.

Attribute Type Description
field string One of geo_city, geo_country, room_ids. Required.
values array Non-empty list of strings. Required.
apply_to_pageview boolean Whether this filter also applies to pageview counts. Default true.
1
2
3
4
"base_filters": [
  { "field": "geo_country", "values": ["FI", "SE"] },
  { "field": "geo_city", "values": ["Helsinki"], "apply_to_pageview": false }
]

Multiple base filter entries are all applied (AND).

Active dimension filters

References a named dimension on the pipeline definition and restricts each step's count to events matching the given values. For cohort-mapped steps the cohort is derived from sessions that matched the filter on the source step.

The pipeline definition must have a dimension with the given dimension_name. Unknown names are rejected with 400.

Attribute Type Description
dimension_name string Name of the dimension as defined on the pipeline. Required.
values array Non-empty list of strings. Required.
apply_to_pageview boolean Whether this filter restricts pageview counts via pageview_cohort_from_step. Default true.

Multiple filters entries are AND-ed. apply_to_pageview defaults to true if omitted.

Example — base filter narrows by country; dimension filter further narrows by a pipeline-declared interaction dimension (which maps to label on each step, not a geo field):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "pipeline_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "start": "2024-01-01T00:00:00Z",
  "end": "2024-01-31T23:59:59Z",
  "include_pageview_counts": true,
  "base_filters": [
    { "field": "geo_country", "values": ["FI"], "apply_to_pageview": true }
  ],
  "filters": [
    { "dimension_name": "interaction", "values": ["int-abc-123"], "apply_to_pageview": true }
  ]
}