Skip to content
Listener.comDevelopers

Time windows

How analytics windows resolve, how growth is compared, and what coverage tells you.

2 min read

Every analytics endpoint answers for a window of days. You choose it with time_range, or with explicit dates.

Choosing a window#

ParameterValues
time_range7d, 14d, 30d, 90d, 180d, 365d, all, a quarter like 2026-Q3, or Q3 for that quarter this year.
start_date + end_dateYYYY-MM-DD, both inclusive. Send both. They override time_range.

Windows are UTC calendar days and include today. 30d on 2026-10-14 means 2026-09-15 through 2026-10-14.

The previous period is the same number of days immediately before the window. For quarter tokens it is the previous quarter.

The window object#

Windowed responses echo what they resolved, so you never have to recompute it:

window
{
  "time_range": "30d",
  "kind": "rolling",
  "start": "2026-09-15",
  "end": "2026-10-14",
  "days": 30,
  "previous_start": "2026-08-16",
  "previous_end": "2026-09-14"
}

Coverage#

Not every platform has data for every day. coverage says how much of the window is backed by data:

coverage
{
  "start": "2026-08-16",
  "embedded_boundary": "2026-09-15",
  "history_used": true,
  "current_window_coverage_days": 30,
  "previous_window_coverage_days": 11,
  "growth_basis": "like_for_like",
  "warnings": ["Previous window has data for 11 of 30 days; growth is not shown."]
}
Field
embedded_boundaryToday minus 29 days. Recent days come from each platform’s live series; older days come from stored history.
history_usedtrue when the window reached into stored history.
current_window_coverage_days, previous_window_coverage_daysHow many days of each window have data.
growth_basisHow growth was compared (below).
warningsPlain-language reasons when something was left out. Show them to users.

Growth#

Growth compares the window with the previous period. It is null when the previous window has data for fewer than half of its days, because comparing against a mostly empty baseline produces numbers like +3,441% that mean nothing. The reason is in coverage.warnings.

Show null growth as a dash, never as 0:

Show null growth as a dash, never as 0

Never coerce null growth to 0. Zero claims “no change”; null means “not comparable”. The Listener apps show a dash (—) in that case, and your users will expect the same.

Like-for-like growth on long windows#

For windows longer than 30 days (90d, quarters, custom ranges), growth is compared like for like: only platforms whose data covers at least half of the previous window take part, and both windows are summed over exactly those platforms. coverage.growth_basis is "like_for_like" and coverage.growth_platforms lists the platforms compared. If no platform qualifies, growth is null.

Endpoints with fixed windows#

The dashboard KPIs (GET /v1/analytics/dashboard) and per-show platform stats (GET /v1/shows/{show_id}/platforms) accept 7d, 30d or 90d. On 90d, impressions, downloads and engagement rate cover all 90 days from history, but likes, comments, posts, top content and follower changes stay on the last 30 days, because there is no long-range source for them. metric_windows (and each tile’s window) says which window every metric used. Those 30-day metrics, and EMV, have no growth on 90d.

Custom ranges#

Custom ranges are the most precise way to align with a reporting period:

curl
curl -G https://api.listener.com/v1/analytics/reach \
  -H "Authorization: Bearer $LISTENER_API_KEY" \
  -d start_date=2026-07-01 \
  -d end_date=2026-09-30

That is equivalent to time_range=2026-Q3, and its previous period is 2026-Q2.