Query model reference

A query describes an event set, aggregate metrics, presentation order, and time range. The result carries both values and the plan used to produce them.

AnalyticsQuery properties

Property Default Meaning
Site Engine default Dataset site
Event pageview Base event for unqualified metrics
Range Last 30 calendar days Selected history
TimeZone Engine time zone Calendar ranges and day-or-coarser buckets
Interval None One aggregate bucket or a time series
GroupBy Empty Ordered list of grouping dimensions
Filters Empty Conditions on every event sub-query
Segments Empty Behavioral visitor or session membership
Metrics Events and Visitors when omitted Selected measures
OrderBy Bucket order, otherwise first metric descending Result sort keys
Limit / Offset All / zero Overall pagination
LimitPerBucket All Top groups within each bucket before global pagination
Fill Zero Time-series gaps for groups with data
Having Empty Conditions on aggregated rows
OnlyRowsWithBaseEvent false Restrict joined results to base-event rows
Compare None Comparison period
Source Auto Automatic, forced rollup, or forced raw execution

Metrics that read different events execute as separate sub-queries and join by bucket and dimensions. Missing dimension values group under null.

Metric families

Metric Reads Meaning
Events, Visitors base event count and unique visitors
EventsOf(e), VisitorsOf(e) event e count and unique visitors of another event
PageViews page views page view count
Sessions, Bounces, BounceRate, SessionDuration, AverageSessionDuration, PageViewsPerSession sessions session metrics; rates are 0 to 1, durations are seconds
Entrances, Exits, ExitRate page views sessions that started or ended on a page
Sum(v), Average(v), Min(v), Max(v), Count(v) base event, or Sum(v, e) aggregates of a tracked value
StandardDeviation(v), Variance(v) base event, or with e population spread of a tracked value
Percentile(v, p), Median(v) base event, or with e quantile estimates; exact minimum at 0 and maximum at 100 ¹
First(v), Last(v) base event, or with e the first and last value by time: gauges such as a temperature ¹
Distinct(d) base event, or with e distinct values of a dimension, such as tenants or countries ¹
CountBetween(v, lower, upper), Histogram(v, edges) base event, or with e approximate counts in [lower, upper); a histogram returns one metric per bin ¹
m.Where(filters) as m m over the events that match the filters: CountIf, SumIf and so on
VisitorsOf(goal), ConversionRate(goal) goal event goal visitors, and goal visitors ÷ base visitors
PercentOfTotal(m) as m each row's share of the total
BotHits bot events automated requests, see bot collection

¹ Answered from rollups when configured (see rollups and query planning), otherwise from retained raw events. See accuracy and optional aggregate state for estimation limits.

The engine runs sub-queries for the events and metric-local conditions needed by a request, then joins results by bucket and group values. By default, any metric can contribute a result row. Set OnlyRowsWithBaseEvent=true to keep only groups with base-event activity. Query filters apply to every sub-query.

var errors = Metric.Events.Where(Filter.GreaterThanOrEqual("status", 500));
var report = await analytics.QueryAsync(new AnalyticsQuery
{
    Event = "request_completed",
    GroupBy = { "route" },
    Metrics = { Metric.Events, errors, errors / Metric.Events },
});

A conditional metric is answered from rollups when a rollup definition covers the group-by and filter dimensions together with the dimensions of its conditions, otherwise from raw events; on a formula, the conditions apply to every aggregate in it. Histograms and CountBetween read the percentile sketches, so they need ValueAggregates.Percentiles to be answered from rollups.

Session metrics can only be grouped and filtered by session-level dimensions (standard and Sessions.Dimensions) and the entry page; entrances and exits also by page and hostname. Use a segment to select sessions by anything else. Bot metrics can only be grouped and filtered by page, hostname, event, bot and bot_category, and cannot be combined with segments.

Every metric has a stable key, for example visitors, bounce_rate, sum:revenue, avg:duration_ms@job_completed, p95:load_time, distinct:tenant, conversion_rate:signup, percent(visitors), div(sum:revenue,events:purchase), moving_avg(visitors,7), count_between(load_time,100,500) or where(events,"status>=500") (filters in double quotes, with backslash escapes); Metric.Parse turns keys back into metrics.

Formulas and series functions

Arithmetic operators compose metrics. PercentOfTotal, Rate, Cumulative, MovingAverage, Difference, Increase, Lag, and Lead transform aggregate series. Metric keys provide a round-trippable text representation through Parse and TryParse.

