---
title: Reference
url: https://docs.kaltura.com/docs/rich-media-cms-apis/analytics/analytics-events-reference
---

## Error Handling & Best Practices

### Error Handling

#### stats.collect Errors

`stats.collect` is designed to be fire-and-forget. It returns a minimal response:

| Response | Meaning |
|----------|---------|
| Empty/null | Event accepted (standard behavior) |
| KalturaAPIException | Invalid KS, missing required fields |

#### analytics.trackEvent Errors

| HTTP Status | Cause | Resolution |
|-------------|-------|------------|
| 200 | Event accepted | No action needed |
| 400 | Missing required fields | Include `eventType`, `partnerId` |
| 401 | Invalid or expired KS | Generate a new KS |
| 404 | Wrong analytics server URL | Verify `$KALTURA_ANALYTICS_URL` |

#### Retry Logic

For transient failures (HTTP 500, network timeout):
- Retry up to 3 times with exponential backoff (1s, 2s, 4s)
- Queue events locally if the server is unreachable
- Send queued events in order when connectivity resumes
- Retry only 5xx/timeout errors — 400/401 responses indicate a request problem to fix before resending

### Best Practices

**Event ordering matters.** Fire events in lifecycle order (WIDGET_LOADED → MEDIA_LOADED → PLAY → quartiles). Out-of-order events may cause incorrect analytics calculations (e.g., a PLAY event without a preceding WIDGET_LOADED).

**Fire quartiles once per session.** Each quartile event (25%, 50%, 75%, 100%) should fire exactly once per playback session. Seeking past a quartile does not count — only natural forward playback reaching that position should trigger the event.

**Use consistent session IDs.** All events in a single playback session must share the same `sessionId`. A new session ID is generated each time the user starts a new playback (including replays).

**Include userId for attribution.** Always include `userId` in the KS for per-user analytics. Without it, events are anonymous and cannot be correlated with user-level reports.

**Use appId for multi-app environments.** If you run multiple applications on one Kaltura account, use `appId:<name>` KS privileges to segment analytics per application. This enables separate dashboards and reports for each app.

**Kaltura Player v7 is the reference implementation.** The built-in Kaltura Player handles all event reporting automatically. When building a custom player, use the Player v7 analytics behavior as the reference for which events to fire and when.

**Gamification integration.** `viewPeriod` events (derived from playback events) feed the Gamification rules engine. Custom player events reported via `stats.collect` trigger leaderboard scoring, badge progress, and certificate tracking. See [Gamification Guide](/docs/events-collaboration/gamification-api/gamification-overview).

### Common Integration Patterns

#### Custom Player Analytics Integration

Build a custom player that reports events back to Kaltura analytics.

```bash
SESSION_ID="custom_player_$(date +%s)_$$"

# Report lifecycle events in order
for EVENT in 1 2 3; do
  curl -s -X POST "$KALTURA_SERVICE_URL/service/stats/action/collect" \
    -d "ks=$KALTURA_KS" \
  -d "format=1" \
    -d "event[objectType]=KalturaStatsEvent" \
    -d "event[partnerId]=$KALTURA_PARTNER_ID" \
    -d "event[entryId]=$KALTURA_ENTRY_ID" \
    -d "event[eventType]=$EVENT" \
    -d "event[sessionId]=$SESSION_ID" \
    -d "event[eventTimestamp]=$(date +%s)" \
    -d "event[referrer]=https://my-app.example.com/player"
done

# Report quartiles as playback progresses
for QUARTILE in 4 5 6 7; do
  curl -s -X POST "$KALTURA_SERVICE_URL/service/stats/action/collect" \
    -d "ks=$KALTURA_KS" \
  -d "format=1" \
    -d "event[objectType]=KalturaStatsEvent" \
    -d "event[partnerId]=$KALTURA_PARTNER_ID" \
    -d "event[entryId]=$KALTURA_ENTRY_ID" \
    -d "event[eventType]=$QUARTILE" \
    -d "event[sessionId]=$SESSION_ID" \
    -d "event[eventTimestamp]=$(date +%s)"
done
```

#### Full Funnel Tracking (Page + Video)

Track the full user journey from portal visit through video playback.

```bash
# Page load — track portal landing
curl -s -X POST "$KALTURA_ANALYTICS_URL/api_v3/index.php?service=analytics&action=trackEvent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "eventType=10003" \
  -d "partnerId=$KALTURA_PARTNER_ID" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "kalturaApplication=events-portal" \
  -d "pageType=lobby"

# CTA click — user navigated to session page
curl -s -X POST "$KALTURA_ANALYTICS_URL/api_v3/index.php?service=analytics&action=trackEvent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "eventType=10002" \
  -d "partnerId=$KALTURA_PARTNER_ID" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "kalturaApplication=events-portal" \
  -d "buttonType=navigation" \
  -d "buttonName=view-session"

# Video playback — stats.collect handles play events
curl -s -X POST "$KALTURA_SERVICE_URL/service/stats/action/collect" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "event[objectType]=KalturaStatsEvent" \
  -d "event[partnerId]=$KALTURA_PARTNER_ID" \
  -d "event[entryId]=$KALTURA_ENTRY_ID" \
  -d "event[eventType]=3" \
  -d "event[sessionId]=$SESSION_ID" \
  -d "event[eventTimestamp]=$(date +%s)"
```

#### Server-Side Playback Tracking

Backend systems report plays for unified analytics across all channels.

```bash
# Generate server-side KS with userId
KS=$(curl -s -X POST "$KALTURA_SERVICE_URL/service/session/action/start" \
  -d "secret=$KALTURA_ADMIN_SECRET" \
  -d "format=1" \
  -d "type=0" \
  -d "partnerId=$KALTURA_PARTNER_ID" \
  -d "userId=server-process@example.com" | tr -d '"')

# Report server-side playback
SESSION_ID="server_$(date +%s)"
for EVENT_TYPE in 1 2 3 4 5 6 7; do
  curl -s -X POST "$KALTURA_SERVICE_URL/service/stats/action/collect" \
    -d "ks=$KALTURA_KS" \
  -d "format=1" \
    -d "event[objectType]=KalturaStatsEvent" \
    -d "event[partnerId]=$KALTURA_PARTNER_ID" \
    -d "event[entryId]=$KALTURA_ENTRY_ID" \
    -d "event[eventType]=$EVENT_TYPE" \
    -d "event[sessionId]=$SESSION_ID" \
    -d "event[eventTimestamp]=$(date +%s)" \
    -d "event[referrer]=server://batch-process"
done
```

#### Per-Application Segmentation

Separate analytics for multiple applications on the same Kaltura account.

```bash
# Application A
KS_A=$(curl -s -X POST "$KALTURA_SERVICE_URL/service/session/action/start" \
  -d "secret=$KALTURA_ADMIN_SECRET" \
  -d "format=1" \
  -d "type=0" \
  -d "partnerId=$KALTURA_PARTNER_ID" \
  -d "userId=viewer@example.com" \
  -d "privileges=appId:corporate-portal" | tr -d '"')

# Application B
KS_B=$(curl -s -X POST "$KALTURA_SERVICE_URL/service/session/action/start" \
  -d "secret=$KALTURA_ADMIN_SECRET" \
  -d "format=1" \
  -d "type=0" \
  -d "partnerId=$KALTURA_PARTNER_ID" \
  -d "userId=viewer@example.com" \
  -d "privileges=appId:customer-education" | tr -d '"')

# Events from KS_A are tagged "corporate-portal"
# Events from KS_B are tagged "customer-education"
# Pull per-app analytics via report.getTable with the respective KS
```
