Select platform: [HTML5](https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/html5/timed-metadata "View this page for the HTML5 platform docs.") [Roku](https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/roku/timed-metadata "View this page for the Roku platform docs.")

<br />

The Interactive Media Ads (IMA) Dynamic Ad Insertion SDK (DAI) relies on
metadata information embedded in the stream's media segments (in-band metadata),
or in the streaming manifest file (in-manifest metadata) to track viewers'
positions and client-side ad events. Metadata is available from the DAI stream
in different formats, depending on the type of stream being played. The IMA DAI
SDK handles all metadata formats through a single API.

Your app is responsible for capturing metadata and forwarding it to the IMA DAI
SDK. The SDK offers the
[`StreamManager.onMessage()`](https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/roku/reference/ima.StreamManager#.onMessage)
method to pass this information. This method forwards metadata in the form of a
`msg` object provided by the roVideo port. These objects are then processed by
the IMA DAI SDK to establish the timing for ad events. It takes a single
argument:

- `msg`: a msg type object provided by the roVideo port.

## Metadata sample code

Here's an example of how to handle the metadata from the roVideo port and
pass it to the IMA DAI SDK through `StreamManager.onMessage()`.

    Sub runLoop()
      ' Forward all timed metadata events to IMA.
      m.top.video.timedMetaDataSelectionKeys = ["*"]

      ' Cycle through all the fields and set listeners.
      ' IMPORTANT: Failure to listen to the position and timedmetadata fields could
      ' result in ad impressions not being reported.
      m.port = CreateObject("roMessagePort")
      fields = m.top.video.getFields()
      for each field in fields
        m.top.video.observeField(field, m.port)
      end for

      while True
        msg = wait(1000, m.port)
        if m.top.video = invalid
          print "exiting"
          exit while
        end if

        m.streamManager.onMessage(msg)
        currentTime = m.top.video.position
        If currentTime > 3 And not m.top.adPlaying
           m.top.video.enableTrickPlay = true
        End If
      end while
    End Sub

For more information on how to incorporate the loop handling stream metadata
into your app, see the
[IMA Roku getting started guide](https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/roku). The
[event listener and stream start section](https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/roku#add-event-listeners-and-start-the-stream)
of the guide contains the metadata handling loop.

## Stream format and container requirements

To enable client-side ad tracking on Roku, you must use media segments
in your DAI stream packaged in a supported container format. This process
lets Roku OS to extract timed metadata.

The Roku Media Player supports in-band ID3 metadata extraction on the
following container formats:

- MPEG-2 Transport Stream (TS)
- Fragmented MP4
- Common Media Application Format (CMAF)

Raw elementary audio streams, such as raw Advanced Audio
Coding (AAC) segments, aren't supported for timed metadata on Roku OS. The
Roku Media Player can't extract ID3 timed metadata from raw AAC audio
streams, which prevents IMA SDK from receiving metadata events and sending
ad impression or tracking beacons. For all audio-only and audio-rendition
streams, you must use streams with supported container format packaging, such
as TS, MP4, or CMAF.

## HLS CMAF streams

Linear DAI HLS streams using the Common Media Application Framework (CMAF) pass
timed metadata through in-band eMSGv1 boxes following the [ID3 through
CMAF](https://aomediacodec.github.io/id3-emsg/) standard. These eMSG boxes are
embedded at the beginning of each media segment, with each ID3 eMSG containing
a PTS relative to the last discontinuity in the stream.

For IMA Roku, all HLS CMAF streams send in-band ID3 data using the eMSGv0 format.
IMA combines information provided by the eMSGv0 format with information
from the video object.

To enable proper parsing of HLS CMAF stream ID3 events, you must send your
video object in the stream request using
[`StreamRequest.videoObject`](https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/roku/reference/ima.StreamRequest#.videoObject).