PlunkPlunk
Guides

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 patternTargetsExamples
emailThe contact's email addressemail
subscribedThe contact's subscription statesubscribed
createdAt, updatedAtBuilt-in contact timestampscreatedAt
data.<path>Custom contact data — supports nested pathsdata.plan, data.profile.tier
event.<eventName>Custom events tracked via /v1/trackevent.signed_up
email.<activity>Email engagement: sent, delivered, opened, clicked, bounced, complainedemail.opened
segment.<segmentId>Membership of another segmentsegment.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.

OperatorWhat it does
equalsExact match. Case-insensitive on email, exact on data.*.
notEqualsNegation of equals.
containsCase-insensitive substring match.
notContainsNegation of contains.

Yes/no fields

For subscribed and any data.<key> that holds true or false.

OperatorWhat it does
equalsMatch true or false.
notEqualsNegation.

Dates and timestamps

For createdAt, updatedAt, and any data.<key> that holds an ISO 8601 date string.

OperatorWhat it does
equals / notEqualsMatch the timestamp. If the value is just a date (YYYY-MM-DD), the comparison covers the whole UTC day.
greaterThan / lessThanStrictly after / strictly before.
greaterThanOrEqual / lessThanOrEqualInclusive variants.
withinWithin the last N units. Pair with unit: "days" / "hours" / "minutes".
olderThanMore 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.

OperatorWhat it does
existsThe key is present on the contact and is not null.
notExistsThe key is missing or explicitly null.

Events and email activity

These operators apply to both event.<eventName> (custom events) and email.<activity> (email engagement).

OperatorWhat it does
triggeredThe contact has had this event at least once, ever.
notTriggeredThe contact has never had this event.
triggeredWithinAt least one occurrence in the last N units. Pair with unit.
triggeredOlderThanHas had this event, but not within the last N units. Pair with unit.
notTriggeredWithinHas 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.

OperatorWhat it does
memberOfSegmentContact is currently in the referenced segment.
notMemberOfSegmentContact 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 }
      ]
    }
  ]
}