diff --git a/docs/stats-api.md b/docs/stats-api.md
index 432941c8..4d923c59 100644
--- a/docs/stats-api.md
+++ b/docs/stats-api.md
@@ -172,7 +172,7 @@ Filters allow limiting the data analyzed in a query. [See example](#example-filt
#### Simple filters
-Each simple filter takes the form of `[operator, dimension, clauses]`.
+Each simple filter is an array with three or four elements `[operator, dimension, clauses]` or `[operator, dimension, clauses, modifiers]`.
##### operators
@@ -187,6 +187,7 @@ The following operators are currently supported:
| `matches` | `["matches", "event:page", ["^/user/\d+$"]]` | Events where page matches regular expression `^/user/\d+$`. [Uses re2 syntax](https://github.com/google/re2/wiki/Syntax) |
| `matches_not` | `["matches", "event:page", ["^/user/\d+$"]]` | Events where page does not match regular expression `^/user/\d+$`. [Uses re2 syntax](https://github.com/google/re2/wiki/Syntax) |
+
##### dimension
[Event and visit dimensions](#dimensions) are valid for filters.
@@ -197,6 +198,12 @@ Note that only `is` operator is valid for `event:goal` dimension.
List of values to match against. A data point matches filter if _any_ of the clauses matches.
+##### modifiers
+
+`contains` and `is` filters also support a 4th, modifier argument. For example, to match countries ignoring casing, you can use the following filter:
+
+`["contains", "event:country", ["united", "EST], { "case_sensitive": false }]`. [See full example](#example-filtering-case-insensitive)
+
#### Logical operations
Filters can be combined using `and`, `or` and `not` operators.
@@ -341,6 +348,10 @@ The query that was executed, after manipulations performed on the backend.
+### Case insensitive filtering {#example-filtering-case-insensitive}
+
+
+
### Timeseries query {#example-timeseries}
diff --git a/src/js/apiv2-examples/filtering-case-insensitive-query.json b/src/js/apiv2-examples/filtering-case-insensitive-query.json
new file mode 100644
index 00000000..f25563f1
--- /dev/null
+++ b/src/js/apiv2-examples/filtering-case-insensitive-query.json
@@ -0,0 +1,8 @@
+{
+ "site_id": "dummy.site",
+ "metrics": ["visitors"],
+ "date_range": "7d",
+ "filters": [
+ ["contains", "event:page", ["blog"], {"case_sensitive": false}]
+ ]
+}
diff --git a/src/js/apiv2-examples/filtering-case-insensitive-response.json b/src/js/apiv2-examples/filtering-case-insensitive-response.json
new file mode 100644
index 00000000..519e6006
--- /dev/null
+++ b/src/js/apiv2-examples/filtering-case-insensitive-response.json
@@ -0,0 +1,15 @@
+{
+ "results": [{"metrics": [10], "dimensions": []}],
+ "meta": {},
+ "query": {
+ "site_id": "dummy.site",
+ "metrics": ["visitors"],
+ "date_range": ["2024-09-04T00:00:00+00:00", "2024-09-10T23:59:59+00:00"],
+ "filters": [
+ ["contains", "event:page", ["/blog"], {"case_sensitive": false}]
+ ],
+ "dimensions": [],
+ "order_by": [["visitors", "desc"]],
+ "include": {}
+ }
+}
diff --git a/src/js/examples.tsx b/src/js/examples.tsx
index 6231c0d1..1781cc78 100644
--- a/src/js/examples.tsx
+++ b/src/js/examples.tsx
@@ -33,6 +33,12 @@ const EXAMPLES = [
query: read("apiv2-examples/filtering-basics-query.json"),
exampleResponse: read("apiv2-examples/filtering-basics-response.json"),
},
+ {
+ id: "example-filtering-case-insensitive",
+ title: "Case insensitive filtering",
+ query: read("apiv2-examples/filtering-case-insensitive-query.json"),
+ exampleResponse: read("apiv2-examples/filtering-case-insensitive-response.json"),
+ },
{
id: "example-timeseries",
title: "Timeseries query",