# Segmentation language

Pushwoosh offers a powerful segmentation engine for building granular Segments based on Tag values. **Segmentation Language** is a specific way of writing and combining segmentation criteria to describe a particular group of users that match those criteria and treat them as a single audience segment.

This article describes the basic concepts and syntax of the Segmentation Language and provides comprehensive examples of building segmentation criteria for various cases.

## Basics

Each device in your user base has specific attributes associated with it via **Tag values**.

For example, let's say a user named Jane lives in Tokyo, and her age is 28. That user will have the following Tags set for their device:

* Name: Jane
* City: Tokyo
* Age: 28

To target Jane, you will need to describe a segment as follows:

`T("Name", eq, "Jane") * T("Age", eq, 28) * T("City", eq, "Tokyo")`

This combination of conditions is a **filter expression** used in Segmentation Language for describing groups of users aka audience Segments.

## Filter expressions

Filter expression is a string that contains a condition or a combination of conditions describing the segment you need.

### Conditions

Each condition describes a segment of devices that match the criteria specified in that condition.

For example, the following condition builds a segment of users who live in Tokyo:

`T("City", e, "Tokyo")`

where

* T is a Tag (condition type);
* eq is an operator to apply;
* "Tokyo" is a Tag value users have associated with their devices.

#### Condition types

The following condition types are available for segmentation:

* **A** (Application) – describes a segment of devices with a particular app installed. Aliases: **App**, **Application**;
* **T** (Tag) – describes a segment of devices with the specified Tag values;
* **AT** (App-scoped tag) – looks up a tag value within a specific application; app code is required as the first argument. Alias: **Tag**;
* **Event** – describes a segment of devices triggered a specific Pushwoosh event;
* **Geo** – describes a segment of devices within a specific geographic radius;
* **BTTS** – describes a segment of devices based on their best time to send;
* **Updated** – describes a segment of devices based on their last update timestamp;
* **Segment** – references another filter/segment by its code;

### Operations with conditions

For building sophisticated segments, the following operations can be applied to conditions within the filter expression:

#### Union (+)

Joins the segments, i.e., builds a new segment of users who match at least one of the specified conditions.

<img src="/filters-segmentation-language-1.webp" alt=""/>

For example, to target users who live in Tokyo or in Osaka, you'll need to describe the segment with the following conditions:

`T("City", eq, "Tokyo") + T("City", eq, "Osaka")`

<Aside type="note">
Equivalent to logical **disjunction** (**OR**). Can also be written as **or** operator.
</Aside>

#### Intersection (\*)

Constructs a segment of users belonging to both segments described by the conditions. Thus, only those users who comply with each condition you specify will be included.

<img src="/filters-segmentation-language-2.webp" alt=""/>

The following expression describes a segment of users who both live in Tokyo and have specified their names:

`T("City", eq, "Tokyo") * T("Name", any)`

<Aside type="note">
Analog to logical **conjunction** (**AND**). Can also be written as **and** operator.
</Aside>

#### Difference (\\)

Builds a segment of users who belong to one of the described segments and do not belong to another.

<img src="/filters-segmentation-language-3.webp" alt=""/>

Users who live in Tokyo but have not given you their names will be described as follows:

`T("City", eq, "Tokyo") \ T("Name", any)`

<Aside type="note">
Equivalent to logical **negation** (**NOT**). Can also be written as **not** operator.
</Aside>

#### Parentheses

Determine the order of operations to perform with the conditions in your filter expression.

For example, the following filter expression will, at first, obtain a segment of the 12345-67890 subscribers whose age is 18 and then subtract all men of that segment:

`( A("12345-67890") * T("Age", eq, 18) ) \ T("Gender", eq, "Male")`

## Tag conditions operators

For each Tag type, their own operators are applied.

### Integer Tags Operators

* **eq** - equal to a specified value
* **noteq** - not equal to a specified value
* **lte** - less than or equal to a specified value
* **gte** - greater than or equal to a specified value
* **in** - any of specified values
* **notin** - not equal to any of specified values
* **between** - in a specified range
* **any** - devices with any values set for the tag
* **notset** - devices with no value set for the tag

<Aside type="note" title="Integer Tags syntax example">
`T("int", eq, 42)`
</Aside>

### String Tags Operators

* **eq** - equal to a specified value
* **noteq** - not equal to a specified value
* **startswith** - starts with a specified prefix
* **endswith** - ends with a specified suffix
* **contains** - contains a specified substring
* **in** - equal to any of specified values
* **notin** - not equal to any of specified values
* **any** - devices with any values set for the tag
* **notset** - devices with no value set for the tag

