Video Spec

Segment’s video spec helps you define how a customer is engaging with your video and ad content. The below documentation covers the naming syntax and conventions for how you should send events when tracking video analytics.

NOTE: Not all destinations support video tracking and you should always check with the individual destination documentation to confirm.

Getting Started

Before you start implementing the Segment video spec, you should understand the overall structure and classification of events. The video spec will be organized into three distinct types of events:

  • Playback events
  • Content events
  • Ad events

Playback Events

You can think of playback events being related to the actual playback of the video content. This means that these events are meant to track information about the video player (ie. pause, resume, play). Thus, you can think of playback events to be at the session level. For example, when a customer presses play on your video, you would start by sending a Video Playback Started event with a unique session_id.

For the duration of that user’s session with that specific video player, all subsequent events generated from this session/playback should be tied with the same aforementioned session_id. So if you had a web page that had two video players, you would have two separate sessions and session_ids while contrastingly if you only had one video player on the page but the playback played two video contents in a row, you would only have one session but two contents tied to it.

Below is the full list of Playback events and their supported properties:

Segment Event NameDescription
Video Playback StartedWhen a user presses Play
Video Playback PausedWhen a user presses Pause
Video Playback InterruptedWhen the playback stops unintentionally (ie. network loss, browser close/redirect, app crash)
Video Playback Buffer StartedWhen playback starts buffering content or ad
Video Playback Buffer CompletedWhen playback finishes buffering content or ad
Video Playback Seek StartedWhen a user manually seeks a certain position of the content or ad in the playback
Video Playback Seek CompletedWhen a user finishes seeking a certain position of the content or ad in the playback
Video Playback ResumedWhen playback is resumed after being paused
Video Playback CompletedWhen playback is complete and only when the session is finished
Segment Property NameTypeDescription
session_idstringThe unique ID of the overall session used to tie all events generated from a specific playback
content_asset_id or content_asset_idsstring | arrayFor Video Playback Started events only, you should send the plural form with an array of unique IDs of the content assets that will be played in this playback session. For all other playback events, you should send the singular form with the ID of the current content asset playing at the time of the event
content_pod_id or content_pod_idsstring | arrayFor Video Playback Started events only, you should send the plural form with an array of unique IDs of the content pods that will be played in this playback session. For all other playback events, you should send the singular form with the ID of the current content pod playing at the time of the event
ad_asset_id or as_asset_idsstring | arrayFor Video Playback Started events only, you should send the plural form with an array of unique IDs of the ad assets that will be played in this playback session. For all other playback events, you should send the singular form with the ID of the current ad asset playing at the time of the event
ad_pod_id or ad_pod_idsstring | arrayFor Video Playback Started events only, you should send the plural form with an array of unique IDs of the ad pods that will be played in this playback session. For all other playback events, you should send the singular form with the ID the current ad pod playing at the time of the event
ad_type or ad_typespicklist | array of picklistFor Video Playback Started events only, you should send the plural form with an array of the types of ads that will be played in this playback session. For all other playback events, you should send the singular form with the type of ad playing at the time of the event. Values can include 'pre-roll', 'mid-roll', and 'post-roll'
positionnumberThe current index position in seconds of the playhead. If the playback is a livestream (properties.livestream = true), you must send a negative integer that represents the offset in seconds in relation to the current timestamp. For example, if content is being livestreamed at 8PM but the viewer is 30 seconds behind, the value of this property should be -30.
seek_positionnumberThe index position in seconds of the playhead where the user is seeking to
total_lengthnumberThe total duration of the playback in seconds. This should include the duration of all your content and ad included in this playback session. For livestream playback, send null
bitratenumberThe average kbps
video_playerstringThe name of the video player (ie 'youtube', 'tv')
soundnumberThe sound level of the playback represented in a 0 to 100 scale where 0 is muted and 100 is full volume
full_screenbooleantrue if playback is currently in full screen mode and false otherwise
ad_enabledbooleanfalse if the user has adblock or any other ad blockers, true otherwise if they can view your video ads
qualitystringThe quality of the video, ie. 'highres', 'hd1080', '480p'
methodstringFor Video Playback Interrupted event, you can send this property denoting how the playback was interrupted (ie. 'browser redirect', 'device lock', ‘call')
livestreambooleanIf the playback will be a livetream, send true, otherwise false

Content Events

Underneath the playback level, we now have the pod level. A pod can be seen as a “group” or “segment” of either the content or advertisement. So within a playback session, you might have a content and one mid-roll advertisement. This would mean that you could have two content pods (since the mid-roll ad split the content playback into two sections) while you might have one ad pod for the mid-roll ad.

The below lists all the supported Content events and properties related to tracking the engagement with your actual video content. Note that you should separate the properties or concerns of the video player from these events, as those are already sent (and reserved for) the playback events.

Segment Event NameDescription
Video Content StartedWhen the video content starts playing
Video Content PlayingHeartbeats that you can fire every X seconds to track how far into the content the user is currently viewing
Video Content CompletedWhen the video content finishes playing
Segment Property NameTypeDescription
session_idstringThe unique ID of the overall session used to tie all events generated from a specific playback. This value should be same across all playback, content, and ad events if they are from the same playback session
asset_idstringThe unique ID of the content asset
pod_idstringThe unique ID of the content pod
titlestringThe title of the video content
descriptionstringShort description of the video content
keywordsarrayAn array of arbitrary keywords or tags that describe or categorize the video content
seasonstringThe season number if applicable
episodestringThe episode number if applicable
genrestringThe genre of the content, ie. 'comedy', 'action'
programstringThe name of the program, show, etc. of the content if applicable
publisherstringThe content creator, author, producer, or publisher
channelstringThe channel in which the video content is playing, ie. 'espn', 'my blog'
full_episodebooleantrue if content is a full episode and false otherwise
livestreambooleantrue if content is currently being streamed live
airdatestring | dateThe original air date or published date
positionnumberThe current index position in seconds of the playhead. If the content is a livestream (properties.livestream = true), you must send a negative integer that represents the offset in seconds in relation to the current timestamp. For example, if content is being livestreamed at 8PM but the viewer is 30 seconds behind, the value of this property should be -30.
total_lengthnumberThe total duration of the current content asset in seconds. For livestream content you can send null.
bitratenumberThe average kbps

Ad Events

Just like Content events, Ad events also live underneath the playback level and at the pod level. A given ad pod can have multiple ad assets (or just one) and a playback session might have multiple ad pods. For example, if your video playback has two pre-roll, one mid-roll, and one post-roll ads, you would have three ad pods:

  • ad pod 1: plays the two pre-roll ads
  • ad pod 2: plays the one mid-roll ad
  • ad pod 3: plays the one post-roll ad

The below lists all the supported Ad events and properties related to tracking the engagement with your video ads. Note that you should separate the properties or concerns of the video player from these events, as those are already sent (and reserved for) the playback events.

Segment Event NameDescription
Video Ad StartedWhen the video ad starts playing
Video Ad PlayingHeartbeats that you can fire every X seconds to track how far into the ad the user is currently viewing
Video Ad CompletedWhen the video ad finishes playing
Segment Property NameTypeDescription
session_idstringThe unique ID of the overall session used to tie all events generated from a specific playback. This value should be same across all playback, content, and ad events if they are from the same playback session
asset_idstringThe unique ID of the ad asset
pod_idstringThe unique ID of the ad pod
titlestringThe title of the video ad
typepicklistThe ad type. You can send either 'pre-roll', 'mid-roll', or 'post-roll
publisherstringThe ad creator, author, producer, or publisher
load_typepicklist'dynamic' if ads are loaded dynamically and 'linear' if ads are same for all users
positionnumberThe current index position in seconds of the playhead with respect to the length of the ad
total_lengthnumberThe total duration of the current ad asset in seconds
content.$For video destinations that require content metadata to be sent with ad events, you can send all the content metadata nested under this property. ie. content.asset_id, content.title

NOTE: Since some video destinations require sending Content metadata along with Ad metadata, you may need to send your content properties also in all your ad events under properties.content depending on the video destination you are using.

Resuming Playback

When you fire a Video Playback Resumed event, you should immediately call a Segment heartbeat event, Video Content Playing or Video Ad Playing depending on what the playback resumed to. This should effectively mean that you are also resuming your 10 second heartbeats (since they should’ve been paused after sending Video Playback Paused event).

Example Event Lifecycle

Below is an example of how one might implement the video spec:

1) User presses play on a video:

