Prepare client for pod serving redirect

  • The Google DAI Pod Serving API enables server-side ad insertion with Google Ads while allowing control over video stitching, but it's recommended to use the IMA DAI SDK if available for your platform.

  • To integrate the Pod Serving API for VOD streams, you need to register your stream, request the stream manifest from a manifest manipulator, play the stream, poll for ad metadata, listen for ad events, update the UI, and send media verification pings.

  • The API provides URLs for stream registration, metadata retrieval, and media verification, and it supports HLS and MPEG-DASH streaming protocols.

  • When an ad event is triggered, the client application needs to update its UI accordingly, such as hiding seek controls and displaying ad position information.

  • Media verification pings must be sent to Ad Manager for all ad events except those with the type progress, ensuring accurate ad tracking and reporting.

This guide covers developing a client application to load an HLS or DASH livestream with Pod serving API and your manifest manipulator.

Prerequisites

Before continuing, you must have the following:

Make a stream request

When your user selects a stream, do the following:

  1. Make a POST request to the livestream service method. For details, see Method: stream.

  2. Pass ad targeting parameters in application/x-www-form-urlencoded or application/json formats. This request registers a stream session with Google DAI.

    The following example makes a stream request:

    Form encoding

    const url = `https://dai.google.com/ssai/pods/api/v1/` +
          `network/NETWORK_CODE/custom_asset/CUSTOM_ASSET_KEY/stream`;
    
    const params = new URLSearchParams({
            cust_params: 'section=sports&page=golf,tennis'
    }).toString();
    
    const response = await fetch(url, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: params
    });
    
    console.log(await response.json());
    

    JSON encoding

    const url = `https://dai.google.com/ssai/pods/api/v1/` +
          `network/NETWORK_CODE/custom_asset/CUSTOM_ASSET_KEY/stream`;
    
    const response = await fetch(url, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json'
            },
            body: JSON.stringify({
              cust_params: {
                section: 'sports',
                page: 'golf,tennis'
              }
            })
    });
    
    console.log(await response.json());
    

    If successful, you see output similar to the following:

    {
    "stream_id": "8d2b2292-6356-4c0e-94be-cece01d2df2e:DLS",
    "media_verification_url": "https://dai.google.com/view/.../event/c14aZDWtQg-ZwQaEGl6bYA/media/",
    "metadata_url": "https://dai.google.com/linear/pods/hls/.../metadata",
    "session_update_url": "https://dai.google.com/linear/.../session",
    "polling_frequency": 10
    }
    
  3. In the JSON response, locate the stream session ID and store other data for subsequent steps.

Poll ad metadata

To poll ad metadata, do the following:

  1. Read the metadata_url value from the stream registration response.

  2. Make a GET request to the endpoint. For details, see Method: metadata.

    The following example fetches ad metadata:

    const response = await fetch(metadata_url);
    console.log(await response.json());
    

    If successful, you receive the PodMetadata response for current and upcoming ad breaks:

    {
      "tags":{
        "google_5555555555":{
          "ad":"0000229834_ad1",
          "ad_break_id":"0000229834",
          "type":"firstquartile"
        },
        "google_1234567890123456789":{
          "ad":"0000229834_ad1",
          "ad_break_id":"0000229834",
          "type":"progress"
        },
        ...
      },
      "ads":{
        "0000229834_ad1":{
          "ad_break_id":"0000229834",
          "position":1,
          "duration":15,
          "clickthrough_url":"https://.../",
          ...
        },
              ...
      },
      "ad_breaks":{
        "0000229834":{
          "type":"mid",
          "duration":15,
          "ads":1
        },
        ...
      }
    }
    
  3. Save the tags object for later steps.

  4. Set a timer using the polling_frequency value to regularly request metadata for all successive ad breaks.

Load the stream into your video player

After you have the session ID from the registration response, pass the ID to your manifest manipulator, or construct a manifest URL to load the stream into a video player.

To pass the session ID, see your manifest manipulator documentation. If you develop a manifest manipulator, see Manifest manipulator for livestream.

The following example assembles a manifest URL:

https://<your_manifest_manipulator_url>/manifest.m3u8?DAI_stream_ID=SESSION_ID&network_code=NETWORK_CODE&DAI_custom_asset_key=CUSTOM_ASSET_KEY"

When your player is ready, begin playback.

Listen for ad events

Check your stream's container format for the timed metadata:

  • HLS streams with Transport Stream (TS) containers use timed ID3 tags to carry timed metadata. For details, see About the Common Media Application Format with HTTP Live Streaming (HLS).

  • DASH streams use EventStream elements to specify events in the manifest.

  • DASH streams use InbandEventStream elements when the segments contain Event Message (emsg) boxes for payload data, including ID3 tags. For details, see InbandEventStream.

  • CMAF streams, including DASH and HLS, use emsg boxes containing ID3 tags.

To retrieve ID3 tags from your stream, refer to your video player's guide. For details, see Handle timed metadata guide

To retrieve the ad event ID from ID3 tags, do the following:

  1. Filter the events by scheme_id_uri with urn:google:dai:2018 or https://aomedia.org/emsg/ID3.
  2. Extract the byte array from the message_data field.

    The following example decodes the emsg data into JSON:

    {
      "scheme_id_uri": "https://developer.apple.com/streaming/emsg-id3",
      "presentation_time": 27554,
      "timescale": 1000,
      "message_data": "ID3TXXXgoogle_1234567890123456789",
      ...
    }
    
  3. Filter the ID3 tags with the format TXXXgoogle_{ad_event_ID}:

    TXXXgoogle_1234567890123456789
    

Show ad event data

To find the TagSegment object, do the following:

  1. Retrieve the ad metadata tags object from Poll ad metadata. The tags object is an array of TagSegment objects.

  2. Use the full ad event ID to find a TagSegment object with the type progress.

  3. Use the first 17 characters of the ad event ID to find a TagSegment object of other types.

  4. After you have the TagSegment, use the ad_break_id property as the key to find the AdBreak object in the ad metadata ad_breaks object.

    The following example finds an AdBreak object:

    {
      "type":"mid",
      "duration":15,
      "ads":1
    }
    
  5. Use the TagSegment and AdBreak data to show information about the ad position in the ad break. For example, Ad 1 of 3.

Send media verification pings

For every ad event, except the progress type, send a media verification ping. Google DAI discards progress events, and sending these events frequently might impact your app performance.

To generate the complete media verification URL of an ad event, do the following:

  1. From the stream response, append the full ad event ID to the media_verification_url value.

  2. Make a GET request with the complete URL:

    // media_verification_url: "https://dai.google.com/view/.../event/c14aZDWtQg-ZwQaEGl6bYA/media/"
    const completeUrl = `${media_verification_url}google_5555555555123456789`;
    
    const response = await fetch(completeUrl);
    

    If successful, you receive a code status 202 response. Otherwise, you receive a 404 error code.

You can use the Stream Activity Monitor (SAM) to inspect a historical log of all ad events. For details, see monitor and troubleshoot a livestream