Live - DASH

The process to request a DASH-Live stream with client-side tracking enabled can be broken down into the following steps (the technical details for every step follow below):

  1. The App performs a request to the endpoint for a channel and retrieves the URL to the DASH manifest (mediaURL) and VAST data (vastURL)

  2. The mediaURL can now be used to initialize the player and start playback. (Note: in the example below we use a Shaka-Player in an HTML5 environment)

  3. Parallel to step 2 the app can perform a request to the vastURL to load the current VAST information for the live-channel

  4. While the player is constantly loading sub-manifests and media-chunks for playback the app has initialized the VAST handling and is waiting for the player to reach an ad

  5. As soon as an ad signaled in the VAST-Tag is starting to playback, compared to the timeline information from the player or timeline-region-enter events the app will send requests to all tracking-URLs (beacons) defined in the VAST-response for the start event. The same logic applies to the events: pause, resume, finish, firstQuartile, midpoint, thirdQuartile, complete

1. Manifest API Request

The first request to obtain a dash-manifest and VAST tracking information will create a DASH-Live session for the requesting client. The URL to the ad-insertion enabled channel is called outputUrl and can be viewed at or via API endpoint.

GET Request: 

Response body:

    "mediaURL": "",
    "vastURL": ""


Before calling the vastUrl you have to attend the AdId which can be found in the response of the mediaURL as described below.

The full URL schema is:

2. Player call with mediaURL

You will find below an example of how to playback a DASH-Live stream in a browser.

For any other player and environment you have to load and initialize your player of choice. Afterward, pass it the mediaURL and start the playback.


<!DOCTYPE html>
    <title>Test Player</title>
    <script src=""></script>
    <h1> Test</h1>
    <video id="video" controls autoplay></video>


(async () => {
  const response = await fetch('')
  const {mediaURL, vastURL} = await response.json()
  const video = document.getElementById("video");
  const player = new shaka.Player(video);

3. Load VAST data

To gather the VAST-related data call the vastURL gathered in step 1.

Build the URL the following way: ${vastURL}/${adId}.xml

GET Request:

Response Body:

  <EventStream schemeIdUri="urn:ssai:vast:event:2020" timescale="1000">
    <Event id="0" presentationTime="0" duration="5000">vast:a2363da8-2331-4483-995d-5286220005d8</Event>
    <Event id="1" presentationTime="500">beacon:start</Event>
    <Event id="2" presentationTime="1250">beacon:firstQuartile</Event>
    <Event id="3" presentationTime="2500">beacon:midpoint</Event>
    <Event id="4" presentationTime="3750">beacon:thirdQuartile</Event>
    <Event id="5" presentationTime="4500">beacon:complete</Event>

Each period in the DASH manifest that signals an inserted ad clip contains an event stream for the VAST tracking.

The first event id=vast:adId signals an id under which the whole original VAST response, including all tracking event information for the respective clip, can be obtained from the SSAI-API under the provided vastURL contained in the initial session created response. The following events, id=beacon:start etc. trigger the VAST quartile reporting at the respective points in the clips presentation timeline.

Every time a new ad is signaled in the DASH manifests, continuously pulled by the player, the app needs to load the vast information for this ad

4. Detect the start of an ad in the stream

At the time an ad is detected in the DASH-Stream fetch the vast information for this ad from the vastURL: ${vastBaseUrl}/${adId}.xml.

How to get access to the timeline events is highly dependent on the player you are using.

Javascript - Shaka-Player:

// If a new timeline-region (or segment) is added load the related VAST data
player.addEventListener("timelineregionadded", evt => {
  // is e.g. vast:f295a0cc-9d2b-4014-9858-87fb28fc6ec1
  const [type, id] =":");

  if (type === "vast") {
    const response = await fetch(`${this.vastBaseUrl}/${id}.xml`)
    const vastXML = await response.text()
    const vast = document.createElement("div");
    // remove xml document declaration as required by xhtml
    vast.innerHTML = vastXml.substr(vastXml.indexOf("?>") + 2);
    // work with the vast response
    // ...

5. Keep track of the ad playback and send beacons

As soon as the VAST information for the upcoming ad is loaded the client needs to track if the player reaches one of the predefined timeline positions and fire the events accordingly

Javascript - Shaka-Player:

// start of dash event
player.addEventListener("timelineregionenter", evt => {
    const [type, arg] =":")

    // 'id' and 'vast' from the request at 4 above
    // fire the impression or beacon
    if(type === 'vast) fire('Impression', vast)
    if(type === 'beacon) fire(`Tracking[event='${arg}']`, vast)

function fire(selector, vast) {
  $(vast) // this requires jQuery
    .each((n, elem) => {
      const url = elem.firstChild.textContent.replace(/\[/g, "").replace(/\]/g, "").replace(/CDATA/g, "")
      fetch(url, { mode: "no-cors" }).catch(err =>
        // Error handling

The above example only handles the start of an add. You have to implement the handling for pause, resume, finish, firstQuartile, midpoint, thirdQuartile, and complete as well.

See the below example implementation for a full example of the DASH Vast tracking.

Example Implementation

The example implementation handles Impression- and progress (beacon) events based on the DASH event timeline as well as the following tracking events based on HTML5 video element events:

  • mute/unmute

  • pause

  • resume

  • expand/collapse

Last updated