Skip to content

Understanding the Statistics

Justagwas edited this page Aug 25, 2026 · 1 revision

Understanding the statistics

GitHub exposes a cumulative download_count for each file attached to a release. GitHub Downloads Action converts those current counters into a dated total series, then derives rolling changes from earlier snapshots.

Total downloads

For a run on UTC date d, the total is:

total(d) = sum of download_count for every release asset returned by GitHub

If a release has three attached files, downloads of all three contribute to the total. One person downloading two assets contributes two asset downloads. The value does not represent unique users.

Day, week, and month

For a range of k days, the action uses:

range(k, d) = max(0, total(d) - baseline(d - k))

The published fields use k = 1, 7, and 30:

Field Intended baseline
stats.day Total one UTC date earlier
stats.week Total seven UTC dates earlier
stats.month Total thirty UTC dates earlier

When an exact baseline date exists, the corresponding partial flag is false. When it does not exist, the action uses the nearest available snapshot and marks the result as partial.

Partial flags

partial.day, partial.week, and partial.month describe baseline coverage, not whether the action failed.

  • false means an exact snapshot was available on the required baseline date.
  • true means the range is still warming up or contains a date gap, so the value uses the best available baseline.

A normal daily schedule typically develops coverage in this order:

Snapshot history Day Week Month
First run Partial Partial Partial
After two daily dates Exact when consecutive Partial Partial
After eight daily dates Exact when consecutive Exact when consecutive Partial
After thirty-one daily dates Exact when consecutive Exact when consecutive Exact when consecutive

Missing scheduled runs can make a range partial again because the required calendar date is absent. A range value may still be useful, but it should not be presented as an exact interval count while its flag is true.

Snapshot window

window_days controls how many UTC dates remain in snapshots.series. The default is 45, which retains enough history for all three standard ranges when the workflow runs consistently. Reducing the window below 31 days prevents reliable thirty-day baselines.

Only one total is retained for each UTC date. Running the hourly profile refreshes the current day's snapshot more often, but it does not create hourly history or an hourly download metric. profile.defaultMode records whether the selected workflow profile is daily or hourly.

Interpreting changes in the total

The action polls the current release asset counters. It does not maintain a permanent ledger of individual download events. Deleting a release or replacing an asset can remove its counter from later API totals. When a current total is lower than a baseline, the published range delta is clamped to zero rather than becoming negative.

For this reason, the series should be interpreted as snapshots of the repository's currently visible release asset counters. It is well suited to README badges and rolling project indicators, but it is not a substitute for event-level analytics or unique-user measurement.

Published JSON structure

{
  "schemaVersion": "1",
  "owner": "OWNER",
  "repo": "REPOSITORY",
  "visibility": "public",
  "generatedAt": "2026-08-25T03:00:00.000Z",
  "stats": {
    "total": 9412,
    "day": 16,
    "week": 159,
    "month": 802
  },
  "partial": {
    "day": false,
    "week": false,
    "month": false
  },
  "snapshots": {
    "windowDays": 45,
    "count": 45,
    "firstDate": "2026-07-12",
    "lastDate": "2026-08-25",
    "series": {
      "2026-08-25": 9412
    }
  },
  "profile": {
    "defaultMode": "daily",
    "hourlyEnabled": false
  }
}

The normative structure is defined by the repository's JSON Schema.