<Aside type="note" title="String Tags syntax examples">
* `T("str", eq, "kangaroo")` - exact match
* `T("str", startswith, "kang")` - starts with "kang"
* `T("str", endswith, "roo")` - ends with "roo"
* `T("str", contains, "nga")` - contains "nga" anywhere in the string
</Aside>

### List Tags Operators

* **in** - devices with any of the specified tag values
* **notin** - none of the specified tag values associated with the device
* **any** - devices with any values set for the tag
* **notset** - devices with no value set for the tag

<Aside type="note" title="List Tags syntax example">
`T("list", notin, ["kangaroo", "raccoon"])`
</Aside>

### Date Tags Operators

* **eq** - equal to the date specified
* **noteq** - not equal to the date specified
* **lte** - before or on the date specified
* **gte** - after or on the date specified
* **in** - equal to any of specified dates
* **notin** - not equal to any of specified dates
* **between** - in a specified range
* **any** - devices with any values set for the tag
* **notset** - devices with no value set for the tag
* **match** - matches a specified month of the year and day of the month.

<Aside type="note" title="match operator examples">


* `AT("XXXXX-XXXXX", "Date tag", match month 4 day 1)` - devices that have the "Date tag" set to the 1st of April of any year.
* `AT("XXXXX-XXXXX", "Date tag", match month "now" day 13)` - devices that have the "Date tag" set to the 13th day of the current month.
* `AT("XXXXX-XXXXX", "Date tag", match month "now" day "now+2")` - devices that have the "Date tag" set to the day after tomorrow. Common use case: birthday greetings.
</Aside>

<Aside type="note" title="Match operator examples for anniversary and birthday segments">
You can [segment users based on recurring calendar dates](/product/audience-data-and-segmentation/segmentation/create-segments/anniversary-segments), such as birthdays or anniversaries. In these cases, only the month and day are taken into account, while the year is ignored.

* `AT("XXXXX-XXXXX", "birthday", match month "now" day "now")`
   **Targets users whose birthday is today** (same day and month as today).
   *Use this to send birthday greetings or special offers on the user's actual birthday.*

* `AT("XXXXX-XXXXX", "birthday", match month "now" day "now+N")`
   **Targets users whose birthday is in N days** (same month and day, N days from today).
   *Use this to prepare users in advance, for example, send countdown messages or upcoming event reminders.*

* `AT("XXXXX-XXXXX", "birthday", match month "now" day "now-N")`
   **Targets users whose birthday was N days ago**.
   *Use this for belated birthday messages or follow-ups like feedback requests.*
* `AT("XXXXX-XXXXX", "birthday", match month "now" day N)`
   **Targets users whose birthday is on the Nth day of the current month**, regardless of the year.
   *Use this when planning fixed monthly campaigns tied to specific dates (e.g., monthly loyalty rewards on the 10th).*
</Aside>

* **daysago eq** - equal to a specified number of days before the present day
* **daysago noteq** - not equal to a specified number of days before the present day
* **daysago lte** - less than or equal to a specified number of days before the present day
* **daysago gte** - greater than or equal to specified number of days  before the present day
* **daysago between** - between the specified numbers of days

<Aside type="note" title="daysago operator examples">

* `T("Date tag", daysago, eq, 0)` - the present day from 00:00 to the current moment
* `T("Date tag", daysago, eq, 1)` - from 00:00 of the previous day to 00:00 of the present day
* `T("Date tag", daysago, gte, 1)` - all the time to 00:00 of the present day
* `T("Date tag", daysago, lte, 7)` - from 00:00 of the day 6 days ago to the current moment
* `T("Date tag", daysago, between, [2,7])` - from 7 to 2 days ago.
</Aside>

* **minutesago lte** - less than or equal to a specified number of minutes before the present moment
* **minutesago gte** - greater than or equal to a specified number of minutes before the present moment

<Aside type="note" title="minutesago operator examples">

* `T("Date tag", minutesago, lte, 30)` - the last 30 minutes;
* `T("Date tag", minutesago, gte, 60)` - 60 or more minutes ago;
* `T("Date tag", minutesago, lte, 1)` - within the last minute.
</Aside>

* **daysahead** - in N to M days from the present day (UTC), inclusive on both ends

<Aside type="note" title="daysahead operator examples">