analytics.track('Video Playback Started', {
  session_id: '12345',
  content_asset_ids: ['0129370'],
  content_pod_ids: ['segA', 'segB'],
  ad_asset_ids: [ 'ad123', 'ad097' ],
  ad_pod_ids: ['adSegA', 'adSegB'],
  ad_types: ['mid-roll', 'post-roll'],
  position: 0,
  total_length: 392,
  bitrate: 100,
  video_player: 'youtube',
  sound: 88,
  full_screen: false,
  ad_enabled: false,
  quality: 'hd1080'
});

2) Playback starts to play content:

analytics.track('Video Content Started', {
  session_id: '12345',
  asset_id: '0129370',
  pod_id: 'segA',
  title: 'Interview with Tony Robbins',
  description: 'short description',
  keywords: ['entrepreneurship', 'motivation'],
  season: '2',
  episode: '177',
  genre: 'entrepreneurship',
  program: 'Tim Ferris Show',
  publisher: 'Tim Ferris',
  position: 0,
  total_length: 360,
  channel: 'espn',
  full_episode: true,
  livestream: false,
  airdate: '1991-08-13'
});

3) User views content for 20 seconds and we have 10 second heartbeats:

analytics.track('Video Content Playing', {
  session_id: '12345',
  asset_id: '0129370',
  pod_id: 'segA',
  title: 'Interview with Tony Robbins',
  description: 'short description',
  keywords: ['entrepreneurship', 'motivation'],
  season: '2',
  episode: '177',
  genre: 'entrepreneurship',
  program: 'Tim Ferris Show',
  publisher: 'Tim Ferris',
  position: 10,
  total_length: 360,
  channel: 'espn',
  full_episode: true,
  livestream: false,
  airdate: '1991-08-13'
});
analytics.track('Video Content Playing', {
  session_id: '12345',
  asset_id: '0129370',
  pod_id: 'segA',
  title: 'Interview with Tony Robbins',
  description: 'short description',
  keywords: ['entrepreneurship', 'motivation'],
  season: '2',
  episode: '177',
  genre: 'entrepreneurship',
  program: 'Tim Ferris Show',
  publisher: 'Tim Ferris',
  position: 20,
  total_length: 360,
  channel: 'espn',
  full_episode: true,
  livestream: false,
  airdate: '1991-08-13'
});

