Client video player app for VOD streams

The Google DAI Pod Serving API lets you perform server-side ad insertion powered by Google Ads while maintaining control of your own video stitching.

This guide shows you how to interact with the Pod Serving API and achieve similar functionality with the IMA DAI SDK. For specific questions about supported functionality, contact your Google account manager.

The Pod Serving API supports pod serving streams in either HLS or MPEG-DASH streaming protocols. This guide focuses on HLS streams and highlights the key differences between HLS and MPEG-DASH in specific steps.

To integrate the Pod Serving API into your app for VOD streams, complete the following steps:

Make a stream registration request to Ad Manager

Make a POST request to the stream registration endpoint. You receive in turn a JSON response containing the stream ID to send to your manifest manipulation server and associated Pod Serving API endpoints.

API endpoint

POST: /ondemand/pods/api/v1/network/{network_code}/stream_registration
Host: dai.google.com
Content-Type: application/json

Path parameters

{network_code} Your Google Ad Manager 360 network code

JSON body parameters

targeting_parameters A JSON object containing the ad targeting parameters. Required

Response JSON

media_verification_url The base URL to ping playback tracking events. A complete media verification URL is formed by appending an ad event ID to this base URL.
metadata_url The URL to request ad pod metadata.
stream_id The string used to identify the current stream session.
valid_for The amount of time left until the current stream session expires, in dhms (days, hours, minutes, seconds) format. For example, 2h0m0.000s represents a duration of 2 hours.
valid_until The time at which the current stream session expires, as an ISO 8601 datetime string in yyyy-MM-dd'T'hh:mm:ss.sssssssss[+|-]hh:mm format.

Example request (cURL)

curl -X POST \
     -d '{"targeting_parameters":{"url":"http://example.com"}}' \
     -H 'Content-Type: application/json' \
  https://dai.google.com/ondemand/pods/api/v1/network/21775744923/stream_registration

Example response

{
  "media_verification_url": "https://dai.google.com/.../media/",
  "metadata_url": "https://dai.google.com/.../metadata",
  "stream_id": "6e69425c-0ac5-43ef-b070-c5143ba68541:CHS",
  "valid_for": "8h0m0s",
  "valid_until": "2023-03-24T08:30:26.839717986-07:00"
}

In case of errors, standard HTTP error codes are returned with no JSON response body.

Parse the JSON response and store the relevant values.

Request the stream manifest from the manifest manipulator

Each manifest manipulator has a different request and response formats. Contact your manipulator provider to understand their specific requirements. If you're implementing your own manifest manipulator, read the manifest manipulator guide to understand the requirements for this component.

In general, you need to pass the stream ID that was returned by the registration endpoint above to your manifest manipulator for it to build session-specific manifests. Unless explicitly stated by your manifest manipulator, the response to your manifest request is a video stream containing both content and ads.

Example request (cURL)

curl https://{manifest_manipulator}/video/1331997/stream/6e69425c-0ac5-43ef-b070-c5143ba68541:CHS/vod_manifest.m3u8

Example response (HLS)

#EXTM3U
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs0",LANGUAGE="en",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="abcd1234_     subitles-en.vtt"
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080,CODECS="avc1.42e00a,mp4a.40.2"
abcd1234_video-1080p.m3u8

Play the stream

Load the manifest that you received from the manifest manipulation server into a video player and start the playback.

Request ad pod metadata from Ad Manager

Make a GET request to the metadata_url that you received in step one. This step must occur after you've received the stitched manifest from your manifest manipulator. In return, you receive a JSON object containing the following parameters:

tags A set of key-value pairs containing all ad events that appear in the stream. The keys are either the first 17 characters of an ad event ID that appear in the stream's timed metadata, or in the case of events of type progress, the full ad event ID.

Each value is an object containing the following parameters:

