Skip to content

Timeline

Audit TrailInvestigation

Builds a chronological log of everything a user or device did within a time window — like a play-by-play activity feed. Each event is recorded with a timestamp and any extra fields you capture.

When to Use

  • Abuse investigation: pull a user's timeline to see exactly what happened and in what order
  • Compliance audit trails: generate a full record of user activity for regulatory review
  • Anomaly investigation: a user flagged by another behavior — what did their session look like?
  • Onboarding drop-off analysis: what's the last event users hit before they stop?

Configuration

json
{
  "name": "device_activity_timeline_24h",
  "operation": "timeline",
  "group_by": "device_id",
  "fields": ["country_code", "ip_address", "identity"],
  "window_duration_seconds": 86400,
  "operation_config": {
    "max_entries": 50,
    "dedupe_consecutive": true
  }
}

Fields

fields is optional. It specifies additional fields to capture per entry beyond the always-included event_name and event_id. Fields are resolved from the top-level event data first, then fall back to event_properties (e.g., "phone" resolves to event_properties.phone if no top-level phone field exists). Dot notation also works: "event_properties.phone".

Configuration Options

OptionDefaultDescription
max_entries50Maximum entries to retain. Oldest are evicted (FIFO). Summary stats still cover the full window.
dedupe_consecutivetrueConsecutive events with the same event_name and identical field values are collapsed into a single entry with min_time, max_time, and count. When two events share the same name but differ in any captured field, they are not merged. Set to false for one entry per event.

Response

FieldDescription
entriesArray of event snapshots (capped to max_entries, most recent retained)
entries[].event_nameThe name of the event
entries[].event_idID of the first event in a collapsed group
entries[].min_timeTimestamp of the first event in the entry (when dedupe_consecutive is enabled)
entries[].max_timeTimestamp of the most recent event in the entry (when dedupe_consecutive is enabled)
entries[].event_timeTimestamp of the event (when dedupe_consecutive is false)
entries[].countNumber of consecutive events collapsed into this entry
summary.countTotal number of events in the window (may exceed entry_count)
summary.entry_countNumber of entries currently in the timeline
summary.min_timeTimestamp of the first event in the window
summary.max_timeTimestamp of the most recent event
summary.duration_secondsTime elapsed between first and last event
summary.eventsPer-event-name breakdown with count, min_time, and max_time

Example (with dedupe_consecutive: true)

In this example, 5 raw events occurred, but the 3 consecutive page_view events were collapsed into a single entry with count: 3:

json
{
  "behaviors": {
    "device_activity_timeline_24h": {
      "entries": [
        {
          "event_name": "page_view",
          "event_id": "a1b2c3",
          "min_time": "2025-06-12T14:00:00.000Z",
          "max_time": "2025-06-12T14:02:00.000Z",
          "count": 3,
          "country_code": "US",
          "ip_address": "1.2.3.4",
          "identity": "wallet_0xabc"
        },
        {
          "event_name": "trade",
          "event_id": "d4e5f6",
          "min_time": "2025-06-12T14:05:00.000Z",
          "max_time": "2025-06-12T14:05:00.000Z",
          "count": 1,
          "country_code": "US",
          "ip_address": "1.2.3.4",
          "identity": "wallet_0xabc"
        },
        {
          "event_name": "login",
          "event_id": "g7h8i9",
          "min_time": "2025-06-12T15:30:00.000Z",
          "max_time": "2025-06-12T15:30:00.000Z",
          "count": 1,
          "country_code": "IR",
          "ip_address": "5.6.7.8",
          "identity": "wallet_0xabc"
        }
      ],
      "summary": {
        "count": 5,
        "entry_count": 3,
        "min_time": "2025-06-12T14:00:00.000Z",
        "max_time": "2025-06-12T15:30:00.000Z",
        "duration_seconds": 5400,
        "events": {
          "page_view": {
            "count": 3,
            "min_time": "2025-06-12T14:00:00.000Z",
            "max_time": "2025-06-12T14:02:00.000Z"
          },
          "trade": {
            "count": 1,
            "min_time": "2025-06-12T14:05:00.000Z",
            "max_time": "2025-06-12T14:05:00.000Z"
          },
          "login": {
            "count": 1,
            "min_time": "2025-06-12T15:30:00.000Z",
            "max_time": "2025-06-12T15:30:00.000Z"
          }
        }
      },
      "timestamp": "2025-06-12T14:00:00.000Z",
      "remaining_window_seconds": 81000
    }
  }
}

Deduplication

When dedupe_consecutive is enabled (default), consecutive events with the same event_name and identical captured field values are merged into a single entry. This dramatically reduces timeline size for repetitive actions like polling, page reloads, or heartbeat events — while preserving the full event count in summary.count. If a field value changes (e.g., country switches from US to IR), a new entry is created even if the event_name is the same.

Summary vs Entries

When summary.count exceeds summary.entry_count, it means older entries were evicted from the timeline but the summary stats (including per-event breakdowns in summary.events and duration_seconds) still reflect the full window of activity.