Reference - Analytics
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.
Common Integration Patterns
Custom Player Analytics Integration
Build a custom player that reports events back to Kaltura analytics.
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.
# 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.
# 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.
# 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