Function Result rows Totals
Rate(metric, per) Rate over each bucket's covered duration Average rate over the range
Cumulative(metric) Running total Metric total
MovingAverage(metric, buckets) Window average Metric total
Difference(metric) Change from the previous observation Sum of changes
Increase(metric) Counter increase, treating a decrease as a reset Sum of increases
Lag / Lead Value at an earlier or later interval position Metric total

Series functions require an interval, except Rate. Lag, Lead, and moving-average windows count interval positions. With no gap fill, an absent target contributes zero to these calculations. Difference and Increase compare consecutive returned observations.

Formulas are evaluated from aggregate totals for the totals row. Division by zero and non-finite formula results evaluate to zero; individual numeric aggregates can still be non-finite.

Fill runs on aggregates before formulas and series functions. Previous fill uses the nearest available value for leading gaps; linear fill interpolates between observed buckets and uses nearest values at the edges. Groups with no data anywhere in the selected range are not invented.

Accuracy and optional aggregate state

At default sketch precision 14, distinct counts are exact up to 4,096 identities per row and have approximately 0.8% standard error above that threshold.

Percentiles use a mergeable quantile sketch. Retained logarithmic buckets have at most 1% relative value error. Magnitudes below 1e-9 share a zero bucket; each sign retains at most 2,048 buckets, and smaller magnitudes can collapse when its span is exceeded. The relative-error guarantee excludes zero and collapsed buckets. Percentiles zero and 100 remain exact.

Histogram and CountBetween results use quantile buckets. Their bin counts are approximate; relative value precision is not a guarantee of relative error in each bin's count.

Percentiles, first/last values, and distinct dimension counts need their configured optional state for rollup execution. Without it, retained raw events can answer the metric. Retention and activation coverage remain independent of sketch accuracy.

Filter families

Factory Meaning
Equal / NotEqual Match or exclude specified values
Contains / NotContains Substring tests
StartsWith / EndsWith Prefix and suffix tests
Matches / NotMatches Regular-expression tests
GreaterThan / GreaterThanOrEqual / LessThan / LessThanOrEqual Numeric dimension comparisons
IsSet / IsNotSet Presence and absence
AnyOf / AllOf Nested Boolean groups

Conditions in a query's filter list are combined with AND. Alternative values inside a condition match with OR. Missing values satisfy negative comparisons but not positive value matches; use presence tests when absence must be explicit.

Metric.Where is a metric-local contribution filter. MetricFilter is a post-aggregation HAVING condition and does not change totals or comparison source rows.

Histograms

Histogram returns one metric per adjacent pair of edges. Add those metrics to a query to report a distribution:

var query = new AnalyticsQuery
{
    Range = DateRange.LastDays(30),
    GroupBy = { StandardDimensions.Page },
};
query.Metrics.AddRange(Metric.Histogram(
    "load_time", [0, 100, 250, 500, 1000, double.PositiveInfinity]));
var report = await analytics.QueryAsync(query);

Configure percentile aggregate state for rollup execution; retained raw events can supply the measurement when that state is unavailable.

Ranges, intervals, and comparisons

var today = DateRange.Today;
var completedWeek = DateRange.LastDays(7, includeToday: false);
var recentActivity = DateRange.Last(TimeSpan.FromMinutes(30));
var calendarPeriod = DateRange.Days(
    new DateOnly(2026, 6, 14), new DateOnly(2026, 7, 15));

var query = new AnalyticsQuery
{
    Range = calendarPeriod,
    TimeZone = TimeZoneInfo.FindSystemTimeZoneById("Europe/Berlin"),
    Compare = ComparisonPeriod.PreviousPeriod,
};

Text forms. Ranges, comparison periods, filters, metrics, conditions, sort keys, segments and intervals each have a text form: Parse reads it, TryParse tries to, and ToString() writes it back. The reporting API uses the same syntax.

Type Examples
DateRange today, yesterday, 30d, today-7..today-1, 12h, 30m, this-month, last-month, this-year, last-year, 2026, 2026-02, 2026-02-28, 2026-02-01..2026-02-28, two ISO 8601 date-times separated by ..
ComparisonPeriod previous-period, previous-year, or a date range
Filter country==DE|AT, page^=/blog/, load_time>=500, utm_source?
Metric visitors, sum:revenue, p95:load_time, percent(visitors)
MetricFilter visitors>10
Order -visitors, page (a group-by dimension), bucket
Segment visitors with purchase where plan==pro; country==DE, not sessions with signup
TimeInterval day, hour, 5m, 6h