4) Playback is paused & resumed:

analytics.track('Video Playback Paused', {
  session_id: '12345',
  content_asset_id: '0129370',
  content_pod_id: 'segA',
  ad_asset_id: null,
  ad_pod_id: null,
  ad_type: null,
  position: 21,
  total_length: 392,
  video_player: 'youtube',
  sound: 88,
  bitrate: 100,
  full_screen: false,
  ad_enabled: false,
  quality: 'hd1080'
});
analytics.track('Video Playback Resumed', {
  session_id: '12345',
  content_asset_id: '0129370',
  content_pod_id: 'segA',
  ad_asset_id: null,
  ad_pod_id: null,
  ad_type: null,
  position: 21,
  total_length: 392,
  sound: 88,
  bitrate: 100,
  full_screen: false,
  video_player: 'youtube',
  ad_enabled: false,
  quality: 'hd1080'
});

5) Mid-roll ad starts playing:

analytics.track('Video Ad Started', {
  session_id: '12345',
  asset_id: 'ad123',
  pod_id: 'adSegA',
  type: 'mid-roll',
  title: 'Segment Connection Modes',
  publisher: 'Segment',
  position: 0,
  total_length: 21,
  load_type: 'dynamic'
});

6) User watches the full 21 second ad and we have 10 second heartbeats:

analytics.track('Video Ad Playing', {
  session_id: '12345',
  asset_id: 'ad123',
  pod_id: 'adSegA',
  type: 'pre-roll',
  title: 'Segment Connection Modes',
  publisher: 'Segment',
  position: 10,
  total_length: 21,
  load_type: 'dynamic'
});
analytics.track('Video Ad Playing', {
  session_id: '12345',
  asset_id: 'ad123',
  pod_id: 'adSegA',
  type: 'pre-roll',
  title: 'Segment Connection Modes',
  publisher: 'Segment',
  position: 20,
  total_length: 21,
  load_type: 'dynamic'
});
analytics.track('Video Ad Completed', {
  session_id: '12345',
  asset_id: 'ad123',
  pod_id: 'adSegA',
  type: 'pre-roll',
  title: 'Segment Connection Modes',
  publisher: 'Segment',
  position: 21,
  total_length: 21,
  load_type: 'dynamic'
});

7) Content resumes, user finishes the full content:

analytics.track('Video Content Playing', {
  session_id: '12345',
  asset_id: '0129370',
  pod_id: 'segB',
  title: 'Interview with Tony Robbins',
  description: 'short description',
  keywords: ['entrepreneurship', 'motivation'],
  season: '2',
  episode: '177',
  genre: 'entrepreneurship',
  program: 'Tim Ferris Show',
  publisher: 'Tim Ferris',
  position: 31,
  total_length: 360,
  channel: 'espn',
  full_episode: true,
  livestream: false,
  airdate: '1991-08-13'
});

< Video Content Playing hearbeats every 10 seconds >

analytics.track('Video Content Completed', {
  session_id: '12345',
  asset_id: '0129370',
  pod_id: 'segB',
  title: 'Interview with Tony Robbins',
  description: 'short description',
  keywords: ['entrepreneurship', 'motivation'],
  season: '2',
  episode: '177',
  genre: 'entrepreneurship',
  program: 'Tim Ferris Show',
  publisher: 'Tim Ferris',
  position: 360,
  total_length: 360,
  channel: 'espn',
  full_episode: true,
  livestream: false,
  airdate: '1991-08-13'
});

8) 11 second post-roll ad plays after content finishes:

analytics.track('Video Ad Started', {
  session_id: '12345',
  asset_id: 'ad097',
  pod_id: 'adSegB',
  type: 'post-roll',
  title: 'Segment Cross Domain IDs',
  publisher: 'Segment',
  position: 0,
  total_length: 11,
  load_type: 'dynamic'
});
analytics.track('Video Ad Playing', {
  session_id: '12345',
  asset_id: 'ad097',
  pod_id: 'adSegB',
  type: 'post-roll',
  title: 'Segment Cross Domain IDs',
  publisher: 'Segment',
  position: 10,
  total_length: 11,
  load_type: 'dynamic'
});
analytics.track('Video Ad Completed', {
  session_id: '12345',
  asset_id: 'ad097',
  pod_id: 'adSegB',
  type: 'post-roll',
  title: 'Segment Cross Domain IDs',
  publisher: 'Segment',
  position: 11,
  total_length: 11,
  load_type: 'dynamic'
});

9) Playback finishes:

analytics.track('Video Playback Completed', {
  session_id: '12345',
  content_asset_id: null,
  content_pod_id: null,
  ad_asset_id: 'ad907',
  ad_pod_id: 'adSegB',
  ad_type: null,
  position: 392,
  total_length: 392,
  sound: 88,
  bitrate: 100,
  full_screen: false,
  video_player: 'youtube',
  ad_enabled: false,
  quality: 'hd1080'
});

If you have any questions or see anywhere we can improve our documentation, please let us know or kick off a conversation in the Segment Community!