`daysahead` takes a `[from, to]` interval (days from today's UTC midnight, both ends inclusive). Unlike `daysago`, it has no sub-operator — only the interval form.

* `T("Date tag", daysahead, [0, 0])` - the present day from 00:00 to 23:59:59
* `T("Date tag", daysahead, [1, 1])` - the next day from 00:00 to 23:59:59
* `T("Date tag", daysahead, [2, 5])` - any moment from the start of 2 days from now to the end of 5 days from now
</Aside>

<Aside type="note" title="date operator example">
* `T("Date tag", eq "2022-12-05 00:00:00")`
</Aside>

### Boolean Tags Operators

* **eq** - equal to a specified value
* **noteq** - not equal to a specified value
* **any** - devices with any values set for the tag
* **notset** - devices with no value set for the tag

<Aside type="note" title="Boolean Tags syntax example">
 `T("bool", eq, true)`
</Aside>

### Price Tags Operators

* **eq** - equal to a specified value
* **noteq** - not equal to a specified value
* **lte** - less than or equal to a specified value
* **gte** - greater than or equal to a specified value
* **in** - equal to any of specified values
* **notin** - not equal to any of specified values
* **between** - in a specified range
* **any** - devices with any values set for the tag
* **notset** - devices with no value set for the tag

<Aside type="note" title="Price Tags syntax example">
`T("price", between, ["4.2", "6.9"])`
</Aside>

### Version Tags Operators

* **eq** - equal to a specified value
* **noteq** - not equal to a specified value
* **lte** - less than or equal to a specified value
* **gte** - greater than or equal to a specified value
* **in** - equal to any of specified values
* **notin** - not equal to any of specified values
* **between** - in a specified range
* **any** - devices with any values set for the tag
* **notset** - devices with no value set for the tag

<Aside type="note" title="Version Tags syntax example">
`T("version", lte, "4.2")`
</Aside>

## Event conditions operators

<Aside type="note">
Please keep in mind the event conditions are app-specific so the app code should be specified in your filter expressions along with the event name.
</Aside>

### Event count

* **count gte** - devices triggered the event more than or exactly n times
* **count lte** - devices triggered the event less than or exactly n times
* **count eq** - devices triggered the event exactly n times
* **count noteq** - devices triggered the event any times but not equal to n

<Aside type="note" title="Event count syntax example">
 `Event("11111-11111", "Level reached", count gte 10) // 11111-11111 is an app code`
</Aside>

### Event date

* **date gte** - devices triggered the event later than or exactly on the specified date
* **date lte** - devices triggered the event earlier than or exactly on the specified date
* **date eq** - devices triggered the event exactly on the specified date
* **date noteq** - devices triggered the event whenever but not on the specified date
* **date in** - devices triggered the event on any of the specified dates
* **date notin** - devices triggered the event whenever but not on any of the specified dates
* **date between** - devices triggered the event within a specified period
* **date daysago eq** - event trigger date is equal to a specified number of days before the present day
* **date daysago noteq** - event trigger date is not equal to a specified number of days before the present day
* **date daysago lte** - event trigger date is less than or equal to a specified number of days before the present day
* **date daysago gte** - event trigger date is greater than or equal to specified number of days  before the present day
* **date daysago between** - event trigger date is between the specified numbers of days
* **date daysahead** - event trigger date is in a specified number of days from the present day (interval is inclusive on both ends, see Date Tags Operators above for full semantics)
* **date minutesago lte** - event trigger date is less than or equal to specified number of minutes before the present moment
* **date minutesago gte** - event trigger date is greater than or equal to specified number of minutes before the present moment

<Aside type="note" title="Event date syntax examples">

- `Event("11111-11111", "Level reached", date gte "2022-01-01 01:02:03")`
- `Event("11111-11111", "Level reached", date in ["2022-01-01 01:02:03", "2022-01-01 02:03:04"])`
- `Event("11111-11111", "Level reached", date between "2022-01-01 01:02:03" "2022-01-01 02:03:04")`
- `Event("11111-11111", "Level reached", date daysahead 0 7)` - events with a trigger date within the next 7 days
- `Event("11111-11111", "Level reached", date minutesago lte 30)` - events within last 30 minutes
- `Event("11111-11111", "Level reached", date minutesago gte 60)` - events 60+ minutes ago

</Aside>

### Event platforms

Filter events by the platform where they were triggered.

* **platforms** - list of platforms (e.g., ["ios", "android"])

<Aside type="note" title="Event platforms syntax example">
`Event("11111-11111", "Level reached", platforms ["android", "ios"], count gte 5)`
</Aside>

### Event attributes

Event conditions can filter based on event attribute values. Attributes support various data types with their corresponding operators.

#### Integer Event Attributes

* **attribute "name" eq** - attribute equals a specified value
* **attribute "name" noteq** - attribute not equal to a specified value
* **attribute "name" gte** - attribute greater than or equal to a specified value
* **attribute "name" lte** - attribute less than or equal to a specified value
* **attribute "name" between** - attribute in a specified range
* **attribute "name" in** - attribute equals any of specified values
* **attribute "name" notin** - attribute not equal to any of specified values
* **attribute "name" any** - any value set for the attribute
* **attribute "name" notset** - no value set for the attribute

<Aside type="note" title="Integer attribute syntax examples">

* `Event("11111-11111", "Purchase", attribute "amount" eq 42)`
* `Event("11111-11111", "Purchase", attribute "amount" between 10 100)`
* `Event("11111-11111", "Purchase", attribute "amount" in [10, 20, 30])`

</Aside>

#### String Event Attributes

* **attribute "name" eq** - attribute equals a specified value
* **attribute "name" noteq** - attribute not equal to a specified value
* **attribute "name" startswith** - attribute starts with a specified prefix
* **attribute "name" endswith** - attribute ends with a specified suffix
* **attribute "name" contains** - attribute contains a specified substring
* **attribute "name" in** - attribute equals any of specified values
* **attribute "name" notin** - attribute not equal to any of specified values
* **attribute "name" any** - any value set for the attribute
* **attribute "name" notset** - no value set for the attribute

<Aside type="note" title="String attribute syntax examples">

* `Event("11111-11111", "Page View", attribute "url" startswith "https://example.com")`
* `Event("11111-11111", "Page View", attribute "url" endswith ".html")`
* `Event("11111-11111", "Page View", attribute "url" contains "/products/")`
* `Event("11111-11111", "Button Click", attribute "button_name" in ["submit", "cancel"])`

</Aside>

#### Boolean Event Attributes

* **attribute "name" eq** - attribute equals true or false
* **attribute "name" noteq** - attribute not equal to true or false

<Aside type="note" title="Boolean attribute syntax example">
`Event("11111-11111", "Feature Toggle", attribute "enabled" eq true)`
</Aside>

#### Date Event Attributes

* **attribute "name" eq** - attribute equals a specified date
* **attribute "name" noteq** - attribute not equal to a specified date
* **attribute "name" gte** - attribute after or on a specified date
* **attribute "name" lte** - attribute before or on a specified date
* **attribute "name" between** - attribute within a specified date range
* **attribute "name" in** - attribute equals any of specified dates
* **attribute "name" notin** - attribute not equal to any of specified dates
* **attribute "name" daysago eq/noteq/gte/lte/between** - attribute relative to days ago
* **attribute "name" daysahead from to** - attribute in a specified interval of days from the present day (interval is inclusive on both ends, see Date Tags Operators above for full semantics)
* **attribute "name" minutesago gte/lte** - attribute relative to minutes ago
* **attribute "name" any** - any value set for the attribute
* **attribute "name" notset** - no value set for the attribute

<Aside type="note" title="Date attribute syntax examples">

* `Event("11111-11111", "Subscription", attribute "start_date" eq "2022-01-01 01:02:03")`
* `Event("11111-11111", "Subscription", attribute "start_date" between "2022-01-01 00:00:00" "2022-12-31 23:59:59")`
* `Event("11111-11111", "Subscription", attribute "start_date" daysago lte 30)` - within last 30 days
* `Event("11111-11111", "Subscription", attribute "renewal_at" daysahead 0 30)` - renewals in the next 30 days
* `Event("11111-11111", "Subscription", attribute "start_date" minutesago gte 60)` - 60+ minutes ago

</Aside>

#### Price Event Attributes

* **attribute "name" eq** - attribute equals a specified price value
* **attribute "name" noteq** - attribute not equal to a specified price value
* **attribute "name" gte** - attribute greater than or equal to a specified price
* **attribute "name" lte** - attribute less than or equal to a specified price
* **attribute "name" between** - attribute in a specified price range
* **attribute "name" in** - attribute equals any of specified prices
* **attribute "name" notin** - attribute not equal to any of specified prices
* **attribute "name" any** - any value set for the attribute
* **attribute "name" notset** - no value set for the attribute

<Aside type="note" title="Price attribute syntax example">
`Event("11111-11111", "Purchase", attribute "total_price" between 10.00 50.00)`
</Aside>

#### List Event Attributes

* **attribute "name" in** - attribute contains any of specified values
* **attribute "name" notin** - attribute doesn't contain any of specified values
* **attribute "name" any** - any value set for the attribute
* **attribute "name" notset** - no value set for the attribute

<Aside type="note" title="List attribute syntax example">
`Event("11111-11111", "Cart Update", attribute "product_ids" in ["prod-123", "prod-456"])`
</Aside>

## Additional condition types

### Geo condition

Target devices based on geographic location within a specified radius.

**Syntax:** `Geo("<app-code>", <latitude>, <longitude>, <range-in-km>)`

<Aside type="note" title="Geo syntax example">
`Geo("11111-11111", 53.2734, -7.77832031, 100.05)` - devices within 100.05 km of coordinates
</Aside>

### BTTS condition

Target devices by their best time to send notifications (hour of day, 0-23).

**Operators:**
* **any** - any best time to send value set
* **eq** - exact hour match
* **noteq** - not equal to hour
* **gte** - hour greater than or equal to
* **lte** - hour less than or equal to

<Aside type="note" title="BTTS syntax examples">

* `BTTS("11111-11111", eq 10)` - devices with best time at 10:00
* `BTTS("11111-11111", gte 18)` - devices with best time from 18:00 onwards
* `BTTS("11111-11111", any)` - devices with any best time value

</Aside>

### Updated condition

Filter devices by their last update timestamp.

**Operators:**
* **gte** - updated after or on specified date
* **lte** - updated before or on specified date
* **between** - updated within date range

<Aside type="note" title="Updated syntax examples">

* `Updated("11111-11111", gte "2022-01-01 00:00:00")` - devices updated after Jan 1, 2022
* `Updated("11111-11111", lte "2022-12-31 23:59:59")` - devices updated before Dec 31, 2022
* `Updated("11111-11111", between "2022-01-01 00:00:00" "2022-12-31 23:59:59")` - devices updated in 2022

</Aside>

### Segment condition

Reference another filter/segment by its code.

<Aside type="note" title="Segment syntax example">
`Segment("11111-11111", "22222-22222")` - reference filter with code "22222-22222"
</Aside>

## Application condition device presence flags

Application conditions support additional flags to control device and token filtering:

* **with_tokens** - devices with push notification tokens
* **without_tokens** - devices without push notification tokens
* **with_devices** - users with registered devices
* **without_devices** - users/profiles without registered devices

<Aside type="note" title="Application flags syntax examples">

* `A("11111-11111", ["ios", "android"], [with_tokens])` - devices with push tokens
* `A("11111-11111", ["ios", "android"], [without_tokens])` - devices without push tokens
* `A("11111-11111", [], [with_devices])` - all devices with device records
* `A("11111-11111", ["ios", "android"], [without_tokens, with_devices])` - devices without tokens but with device records

</Aside>

## Filter expression examples

<Aside type="note">
When writing JSON queries, be sure to escape quotes (`"`) and backslashes (`\`) with a backslash (`\`).
For an example request, see [/exportSegment](/developer/api-reference/segmentation-filters-api/#exportsegment).
</Aside>

### Basic examples

1. iOS and Android devices with the app installed and with push tokens:

```json
A("11111-11111", ["ios","android"], [with_tokens])
```

2. iOS and Android devices with the app installed but without push tokens:

```json
A("11111-11111", ["ios","android"], [without_tokens])
```

3. iOS and Android devices with the app installed, whether they have push tokens or not:

```json
A("11111-11111", ["ios","android"], [with_tokens, without_tokens])
```

4. All app subscribers who have purchased something in the app:

```json
AT("11111-11111", "In-App Purchase", gte, 1)
```

### Advanced examples

5. Users in Tokyo who have opened the app in the last 7 days:

```json
T("City", eq, "Tokyo") * Event("11111-11111", "App Open", date daysago lte 7)
```

6. Users who made a purchase over $50 in the last 30 days:

```json
Event("11111-11111", "Purchase", attribute "total_price" gte 50.00, date daysago lte 30)
```

7. Users whose names start with "J" or end with "e":

```json
T("Name", startswith, "J") + T("Name", endswith, "e")
```

8. Active iOS users within 100km of New York who haven't purchased recently:

```json
A("11111-11111", ["ios"], [with_tokens]) * Geo("11111-11111", 40.7128, -74.0060, 100) \ Event("11111-11111", "Purchase", date daysago lte 30)
```

9. Users with best time to send between 9 AM and 5 PM:

```json
BTTS("11111-11111", gte 9) * BTTS("11111-11111", lte 17)
```

10. Users who triggered a specific event on Android or iOS in the last hour:

```json
Event("11111-11111", "Button Click", platforms ["android", "ios"], date minutesago lte 60)
```

11. Devices updated in the last 3 months with app version 4.2 or higher:

```json
Updated("11111-11111", gte "2024-07-01 00:00:00") * AT("11111-11111", "App Version", gte, "4.2")
```