Grouping

Break results down by one or more fields.

Grouping splits a count into buckets, one per distinct value of a field. Instead of one total you get a breakdown, which is how dashboards answer questions like "completions by country" or "usage by plan".

What grouping returns

typescript
const byCountry = await vanta.groupBy({
  groupBy: ['context.country'],
  filters: filter('type', 'equals', 'checkout.completed'),
  time: timeRange('2024-01-01T00:00:00Z', '2024-12-31T23:59:59Z'),
})

The response contains one group per distinct value, each with its count:

json
{
  "groups": [
    { "field": "context.country", "value": "US", "count": 8124 },
    { "field": "context.country", "value": "DE", "count": 3172 },
    { "field": "context.country", "value": "BR", "count": 2190 }
  ]
}

Single field

Group by a property to see how your data splits across it:

typescript
const byPlan = await vanta.groupBy({
  groupBy: ['data.plan'],
  filters: filter('type', 'equals', 'user.signup'),
  time: timeRange('2024-01-01T00:00:00Z', '2024-12-31T23:59:59Z'),
})

Multiple fields

Pass more than one field to create nested groups. Each combination of values becomes its own group:

typescript
const byPlanAndCountry = await vanta.groupBy({
  groupBy: ['data.plan', 'context.country'],
  filters: filter('type', 'equals', 'checkout.completed'),
  time: timeRange('2024-01-01T00:00:00Z', '2024-12-31T23:59:59Z'),
})

Grouping with filters

Grouping composes with filtering. Restrict the events first, then split the survivors:

typescript
const bySource = await vanta.groupBy({
  groupBy: ['source'],
  filters: and(
    filter('type', 'equals', 'user.signup'),
    filter('data.plan', 'equals', 'pro'),
  ),
  time: timeRange('2024-01-01T00:00:00Z', '2024-12-31T23:59:59Z'),
})