Segment filter reference
How to write filters for dynamic segments, campaign audiences, and workflow conditions
The same filter format powers three things: dynamic segments, campaign audiences with audienceType: "FILTERED", and CONDITION steps inside workflows. Learn it once, use it everywhere.
For a conceptual introduction, see the Segments concept page.
How a filter is structured
A filter has two parts: a top-level connector (AND or OR) and a list of groups. Each group holds one or more conditions, which are combined with AND inside the group. The top-level connector then joins the groups together.
That sounds complicated, so a quick example: "subscribed users and on the Pro plan and (opened or clicked an email recently)".
{
"logic": "AND",
"groups": [
{
"filters": [
{ "field": "subscribed", "operator": "equals", "value": true },
{ "field": "data.plan", "operator": "equals", "value": "pro" }
]
},
{
"filters": [],
"conditions": {
"logic": "OR",
"groups": [
{ "filters": [{ "field": "email.opened", "operator": "triggeredWithin", "value": 14, "unit": "days" }] },
{ "filters": [{ "field": "email.clicked", "operator": "triggeredWithin", "value": 14, "unit": "days" }] }
]
}
}
]
}Groups can nest by setting conditions on a group — that lets you build "this AND (that OR this)" expressions without flattening logic. In the dashboard, the segment builder UI handles this for you visually.
Fields you can filter on
The field value is namespaced by prefix — the prefix tells Plunk what part of the contact you're querying.
| Field pattern | Targets | Examples |
|---|---|---|
email | The contact's email address | email |
subscribed | The contact's subscription state | subscribed |
createdAt, updatedAt | Built-in contact timestamps | createdAt |
data.<path> | Custom contact data — supports nested paths | data.plan, data.profile.tier |
event.<eventName> | Custom events tracked via /v1/track | event.signed_up |
email.<activity> | Email engagement: sent, delivered, opened, clicked, bounced, complained | email.opened |
segment.<segmentId> | Membership of another segment | segment.cuid_of_other_segment |
Operators
Operators are grouped by the kind of field they work on.
Text fields
For email and any data.<key> that holds a string.
| Operator | What it does |
|---|---|
equals | Exact match. Case-insensitive on email, exact on data.*. |
notEquals | Negation of equals. |
contains | Case-insensitive substring match. |
notContains | Negation of contains. |
Yes/no fields
For subscribed and any data.<key> that holds true or false.
| Operator | What it does |
|---|---|
equals | Match true or false. |
notEquals | Negation. |
Dates and timestamps
For createdAt, updatedAt, and any data.<key> that holds an ISO 8601 date string.
| Operator | What it does |
|---|---|
equals / notEquals | Match the timestamp. If the value is just a date (YYYY-MM-DD), the comparison covers the whole UTC day. |
greaterThan / lessThan | Strictly after / strictly before. |
greaterThanOrEqual / lessThanOrEqual | Inclusive variants. |
within | Within the last N units. Pair with unit: "days" / "hours" / "minutes". |
olderThan | More than N units ago. Pair with unit. |
For custom date fields (data.<key>), within and olderThan only work when the value is stored as an ISO 8601 string (e.g. "2026-05-06T12:00:00Z"). Unix timestamps and other formats won't compare correctly.
Numbers
For any data.<key> that holds a number: equals, notEquals, greaterThan, lessThan, greaterThanOrEqual, lessThanOrEqual. No unit is needed.
Field existence
For any data.<key>, regardless of value type.
| Operator | What it does |
|---|---|
exists | The key is present on the contact and is not null. |
notExists | The key is missing or explicitly null. |
Events and email activity
These operators apply to both event.<eventName> (custom events) and email.<activity> (email engagement).
| Operator | What it does |
|---|---|
triggered | The contact has had this event at least once, ever. |
notTriggered | The contact has never had this event. |
triggeredWithin | At least one occurrence in the last N units. Pair with unit. |
triggeredOlderThan | Has had this event, but not within the last N units. Pair with unit. |
notTriggeredWithin | Has not had this event in the last N units. Includes contacts who have never triggered it. Pair with unit. |
Segment membership
For segment.<segmentId>, where <segmentId> is the ID of another segment in your project.
| Operator | What it does |
|---|---|
memberOfSegment | Contact is currently in the referenced segment. |
notMemberOfSegment | Contact is not in the referenced segment. |
Quick reference: what to pass with each operator
- Need a
value:equals,notEquals,contains,notContains,greaterThan,lessThan,greaterThanOrEqual,lessThanOrEqual,within,olderThan,triggeredWithin,triggeredOlderThan,notTriggeredWithin. - Need a
unit("days","hours", or"minutes"):within,olderThan,triggeredWithin,triggeredOlderThan,notTriggeredWithin. - Need nothing extra:
exists,notExists,triggered,notTriggered,memberOfSegment,notMemberOfSegment.
Examples
Engaged users on the Pro plan
Subscribed Pro-plan users who opened or clicked any email in the last 14 days but haven't clicked anything in the last 30 days.
{
"logic": "AND",
"groups": [
{
"filters": [
{ "field": "subscribed", "operator": "equals", "value": true },
{ "field": "data.plan", "operator": "equals", "value": "pro" }
]
},
{
"filters": [],
"conditions": {
"logic": "OR",
"groups": [
{ "filters": [{ "field": "email.opened", "operator": "triggeredWithin", "value": 14, "unit": "days" }] },
{ "filters": [{ "field": "email.clicked", "operator": "triggeredWithin", "value": 14, "unit": "days" }] }
]
}
},
{
"filters": [
{ "field": "email.clicked", "operator": "notTriggeredWithin", "value": 30, "unit": "days" }
]
}
]
}New trial users without a purchase
Subscribed contacts created in the last 7 days who haven't yet triggered a purchase event.
{
"logic": "AND",
"groups": [
{
"filters": [
{ "field": "subscribed", "operator": "equals", "value": true },
{ "field": "createdAt", "operator": "within", "value": 7, "unit": "days" },
{ "field": "event.purchase", "operator": "notTriggered" }
]
}
]
}Power users above a tier
Members of the power-users segment whose lifetime value is at least 500.
{
"logic": "AND",
"groups": [
{
"filters": [
{ "field": "segment.<powerUsersSegmentId>", "operator": "memberOfSegment" },
{ "field": "data.lifetimeValue", "operator": "greaterThanOrEqual", "value": 500 }
]
}
]
}