Skip to main content

Track media events with the native mobile trackers

The Snowplow media tracking APIs enable you to track events from media playback on the web and in mobile apps. Track changes in playback state (play, pause, seek), playback position (ping and percentage progress events), and ad playback (ad breaks, ad progress, ad clicks).

For details on the events and entities tracked, see the media tracking overview.

Example app

See the tracked media events and entities live as you watch a video in our React example app. View the source code.

Quick start

A media tracking session follows this lifecycle:

  1. Start tracking when the player loads (before playback begins)
  2. Update player state every second during playback
  3. Track events as they occur (play, pause, seek, etc.)
  4. End tracking when the user leaves
swift
// 1. Start tracking when player loads
let id = UUID().uuidString
let player = MediaPlayerEntity()
.duration(300)
.label("My Video Title")
.mediaType(.video)

let mediaTracking = tracker.media.startMediaTracking(id: id, player: player)

// 2. Update player state every second (or use AVPlayer auto-tracking)
mediaTracking.update(player: MediaPlayerEntity().currentTime(currentTime))

// 3. Track events as they occur
mediaTracking.track(MediaPlayEvent())
mediaTracking.track(MediaPauseEvent())
mediaTracking.track(MediaSeekStartEvent())
mediaTracking.track(MediaSeekEndEvent())
mediaTracking.track(MediaEndEvent())

// 4. End tracking when done
tracker.media.endMediaTracking(id: id)

Configuration

Configure media tracking when you call startMediaTracking. All configuration is optional.

Player properties

Set initial player properties to populate the media player entity. The label property is recommended as it helps identify content during analysis.

swift
let player = MediaPlayerEntity()
.currentTime(0) // Current playback position in seconds
.duration(300) // Total duration in seconds
.ended(false) // Whether playback has ended
.livestream(false) // Whether this is a live stream
.label("My Video") // Human-readable title (recommended)
.loop(false) // Whether to restart after ending
.mediaType(.video) // .video or .audio
.muted(false) // Whether audio is muted
.paused(true) // Whether playback is paused
.pictureInPicture(false) // Whether in picture-in-picture mode
.playbackRate(1.0) // Playback speed (1 = normal)
.quality("1080p") // Quality level
.volume(100) // Volume percentage (0-100)

let mediaTracking = tracker.media.startMediaTracking(id: id, player: player)

Ping events

Media ping events are sent at regular intervals (default: 30 seconds) to report playback position. You can configure ping behavior in the starting configuration.

swift
let configuration = MediaTrackingConfiguration(id: id)
.pingInterval(30) // Seconds between pings (default: 30)
.maxPausedPings(1) // Max pings while paused (default: 1)

// Or turn off pings entirely
let configuration = MediaTrackingConfiguration(id: id)
.pings(false)

Percentage progress

Track events when playback reaches specified percentage boundaries.

swift
let configuration = MediaTrackingConfiguration(id: id)
.boundaries([10, 25, 50, 75, 90]) // Fire events at these percentages

Session tracking

The media session entity is attached to all media events by default. It's optional for the Media Player data model, so you could choose not to include it.

We recommend tracking this entity.

swift
let configuration = MediaTrackingConfiguration(id: id).session(true)

Custom entities

You can attach custom entities to all events for this media tracking instance.

swift
let configuration = MediaTrackingConfiguration(id: id)
.entities([
SelfDescribingJson(
schema: "iglu:com.example/video_metadata/jsonschema/1-0-0",
andData: ["contentId": "abc123", "category": "tutorial"]
)
])

Filter events

Only track specific event types by providing an allowlist:

swift
let configuration = MediaTrackingConfiguration(id: id)
.captureEvents([MediaPlayEvent.self, MediaPauseEvent.self, MediaEndEvent.self])

Tracking events

Track events by calling the appropriate function when player events occur. For a complete list of available events and their properties, see the media events reference.

Playback events

swift
mediaTracking.track(MediaReadyEvent())        // Player is ready
mediaTracking.track(MediaPlayEvent()) // Playback started
mediaTracking.track(MediaPauseEvent()) // Playback paused
mediaTracking.track(MediaEndEvent()) // Playback ended
mediaTracking.track(MediaSeekStartEvent()) // Seek operation started
mediaTracking.track(MediaSeekEndEvent()) // Seek operation ended
mediaTracking.track(MediaBufferStartEvent()) // Buffering started
mediaTracking.track(MediaBufferEndEvent()) // Buffering ended

Player state events

swift
mediaTracking.track(MediaPlaybackRateChangeEvent(newRate: 1.5))
mediaTracking.track(MediaVolumeChangeEvent(newVolume: 80))
mediaTracking.track(MediaFullscreenChangeEvent(fullscreen: true))
mediaTracking.track(MediaPictureInPictureChangeEvent(pictureInPicture: true))
mediaTracking.track(MediaQualityChangeEvent(
newQuality: "1080p",
bitrate: 5000,
framesPerSecond: 30,
automatic: true
))
mediaTracking.track(MediaErrorEvent(
errorCode: "500",
errorName: "NetworkError",
errorDescription: "Failed to load media"
))

Ad events

Track advertising events with ad and ad break information. See the media ad and media ad break entity schemas for property details.

swift
// Ad break events
let adBreak = MediaAdBreakEntity(breakId: "break-1")
.name("pre-roll")
.breakType(.linear)
.podSize(3)
mediaTracking.track(MediaAdBreakStartEvent(), adBreak: adBreak)
mediaTracking.track(MediaAdBreakEndEvent())

// Ad events
let ad = MediaAdEntity(adId: "ad-1")
.name("Product Ad")
.creativeId("creative-1")
.duration(30)
.skippable(true)
mediaTracking.track(MediaAdStartEvent(), ad: ad)
mediaTracking.track(MediaAdFirstQuartileEvent())
mediaTracking.track(MediaAdMidpointEvent())
mediaTracking.track(MediaAdThirdQuartileEvent())
mediaTracking.track(MediaAdCompleteEvent())
mediaTracking.track(MediaAdSkipEvent())
mediaTracking.track(MediaAdClickEvent())
mediaTracking.track(MediaAdPauseEvent())
mediaTracking.track(MediaAdResumeEvent())

Custom events

Track custom self-describing events within the media session. The tracker automatically attaches media entities.

swift
mediaTracking.track(SelfDescribing(
schema: "iglu:com.example/video_interaction/jsonschema/1-0-0",
payload: ["action": "share", "platform": "twitter"]
))

Update player state

Update the player state every second during playback. This ensures accurate metrics in ping events and the session entity. This function does not send any events.

swift
mediaTracking.update(player: MediaPlayerEntity().currentTime(currentTime))

AVPlayer auto-tracking (iOS)

The iOS tracker can automatically track events from AVPlayer. Pass the player instance to startMediaTracking:

swift
let mediaTracking = tracker.media.startMediaTracking(
player: avPlayer,
configuration: MediaTrackingConfiguration(id: "my-video")
)

The following events are auto-tracked:

  • Play events
  • Pause events
  • Seek end events
  • Ping events
  • Percent progress events (if configured)
  • Buffer start events
  • End events
  • Error events