Invalid text raises FormatException; a null text raises ArgumentNullException.

Calendar ranges and day, week, month and year buckets follow the query's time zone (the engine's reporting time zone by default). Daily rollups are stored in the reporting time zone; other time zones are answered from hourly rollups. A time series has at most Queries.MaxTimeBuckets buckets (100,000 by default); longer ones are rejected rather than truncated. A query groups by at most Queries.MaxGroupBy dimensions (8 by default).

Queries.MaxGroups bounds aggregate entries while reading a query (100,000 by default), before Limit, Having or LimitPerBucket are applied. Each time bucket and dimension combination counts separately for each metric source; partial groups of parallel raw scans count until merged. A query that exceeds the budget raises AnalyticsQueryException. Narrow its range, group by fewer dimensions, lower Queries.MaxDegreeOfParallelism, or raise MaxGroups. Comparison periods have separate budgets; gap-filled rows use Queries.MaxFilledRows.

Queries and funnels that run longer than Queries.Timeout (30 seconds by default) are cancelled with an AnalyticsQueryTimeoutException, a kind of AnalyticsQueryException, so an expensive ad-hoc query cannot tie up the host application.

Behavioral requests

Derived time dimensions

StandardDimensions.HourOfDay ($hour_of_day) and DayOfWeek ($day_of_week) are computed in the query's time zone. Hours are 0–23; weekdays are Monday=1 through Sunday=7.

var byHour = new AnalyticsQuery
{
    Range = DateRange.LastDays(30),
    TimeZone = TimeZoneInfo.FindSystemTimeZoneById("Europe/Berlin"),
    GroupBy = { StandardDimensions.DayOfWeek, StandardDimensions.HourOfDay },
    Filters = { Filter.LessThanOrEqual(StandardDimensions.DayOfWeek, 5) },
    Metrics = { Metric.Events, Metric.Visitors },
};

Use them in grouping, filters, and conditional metrics. They are computed rather than stored dimensions, so omit them from rollup definitions.

Segments and funnels

Segment.VisitorsWho, SessionsWith, and VisitorsWhoViewed select identities with matching events. Exclude inverts that membership.

FunnelQuery supplies site, range, time zone, two to 64 ordered steps, optional global filters and segments, and an optional completion window. Null window requires a single session. Step factories include page and goal helpers.

Results and plans

Type Important fields
AnalyticsResult From, To, TimeZone, Rows, TotalRows, Totals, Comparison, Plan
AnalyticsRow Bucket, Dimensions, Values, Previous, metric and dimension indexers
QueryPlan Steps, Warnings, RollupSuggestions, IsComplete, source-use flags
QueryPlanStep Event, Source, From, To, IndexDimension
FunnelResult From, To, Steps, ConversionRate, Plan

TotalRows is the count before global pagination. Totals precede pagination, and distinct counts merge state rather than adding row values. Change(metric) returns relative change, or null when no matching comparison exists or the previous value is zero.

Plan sources are DayRollups, HourRollups, MinuteRollups, RawEvents, and DimensionIndex. A covering rollup index keeps its tier source and sets IndexDimension. Suggestions identify missing ordinary rollup definitions; they do not make historical coverage complete.

Standard web vocabulary

Dimension Source
page, hostname Page URL. Query strings are removed by default; UTM parameters are extracted.
entry_page First page of the session.
source utm_source, a known referrer name ("Google", "Twitter", "Hacker News", "ChatGPT", ...), the referrer host, or "Direct".
referrer Referrer host, empty for direct traffic.
channel Direct, Organic Search, Paid Search, Organic Social, Paid Social, Email, Affiliates, AI Assistants, Video, Referral or Paid Other (constants in Channels).
utm_source, utm_medium, utm_campaign, utm_term, utm_content Campaign parameters of the landing URL.
country, region, city Your IGeoLocator, or values you pass as dimensions (for example from a CDN header).
browser, os, device (+ browser_version, os_version) Built-in, dependency-free user agent parser, or your IUserAgentParser.
bot, bot_category, event On bot events only: the bot, its category and the original event name.

Source, campaign, geography and device are session-level: captured from the first event of a session and attached to every event of the session, so all page views and goals of a visit share them. Standard dimensions can be overridden per event, for example Dimensions = { [StandardDimensions.Country] = cdnCountry }.

For runnable composition patterns, use the query guide and web-report guide.