Filters
Every metric, and searching customers, take a filter: a condition, and
only the customers it matches are counted or listed.
Example: Customers in the US with an MRR above 1,000.
{ "filter": { "all": [ {"key": "customer.country_code", "equals": "US"}, {"key": "customer.mrr", "greater_than": 1000} ] }}Comparing a value
The simplest condition compares one value. It has a key, which says what
to look at, and one operator, which says how to compare it.
Example: Customers in the US.
{"key": "customer.country_code", "equals": "US"}A key starts with what it is about — customer, subscription or
subscription_item — then the field: customer.status,
subscription.currency_code, subscription_item.plan_id.
To use what one of your sources says about a record, put properties and
the source’s slug in between: customer.properties.hubspot.industry.
List fields shows every key your project can use.
The value is read as whatever the key holds: text, a number, true or
false, or a date. A date is ISO 8601 — 2026-03-01 or
2026-03-01T12:00:00Z — and is UTC unless it says otherwise. A key that
does not exist, or a value that does not fit the key, is refused with an
error saying why.
Equals
Matches if the field equals a specific value. Text is compared ignoring case.
Example: Customers in the US.
{"key": "customer.country_code", "equals": "US"}Does not equal
Matches if the field is anything but a specific value, or has no value at all.
Example: Customers HubSpot does not put in finance, including those it says nothing about.
{"key": "customer.properties.hubspot.industry", "not_equals": "finance"}Contains text
Matches if the field contains a piece of text, ignoring case.
Example: Customers with an email address at acme.com.
{"key": "customer.email", "contains": "@acme.com"}For the opposite, wrap it in a not.
Example: Customers without an email address at acme.com.
{"not": {"key": "customer.email", "contains": "@acme.com"}}Greater than
Matches if the field is greater than a value. For a number or a date.
Example: Customers with an MRR above 1,000, in the project’s reporting currency.
{"key": "customer.mrr", "greater_than": 1000}Greater than or equal to
Matches if the field is greater than or equal to a value.
Example: Customers with an item of ten seats or more.
{"key": "subscription_item.quantity", "greater_than_or_equals": 10}Less than
Matches if the field is less than a value. For a date, that means before it.
Example: Customers who first paid before 2026.
{"key": "customer.first_paying_at", "less_than": "2026-01-01"}Less than or equal to
Matches if the field is less than or equal to a value.
Example: Customers with an ARR of 12,000 or less.
{"key": "customer.arr", "less_than_or_equals": 12000}Has a value
Matches if the field has any value at all.
Example: Customers with an email address.
{"key": "customer.email", "present": true}Has no value
Matches if the field is empty.
Example: Customers HubSpot has not given an industry.
{"key": "customer.properties.hubspot.industry", "present": false}Matching every condition
all is an AND: it matches when every condition in its list matches.
Example: Paying customers in the US.
{ "all": [ {"key": "customer.status", "equals": "paying"}, {"key": "customer.country_code", "equals": "US"} ]}Matching any condition
any is an OR: it matches when at least one condition in its list matches.
Example: Customers in the US or Denmark.
{ "any": [ {"key": "customer.country_code", "equals": "US"}, {"key": "customer.country_code", "equals": "DK"} ]}Excluding a condition
not is a NOT: it matches when the condition inside it does not.
Example: Customers outside the US and Denmark.
{ "not": { "any": [ {"key": "customer.country_code", "equals": "US"}, {"key": "customer.country_code", "equals": "DK"} ] }}Nesting conditions
all, any and not can contain any condition, each other included.
Example: Paying customers in the US or Denmark, except those at acme.com.
{ "all": [ {"key": "customer.status", "equals": "paying"}, { "any": [ {"key": "customer.country_code", "equals": "US"}, {"key": "customer.country_code", "equals": "DK"} ] }, {"not": {"key": "customer.email", "contains": "@acme.com"}} ]}A filter is at most four levels deep, with at most twenty-five comparisons.
Subscriptions and items
A filter is about customers, and a customer can have several subscriptions. Take two customers:
- Customer1 has one subscription, active and in euros.
- Customer2 has two: one active and in dollars, and one canceled and in euros.
A condition about a subscription matches a customer who has a subscription that matches it, and each condition is checked on its own. So the filter below matches both customers: Customer1’s subscription is active and in euros, and Customer2 has an active subscription and a subscription in euros, though not the same one.
Example: Customers with an active subscription, and a subscription in euros. Matches Customer1 and Customer2.
{ "all": [ {"key": "subscription.status", "equals": "active"}, {"key": "subscription.currency_code", "equals": "EUR"} ]}To ask for one subscription that is both, put the conditions in a
has_subscription. Everything inside it is about the same subscription.
Example: Customers with an active subscription in euros. Matches Customer1 alone.
{ "has_subscription": { "all": [ {"key": "subscription.status", "equals": "active"}, {"key": "subscription.currency_code", "equals": "EUR"} ] }}has_subscription_item does the same for an item. Inside a
has_subscription it is an item of that subscription; on its own, an item
of any subscription.
Example: Customers with an active subscription that has an item of ten seats or more on the Pro plan.
{ "has_subscription": { "all": [ {"key": "subscription.status", "equals": "active"}, { "has_subscription_item": { "all": [ {"key": "subscription_item.plan_id", "equals": "stripe:prod_pro"}, {"key": "subscription_item.quantity", "greater_than_or_equals": 10} ] } } ] }}Example: Customers with no active subscription in euros. Matches Customer2.
{ "not": { "has_subscription": { "all": [ {"key": "subscription.status", "equals": "active"}, {"key": "subscription.currency_code", "equals": "EUR"} ] } }}A filter contains at most five of them, counting each condition about a subscription or an item outside one as one of its own.
In a metric
A metric adds up revenue. There, a condition about a subscription or an
item outside a has_subscription narrows the revenue counted to the
subscriptions or items it matches.
Example: The MRR of subscriptions in euros alone.
{ "measure": "mrr", "filter": {"key": "subscription.currency_code", "equals": "EUR"}}Inside a has_subscription, it asks about the customer instead, and counts
all of their revenue once they have such a subscription.
Example: The whole MRR of customers who have a subscription in euros.
{ "measure": "mrr", "filter": { "has_subscription": {"key": "subscription.currency_code", "equals": "EUR"} }}A metric that counts customers, such as paying_customers, has no
subscription of its own to narrow to, and takes a condition about a
subscription or an item only inside a has_subscription.
When a value is read
A value can change: a customer moves country, a subscription is canceled.
A comparison reads the value at one moment, and its at says which:
at |
Reads the value |
|---|---|
"now" |
as it is today. What a customer search reads when at is left out. |
| A date or a date and time | as it was then. A date means the end of that day, in the project’s reporting timezone. |
"window" |
as it was in each period: at its end for a figure like MRR, and when the money moved for a movement. Metrics only, and what a metric reads when at is left out. |
Example: Customers who were paying on March 1, 2026, whatever they are today.
{"key": "customer.status", "equals": "paying", "at": "2026-03-01"}In a metric, leaving at out reads each period as it was. Say a customer
moved from Denmark to the US in June. This counts their MRR as American
from June on, and as Danish before.
Example: MRR per month of customers in the US, as they were each month.
{ "measure": "mrr", "from": "2026-01-01", "to": "2026-12-31", "interval": "month", "filter": {"key": "customer.country_code", "equals": "US"}}With "at": "now", every month reads the value as it is today instead, so the
same customer counts as American in every month of the year.
Example: MRR per month of the customers who are in the US today.
{ "measure": "mrr", "from": "2026-01-01", "to": "2026-12-31", "interval": "month", "filter": {"key": "customer.country_code", "equals": "US", "at": "now"}}