Appearance
Sum
AggregationNumeric
Accumulates a numeric field value within a time window. Returns the running total along with count, average, min, and max. Optionally partitions the sum by another field for per-item breakdowns.
When to Use
- Total play duration per user over 30 days
- Cumulative spend or transaction amounts
- Aggregated scores, ratings, or quantities
- Per-item breakdowns: total play time broken down per song
Simple Sum
json
{
"name": "total_play_duration_by_identity_30d",
"operation": "sum",
"group_by": "identity",
"fields": ["event_properties.playDuration"],
"window_duration_seconds": 2592000,
"filters": {
"field": "event_name",
"operator": "equals",
"value": "PauseSong"
}
}fields: The first entry is the dot-notation path to the numeric field to accumulate. Events where this field is absent or non-numeric are skipped.
Response
json
{
"behaviors": {
"total_play_duration_by_identity_30d": {
"sum": 2340,
"count": 18,
"average": 130,
"min": 12,
"max": 480,
"timestamp": "2025-06-01T09:00:00.000Z",
"remaining_window_seconds": 2590200
}
}
}Partitioned Sum
Add partition_by to break the total down by another field — for example, total play time per song for a given user. Results are sorted by sum descending.
json
{
"name": "play_time_by_song_30d",
"operation": "sum",
"group_by": "identity",
"fields": ["event_properties.playDuration"],
"window_duration_seconds": 2592000,
"filters": {
"field": "event_name",
"operator": "equals",
"value": "PauseSong"
},
"operation_config": {
"partition_by": "event_properties.songId",
"n": 20,
"evict_on": ["DislikeSong"]
}
}Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
partition_by | string | — | Dot-notation path to the partition field. When set, response includes a by_partition map sorted by sum descending |
n | number | all | Limits response to top N partitions by sum. All partitions are still tracked internally |
evict_on | string[] | — | Event names that hard-delete a partition from tracking. The partition's accumulated sum and count are subtracted from totals |
Response (partitioned)
| Field | Description |
|---|---|
total_sum | Grand total across all partitions |
total_count | Total events processed across all partitions |
total_average | total_sum / total_count |
values | Partition keys sorted by sum descending (capped to n if set) |
by_partition | Per-partition stats: sum, count, average, min, max |
rejected | Number of partitions removed via evict_on events |
json
{
"behaviors": {
"play_time_by_song_30d": {
"total_sum": 4820,
"total_count": 31,
"total_average": 155.5,
"values": ["song_789", "song_456", "song_123"],
"by_partition": {
"song_789": {
"sum": 2400,
"count": 12,
"average": 200,
"min": 90,
"max": 480
},
"song_456": {
"sum": 1540,
"count": 11,
"average": 140,
"min": 60,
"max": 300
},
"song_123": {
"sum": 880,
"count": 8,
"average": 110,
"min": 30,
"max": 240
}
},
"rejected": 1,
"timestamp": "2025-06-01T09:00:00.000Z",
"remaining_window_seconds": 2589600
}
}
}Use Case: Most-Listened Songs
A music streaming platform wants to know which songs each user has spent the most time listening to — powering a "Your Top Songs" feature and feeding data into a recommendation model.
Each time the user pauses or completes a track, the client sends a PauseSong event:
js
honeypot.track('PauseSong', {
songId: 'song_789',
playDuration: 240, // seconds listened this session
});json
{
"name": "top_songs_by_play_time_30d",
"operation": "sum",
"group_by": "identity",
"fields": ["event_properties.playDuration"],
"window_duration_seconds": 2592000,
"filters": {
"field": "event_name",
"operator": "equals",
"value": "PauseSong"
},
"operation_config": {
"partition_by": "event_properties.songId",
"n": 20,
"evict_on": ["DislikeSong"]
}
}After several sessions:
json
{
"behaviors": {
"top_songs_by_play_time_30d": {
"total_sum": 7200,
"total_count": 42,
"total_average": 171.4,
"values": ["song_789", "song_456", "song_123"],
"by_partition": {
"song_789": {
"sum": 3600,
"count": 18,
"average": 200,
"min": 60,
"max": 480
},
"song_456": {
"sum": 2100,
"count": 14,
"average": 150,
"min": 30,
"max": 360
},
"song_123": {
"sum": 1500,
"count": 10,
"average": 150,
"min": 90,
"max": 240
}
},
"rejected": 2
}
}
}Reading the output:
song_789is the user's most-listened track with 3,600 seconds (1 hour) across 18 sessionsrejected: 2means the user disliked 2 songs — permanently removed from the leaderboard- The
valuesarray feeds directly into a recommendation engine
sum vs top_n with sum_by — which to use?
Both can accumulate play duration per song. The difference is scope:
sumwithpartition_by: Best when the song (partition) is the primary axis and you want totals across userstop_nwithsum_by: Best when the user is the primary axis and you want each user's personal top songs ranked by listening time
Use top_n + sum_by for per-user personalization. Use sum + partition_by for aggregate totals across a population.
Use min/max for anomaly detection
The min and max fields per partition reveal listening patterns. A song with max: 480 (8 minutes) but average: 30 suggests the user usually skips it — except once when they let it run. Useful for identifying background listening vs. intentional plays.