Use the Engagement API to retrieve per-moment engagement as a heatmap across the full video timeline or as a ranked list of the most and least engaging moments.
The Engagement APIBeta reports how much of each moment of a piece of content viewers watched, aggregated across every completed view. It returns this data in two forms:
Engagement metrics are a subset of Mux Data's historical metrics. They're calculated from completed views, so they reflect how a whole population of viewers behaved rather than any single session.
Beta
The Engagement API is in beta. Its request and response shapes may change before general availability.
The Engagement API is part of the Mux Data REST API and uses the same access token authentication and rate limits as the rest of the Data API. Before you can pull engagement data, you'll need:
To query by video ID, you'll also need to be reporting the video_id metadata field from your player.
Every endpoint comes in three variants, one per identifier. All three return the same response shape, so pick the one that matches how you key your content.
| Identifier | Path segment | What it covers |
|---|---|---|
| Asset ID | /assets/{ASSET_ID} | Engagement for a single Mux Video asset. |
| Video ID | /videos/{VIDEO_ID} | Engagement aggregated across every asset and playback ID that shares the same video_id — your own internal identifier for a piece of content. |
| Playback ID | /playback-ids/{PLAYBACK_ID} | Engagement for a single playback ID, covering only the views that used that playback ID. |
The base path for all six endpoints is https://api.mux.com/data/v1/engagement.
The playback ID endpoints only cover views for that specific playback ID. If an asset has more than one playback ID, such as a public one and a signed one, a playback ID query won't include the others. To analyze the whole asset across all of its playback IDs, use the asset ID or video ID endpoint instead.
A heatmap is an array of engagement values spread evenly across the content timeline, ordered from the start of the content to the end.
curl 'https://api.mux.com/data/v1/engagement/assets/{ASSET_ID}/heatmap?timeframe[]=7:days' \
-u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET}{
"total_row_count": 1,
"timeframe": [1610025789, 1610112189],
"data": {
"total_views": 1024,
"value": [0.42, 0.55, 0.61, 0.58, 0.47]
}
}API reference: AssetAPI, VideoAPI, Playback IDAPI.
The engagement values live in the data.value array:
data.total_views is the number of views the heatmap was aggregated from.The buckets are evenly spaced, so once you know the content's duration you can turn any bucket index into a position in the content. Each bucket covers duration / value.length seconds:
// durationSeconds comes from your own metadata or the Mux asset
function bucketsToTimeline(value, durationSeconds) {
const bucketSize = durationSeconds / value.length;
return value.map((score, i) => ({
startSeconds: i * bucketSize,
endSeconds: (i + 1) * bucketSize,
score,
}));
}Each engagement value is now paired with the time range it represents.
Hotspots are the highest-scoring moments of the content, returned as discrete, ranked time ranges.
curl 'https://api.mux.com/data/v1/engagement/assets/{ASSET_ID}/hotspots?timeframe[]=7:days' \
-u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET}{
"total_row_count": 2,
"timeframe": [1610025789, 1610112189],
"data": {
"total_views": 1024,
"hotspots": [
{ "start_ms": 30000, "end_ms": 45000, "score": 0.842 },
{ "start_ms": 120000, "end_ms": 138000, "score": 0.713 }
]
}
}API reference: AssetAPI, VideoAPI, Playback IDAPI.
Each entry in data.hotspots describes one moment:
start_ms — where the moment begins, in milliseconds from the start of the content.end_ms — where it ends, in milliseconds (exclusive).score — an engagement score between 0 and 1. Higher is more engaging.By default, hotspots come back ordered from most to least engaging. data.total_views is the number of views they were aggregated from.
Hotspots are statistical peaks or valleys that must clear certain thresholds to be considered valid. With only a handful of views, the curve is too noisy for anything to clear those score thresholds, so you may get an empty hotspots array as a result. Only content that produces a discernible engagement pattern will return with a result.
Hotspots take two optional query parameters:
| Parameter | Description |
|---|---|
limit | The maximum number of hotspots to return. Leave it off to get all of them. |
order_direction | desc (the default) returns the most engaging moments first. asc returns the least engaging moments — the cold spots — first. |
To return the three least-engaging moments, sort ascending and set a limit:
curl 'https://api.mux.com/data/v1/engagement/videos/{VIDEO_ID}/hotspots?timeframe[]=30:days&order_direction=asc&limit=3' \
-u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET}timeframeEvery endpoint accepts the standard Data timeframe[] query parameter to limit results to a window. Pass it as a relative duration or as a pair of epoch timestamps:
timeframe[]=7:days or timeframe[]=24:hourstimeframe[]=1610025789&timeframe[]=1610112189If you leave it off, the timeframe defaults to the last 7 days. Engagement data follows the same retention as the rest of your Mux Data, so how far back you can query depends on your plan.
Engagement data is only collected by recent versions of the Mux Data SDKs. For a piece of content to have heatmaps and hotspots, the views must be reported by an integration on at least the version below. See the changelog announcement for details.
| SDK | Minimum version |
|---|---|
| Mux Player (web) | v3.11.0 |
| Mux Player Android | v1.5.3 |
| Mux Player Swift | Built on mux-stats-sdk-objc v5.11.0+ |
| mux-embed | v5.15.0 |
| mux-stats-sdk-media3 | v1.11.1 |
| mux-stats-sdk-objc | v5.11.0 |
| mux-stats-sdk-java | v8.9.0 |
| roku-mux | v2.6.0 |