Skip to main content

Media tracking with the Flutter tracker

Introduced in version 0.7 of the tracker

Media tracking is available in the Flutter tracker since version 0.7.0.

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
dart
// 1. Start tracking when player loads
final id = const Uuid().v4();
MediaTracking mediaTracking = await tracker.startMediaTracking(
configuration: MediaTrackingConfiguration(
id: id,
player: const MediaPlayerEntity(
duration: 300,
label: 'My Video Title',
mediaType: MediaType.video,
)
)
);

// 2. Update player state every second
await mediaTracking.update(
player: MediaPlayerEntity(currentTime: currentTime)
);

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

// 4. End tracking when done
await tracker.endMediaTracking(id: id);
Flutter web configuration
To track media events on web with the Flutter tracker, configure the JavaScript plugin URL:
dart
SnowplowTracker tracker = await Snowplow.createTracker(
namespace: namespace,
endpoint: endpoint,
trackerConfig: const TrackerConfiguration(
jsMediaPluginURL: "https://cdn.jsdelivr.net/npm/@snowplow/browser-plugin-media@latest/dist/index.umd.min.js"
)
);

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.

dart
MediaTracking mediaTracking = await tracker.startMediaTracking(
configuration: const MediaTrackingConfiguration(
id: id,
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: MediaType.video, // MediaType.video or MediaType.audio
muted: false, // Whether audio is muted
paused: true, // Whether playback is paused
pictureInPicture: false, // Whether in picture-in-picture mode
playerType: 'html5', // Player type identifier
playbackRate: 1.0, // Playback speed (1 = normal)
quality: '1080p', // Quality level
volume: 100 // Volume percentage (0-100)
)
)
);

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.

dart
MediaTracking mediaTracking = await tracker.startMediaTracking(
configuration: const MediaTrackingConfiguration(
id: id,
pingInterval: 30, // Seconds between pings (default: 30)
maxPausedPings: 1 // Max pings while paused (default: 1)
)
);

// Or turn off pings entirely
MediaTracking mediaTracking = await tracker.startMediaTracking(
configuration: const MediaTrackingConfiguration(id: id, pings: false)
);

Percentage progress

Track events when playback reaches specified percentage boundaries.

dart
MediaTracking mediaTracking = await tracker.startMediaTracking(
configuration: const 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.

dart
MediaTracking mediaTracking = await tracker.startMediaTracking(
configuration: const MediaTrackingConfiguration(id: id, session: true)
);

Custom entities

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

dart
MediaTracking mediaTracking = await tracker.startMediaTracking(
configuration: const MediaTrackingConfiguration(
id: id,
contexts: [
SelfDescribing(
schema: "iglu:com.example/video_metadata/jsonschema/1-0-0",
data: {"contentId": "abc123", "category": "tutorial"}
)
]
)
);

Filter events

Media event filtering isn't available for the Flutter tracker.

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

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

Player state events

dart
await mediaTracking.track(const MediaPlaybackRateChangeEvent(newRate: 1.5));
await mediaTracking.track(const MediaVolumeChangeEvent(newVolume: 80));
await mediaTracking.track(const MediaFullscreenChangeEvent(fullscreen: true));
await mediaTracking.track(const MediaPictureInPictureChangeEvent(pictureInPicture: true));
await mediaTracking.track(const MediaQualityChangeEvent(
newQuality: '1080p',
bitrate: 5000,
framesPerSecond: 30,
automatic: true
));
await mediaTracking.track(const 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.

dart
// Ad break events
await mediaTracking.track(
MediaAdBreakStartEvent(),
adBreak: const MediaAdBreakEntity(
breakId: 'break-1',
name: 'pre-roll',
breakType: MediaAdBreakType.linear,
podSize: 3
)
);
await mediaTracking.track(MediaAdBreakEndEvent());

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

Custom events

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

dart
await mediaTracking.track(
const SelfDescribing(
schema: "iglu:com.example/video_interaction/jsonschema/1-0-0",
data: {"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.

dart
await mediaTracking.update(
player: MediaPlayerEntity(currentTime: currentTime)
);