ad The ID of an ad that matches a key in the ads object.
ad_break_id The ID of an ad break that matches a key in the ad_breaks object.
type The type of ad event. Ad event types are:
start Fired at the beginning of the ad.
firstquartile Fired at the end of the first quartile.
midpoint Fired at the midpoint of the ad.
thirdquartile Fired at the end of the third quartile.
complete Fired at the end of the ad.
progress Fired periodically throughout the ad, to notify the app that an ad break is playing.
ads A set of key-value pairs describing all ads that appear in the stream. The keys are ad IDs that match the values found in the tags object listed above. Each value is an object containing the following parameters:
ad_break_id The ID of an ad break that matches a key in the ad_breaks object.
position The position at which this ad appears within the set of ads in the ad break, in floating point seconds.
duration The length of the ad in floating point seconds.
clickthrough_url The URL that should open when a user interacts with this ad, if supported.
ad_breaks A set of key-value pairs describing all ad breaks that appear in the stream. The keys are ad break IDs that match values found in the tags and ads objects listed above. Each value is an object containing the following parameters:
type The type of ad break. Ad break types are pre (pre-roll), mid (mid-roll), and post (post-roll).
duration The length of the ad break in floating point seconds.
ads The number of ads in this ad break.

Store these values to associate with timed metadata events within your video stream.

Example request (cURL)

curl https://dai.google.com/.../metadata

Example response

{
  "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
    },
    ...
  }
}

Listen for ad events

Listen for timed metadata through triggered ad events in the audio/video stream of your video player.

For MPEG-TS streams, the metadata appears as in-band ID3 v2.3 tags. Each metadata tag has the ID TXXX, and the value begins with the string google_ followed by a series of characters. This value is the ad event ID.

The XXX in TXXX is not a placeholder. The string TXXX is the ID3 tag ID reserved for "user defined text".

Example ID3 tag

TXXXgoogle_1234567890123456789

For MP4 streams, these are sent as in-band emsg events that emulate ID3 v2.3 tags. Each relevant emsg box has a scheme_id_uri value of either https://aomedia.org/emsg/ID3 or https://developer.apple.com/streaming/emsg-id3 and a message_data value beginning with ID3TXXXgoogle_. This message_data value, without the ID3TXXX prefix, is the ad event ID.

Example emsg box

The data structure could vary, depending on your media player library.

If the ad event ID is google_1234567890123456789 the response looks like this:

{
  "scheme_id_uri": "https://developer.apple.com/streaming/emsg-id3",
  "presentation_time": 27554,
  "timescale": 1000,
  "message_data": "ID3TXXXgoogle_1234567890123456789",
  ...
}

Some media player libraries automatically present emsg events that emulate ID3 tags as native ID3 tags. In this case, MP4 streams present identical ID3 tags as MPEG_TS.

Update the client video player app's UI

Each ad event ID can be matched to a key in the tags object from step 4. Matching these values is a two-step process:

  1. Check the tags object for a key matching the full ad event ID. If a match is found, retrieve the event type and its associated ad and ad_break objects. These events should have the type progress.

    If a match is not found for the full ad event ID, check the tags object for a key matching the first 17 characters of the ad event ID. Retrieve the event type and the associated ad and ad_break objects. This should retrieve all events with types other than progress.

  2. Use this retrieved information to update your player's UI. For example, when you receive a start or the first progress event, hide your player's seek controls and display an overlay describing the current ad's position in the ad break, for example: "Ad 1 of 3".

Example ad event IDs

google_1234567890123456789 // Progress event ID
google_5555555555123456789 // First Quartile event ID

Example tags object

{
  "google_5555555555":{
    "ad":"0000229834_ad1",
    "ad_break_id":"0000229834",
    "type":"firstquartile"
  },
  "google_1234567890123456789":{
    "ad":"0000229834_ad1",
    "ad_break_id":"0000229834",
    "type":"progress"
  },
  ...
}

Send media verification pings

A media verification ping must be sent to Ad Manager every time an ad event with a type other than progress is received.

To generate the complete media verification URL of an ad event, append the full ad event ID to the media_verification_url value from the stream registration response.

Make a GET request with the complete URL. If the verification request is successful, you receive an HTTP response with status code 202. Otherwise, you get the HTTP error code 404.

Example request (cURL)

curl https://{...}/media/google_5555555555123456789

Example successful response

HTTP/1.1 202 Accepted

Additional resources