From 55c526feae281e7c9b0c97e18359b2c60a82d1e1 Mon Sep 17 00:00:00 2001 From: Maarten Rimaux Date: Thu, 22 Oct 2026 20:45:50 +0200 Subject: [PATCH 1/7] Ads: document ad workflows by use case (live, VOD) and ad source (static, VAST, Google Ad Manager) Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- ads/concepts/breaks.mdx | 5 + ads/concepts/channels.mdx | 16 +- ads/getting-started/index.mdx | 17 +- ads/how-to-guides/ad-tag-parameters.mdx | 59 +++++-- ads/how-to-guides/workflow-integration.md | 2 +- ads/index.mdx | 14 +- ads/integrations/google/pod-serving.mdx | 20 +-- ads/integrations/index.mdx | 2 + ads/player-integration/index.mdx | 2 +- .../optiview-ads-sdk/android.mdx | 4 +- .../optiview-ads-sdk/index.mdx | 60 ++++--- .../optiview-ads-sdk/ios.mdx | 6 +- .../optiview-ads-sdk/react-native.mdx | 6 +- .../optiview-ads-sdk/web.mdx | 5 +- ads/workflows/google-ad-manager.mdx | 149 ++++++++++++++++++ ads/workflows/index.mdx | 60 +++++++ ads/workflows/live.mdx | 66 ++++++++ ads/workflows/static-assets.mdx | 105 ++++++++++++ ads/workflows/vast.mdx | 138 ++++++++++++++++ ads/workflows/vod.mdx | 105 ++++++++++++ sidebarsAds.ts | 11 ++ 21 files changed, 783 insertions(+), 69 deletions(-) create mode 100644 ads/workflows/google-ad-manager.mdx create mode 100644 ads/workflows/index.mdx create mode 100644 ads/workflows/live.mdx create mode 100644 ads/workflows/static-assets.mdx create mode 100644 ads/workflows/vast.mdx create mode 100644 ads/workflows/vod.mdx diff --git a/ads/concepts/breaks.mdx b/ads/concepts/breaks.mdx index 3a2193b62de8..3e9f62797ee0 100644 --- a/ads/concepts/breaks.mdx +++ b/ads/concepts/breaks.mdx @@ -25,6 +25,7 @@ The [timebase of the channel](./channels.mdx#timebase) defines how a break is sc - **`wallclock`** — the break's `start` is a UTC ISO 8601 timestamp (for example `"2026-07-16T12:15:00.000Z"`). Players match it against the wallclock timeline carried by the stream. `start` is optional on wallclock channels: omitting it creates a [cued break](#cued-breaks). - **`pts`** — the break's `start` is a non-negative number: a presentation timestamp on the encoder's timeline. `start` is required on PTS channels. +- **`mediatime`** — the break's `start` is a non-negative number of seconds from the start of the asset (for example `600`). `start` is required on mediatime channels, which are always [VOD](../workflows/vod.mdx) channels. `duration` is always required and is expressed in seconds. It is the **maximum** duration of the break. @@ -396,6 +397,8 @@ A `static` asset is a media resource the player retrieves directly — a video o } ``` +See [Static assets](../workflows/static-assets.mdx) for the supported creative formats and layouts in the OptiView Ads SDK. + #### VAST assets A `vast` asset points to an ad server that responds with a VAST XML document describing how the ad should be played. The `uri` is the VAST tag URL, and the `mimeType` should be `application/xml` or `text/xml`: @@ -409,6 +412,8 @@ A `vast` asset points to an ad server that responds with a VAST XML document des } ``` +A `vast` asset can also carry `assetParameters`, which the player appends to the VAST tag URL as query parameters. See [VAST](../workflows/vast.mdx) for how the OptiView Ads SDK plays VAST tags, and the layouts they support. + #### Vendor assets A `vendor` asset is delivered through an [ad vendor integration](../integrations/index.mdx), such as Google Ad Manager. The vendor decides the ad content; you identify the vendor and pass the vendor-specific parameters: diff --git a/ads/concepts/channels.mdx b/ads/concepts/channels.mdx index bef0e3796a34..44cd08a491cb 100644 --- a/ads/concepts/channels.mdx +++ b/ads/concepts/channels.mdx @@ -5,7 +5,7 @@ sidebar_label: Channels # Channels -A channel represents one live stream in OptiView Ads. It is the place where you decide how ads behave for that stream: how break start times are interpreted, which breaks are announced to players and when, and whether ad markers in the stream are detected automatically. +A channel represents one live stream or one video-on-demand (VOD) asset in OptiView Ads. It is the place where you decide how ads behave for that content: how break start times are interpreted, which breaks are announced to players and when, and whether ad markers in the stream are detected automatically. Everything else in OptiView Ads hangs off a channel. Origins, marker rules, breaks, events, templates, and integrations are all created for — or looked up through — a channel. @@ -30,14 +30,22 @@ Every channel has a customer-facing `id`. We recommend using a UUID as the chann These channel settings determine how break start times are interpreted and how breaks are delivered to players through the [Break Manifest](./break-manifest.mdx). +### Stream type + +The `streamType` determines the use case of the channel: + +- **`live`** (default) — a live stream. Players poll the Break Manifest continuously and receive breaks as they become relevant. See [Live](../workflows/live.mdx). +- **`vod`** — an on-demand asset. The Break Manifest lists all breaks upfront and players fetch it once. VOD channels do not run break detection and have no events. See [VOD](../workflows/vod.mdx). + ### Timebase The `timebase` determines which timeline break start times are expressed on: -- **`wallclock`** — breaks are scheduled with a UTC timestamp that is matched against the wallclock timeline carried by the stream itself. Use this when the stream carries wallclock timing: in HLS this comes from `EXT-X-PROGRAM-DATE-TIME` tags, in DASH from the MPD's `availabilityStartTime` combined with the segment timeline (optionally synchronized through a `UTCTiming` element). -- **`pts`** — breaks are scheduled with a presentation timestamp (PTS) on the encoder's timeline. The player retrieves the PTS value from the media segments to know where it is on that timeline. Use this when your workflow schedules breaks against encoder PTS values rather than wallclock time. +- **`wallclock`** — breaks are scheduled with a UTC timestamp that is matched against the wallclock timeline carried by the stream itself. Use this when the stream carries wallclock timing: in HLS this comes from `EXT-X-PROGRAM-DATE-TIME` tags, in DASH from the MPD's `availabilityStartTime` combined with the segment timeline (optionally synchronized through a `UTCTiming` element). Available for live and VOD channels. +- **`pts`** — breaks are scheduled with a presentation timestamp (PTS) on the encoder's timeline. The player retrieves the PTS value from the media segments to know where it is on that timeline. Use this when your workflow schedules breaks against encoder PTS values rather than wallclock time. Live channels only. +- **`mediatime`** — breaks are scheduled with a position in the asset, in seconds from its start (for example `600` for 10 minutes in). VOD channels only. -Choose the timebase when creating the channel; all breaks on the channel use the same timebase. +Choose the stream type and the timebase when creating the channel; both are fixed afterwards, and all breaks on the channel use the same timebase. ### DVR window diff --git a/ads/getting-started/index.mdx b/ads/getting-started/index.mdx index 422eef8d56f2..0e9c78f1c14f 100644 --- a/ads/getting-started/index.mdx +++ b/ads/getting-started/index.mdx @@ -10,7 +10,7 @@ import RebrandingNotice from '../callouts/_rebranding_notice.md'; -OptiView Ads monetizes your live stream with Server-Guided Ad Insertion (SGAI): you schedule ad breaks on a channel, and the player renders them on top of your content — without touching your media stream. This guide takes you from an empty organization to seeing your first ad break play out on your device. +OptiView Ads monetizes your live stream with Server-Guided Ad Insertion (SGAI): you schedule ad breaks on a channel, and the player renders them on top of your content — without touching your media stream. This guide takes you from an empty organization to seeing your first ad break play out on your device. It uses a live channel; to monetize on-demand assets, the same steps apply to a [VOD channel](/ads/workflows/vod) with breaks at positions in the asset. The examples use the US region (`https://us.ads.optiview.dolby.com` and `https://us.markers.optiview.dolby.com`). For the EU region, replace `us.` with `eu.`. @@ -84,9 +84,11 @@ await sdk.startSession({ Follow the platform guide for [Web](/ads/player-integration/optiview-ads-sdk/web), [Android](/ads/player-integration/optiview-ads-sdk/android), [iOS](/ads/player-integration/optiview-ads-sdk/ios), or [React Native](/ads/player-integration/optiview-ads-sdk/react-native). If you use the OptiView Player, the legacy [OptiView Player integration](/ads/player-integration/optiview-player/) is also available. +This integration plays every [ad workflow](/ads/workflows/): static assets from your CDN, VAST tags from your ad server, and Google Ad Manager — on live and VOD channels. Static assets need nothing more; for VAST or Google Ad Manager on Web, the workflow page lists the Google IMA script to add to your page. + ## 4. Schedule a break -A [break](/ads/concepts/breaks) describes an ad opportunity: when it starts, how long it lasts, and which ad experience plays. The simplest break plays a single full-screen ad from a VAST tag. +A [break](/ads/concepts/breaks) describes an ad opportunity: when it starts, how long it lasts, and which ad experience plays. The simplest break plays a single full-screen video ad from your CDN, as a [static asset](/ads/workflows/static-assets). Dashboard: open the channel → **Breaks → Schedule now**. Or via the API, scheduling a 30-second break a few minutes from now: @@ -102,16 +104,18 @@ curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//bre "format": "single", "assets": [ { - "type": "vast", + "type": "static", "mediaType": "video", - "uri": "https://cdn.example.com/vast.xml" + "uri": "https://cdn.example.com/ads/spot.m3u8" } ] } }' ``` -Replace `` with an ISO 8601 UTC timestamp a few minutes in the future, for example `2026-01-01T12:00:00.000Z`. +Replace `` with an ISO 8601 UTC timestamp a few minutes in the future, for example `2026-01-01T12:00:00.000Z`, and the `uri` with the URL of an ad video on your CDN. + +To let an ad server choose the ad instead, use a [VAST](/ads/workflows/vast) asset or [Google Ad Manager](/ads/workflows/google-ad-manager). Once you schedule breaks regularly, [templates](/ads/concepts/templates) let you preconfigure the break payload so scheduling becomes a one-liner. @@ -121,7 +125,7 @@ Start playback of your stream on your device. Shortly before the scheduled start You can follow along on both sides: -- **In the dashboard or API:** the break's [lifecycle status](/ads/concepts/breaks#break-lifecycle) moves from `PREPARING` to `READY`, and to `SIGNALED` once it is announced to players. +- **In the dashboard or API:** the break's [lifecycle status](/ads/concepts/breaks#break-lifecycle) is `READY` (a Google pod break passes through `PREPARING` first), and moves to `SIGNALED` once it is announced to players. - **In the player:** the ad plays at the scheduled time and your content resumes afterwards. If the break does not play, verify that the Break Manifest URL from step 2 returns the break, and that your stream carries the time metadata required by the channel's timebase. @@ -131,6 +135,7 @@ If the break does not play, verify that the Break Manifest URL from step 2 retur | Resource | Description | | ------------------------------------------------------------- | ----------------------------------------------------------------- | | [Player integration](/ads/player-integration/) | The full integration guides for the SDK and the OptiView Player. | +| [Ad workflows](/ads/workflows/) | Static assets, VAST, and Google Ad Manager with the SDK. | | [Breaks](/ads/concepts/breaks) | Everything a break can do: layouts, variants, controls, punching. | | [Origins and Break Detection](/ads/concepts/marker-detection) | Turn the ad markers in your stream into breaks automatically. | | [Google Ad Manager](/ads/integrations/google/) | Let Google Ad Manager decision the ads that fill your breaks. | diff --git a/ads/how-to-guides/ad-tag-parameters.mdx b/ads/how-to-guides/ad-tag-parameters.mdx index 3da2b4206c5c..54f5f4119b3a 100644 --- a/ads/how-to-guides/ad-tag-parameters.mdx +++ b/ads/how-to-guides/ad-tag-parameters.mdx @@ -4,13 +4,30 @@ sidebar_position: 3 # Ad targeting parameters -When an ad server such as Google Ad Manager decisions a break, you can pass key-value parameters with the request to personalize the ads — for example the content genre, the placement type, or custom targeting values. In OptiView Ads, these parameters are called **`assetParameters`**. For Google, they map directly to the [ad tag parameters](https://support.google.com/admanager/answer/10678356) (`adTagParameters`) on the ad request. +When an ad server decides which ad fills a break, you can pass key-value parameters with the ad request to personalize the ads — for example the content genre, the placement type, or custom targeting values. In OptiView Ads, these parameters are called **`assetParameters`**. How they reach the ad server depends on the [ad workflow](../workflows/index.mdx): -You can set `assetParameters` in two places: on the break in the **backend**, and in the **OptiView Ads SDK** on the client. Client-side values overwrite the backend values when the same key is set in both. +- **[VAST](../workflows/vast.mdx):** the SDK appends them to the VAST tag URL as URL-encoded query parameters. +- **[Google Ad Manager](../workflows/google-ad-manager.mdx):** they are sent to Google as [ad tag parameters](https://support.google.com/admanager/answer/10678356) (`adTagParameters`). +- **[Static assets](../workflows/static-assets.mdx)** involve no ad request, so they do not use `assetParameters`. + +You can set `assetParameters` in two places: on the break in the **backend**, and in the **OptiView Ads SDK** on the client. ## Asset parameters in the backend -When you [schedule a break](../concepts/breaks.mdx#scheduling) with a vendor asset, you can add an `assetParameters` map to the asset: +When you [schedule a break](../concepts/breaks.mdx#scheduling) with a VAST or vendor asset, you can add an `assetParameters` map to the asset. For a VAST asset: + +```json +{ + "type": "vast", + "mediaType": "video", + "uri": "https://adserver.example.com/vast?slot=midroll", + "assetParameters": { + "content_genre": "sports" + } +} +``` + +For a Google Pod Serving vendor asset: ```json { @@ -26,22 +43,24 @@ When you [schedule a break](../concepts/breaks.mdx#scheduling) with a vendor ass } ``` -OptiView Ads forwards these parameters to the ad server when the break is announced, and also delivers them to the player through the [Break Manifest](../concepts/break-manifest.mdx) so they are included on the ad request. See [Google Pod Serving](../integrations/google/pod-serving.mdx#required-google-parameters) for the parameters Google requires. +OptiView Ads delivers these parameters to the player through the [Break Manifest](../concepts/break-manifest.mdx), so they are included on the ad request. For Google, they are also forwarded to Google when the break is announced; see [Google Pod Serving](../integrations/google/pod-serving.mdx#required-google-parameters) for the parameters Google requires. -## Overwriting from the OptiView Ads SDK +## Asset parameters in the OptiView Ads SDK -The OptiView Ads SDK can supply its own `assetParameters` and overwrite the backend values. There are two client-side layers: +The OptiView Ads SDK can add its own `assetParameters`. There are two client-side layers: - **Session parameters** — passed to `startSession()`, they apply to every break in the session. - **Live updates** — passed to `updateAssetParameters()` during an active session, for values that change while the viewer is watching. -The three layers are merged **per key**, from lowest to highest precedence: +## How the layers are merged -1. The break's `assetParameters` from the backend. -2. The session's `assetParameters` from `startSession()`. -3. The latest `updateAssetParameters()` call. +The layers are merged **per key**, from lowest to highest precedence: -Overwriting one key never discards the others, and live updates apply to **future** breaks only: a break whose ad request has already been sent cannot be retargeted. +1. The session's `assetParameters` from `startSession()`. +2. The latest `updateAssetParameters()` call. +3. The break's `assetParameters` from the backend. + +A value set on the break wins over the same key set in the SDK, so set each key in one place only. Overwriting one key never discards the others, and live updates apply to **future** breaks only: a break whose ad request has already been sent cannot be retargeted. ## Backend or client? @@ -50,6 +69,20 @@ As a rule of thumb: - **Set through the backend** the values that describe the break or the content and are the same for every viewer — such as `description_url`, the placement declaration, and campaign or content targeting that is known when the break is scheduled. - **Set through the SDK** the values that depend on the viewer, the device, or the moment of playback — such as device identifiers, consent state, autoplay/mute state (`vpa`, `vpmute`), or audience context that changes during the session. +## Macros + +A parameter value can contain macros: `$NAME$` tokens that the SDK replaces when it builds the ad request. Macros let a value on the break carry information that is only known on the device. The SDK provides these built-in macros: + +| Macro | Value | +| ----------------------------------- | ---------------------------------------------------------------------------- | +| `$OPTIVIEW_PLAYER_WIDTH$` | Width of the ad container, in logical pixels. | +| `$OPTIVIEW_PLAYER_HEIGHT$` | Height of the ad container, in logical pixels. | +| `$OPTIVIEW_BREAK_DURATION_SECONDS$` | Duration of the ad, in seconds: the asset's `duration`, else the break's. | +| `$OPTIVIEW_BREAK_DURATION_MS$` | The same duration, in whole milliseconds. | +| `$OPTIVIEW_USER_AGENT$` | The user agent of the device. Not available on iOS; register your own value. | + +For example, `"size": "$OPTIVIEW_PLAYER_WIDTH$x$OPTIVIEW_PLAYER_HEIGHT$"` is sent as `size=1920x1080`. You can register your own macros, or override a built-in one, with `assetParameterMacros` in the session configuration. Tokens the SDK does not know, such as `$PUBLISHER_ID$`, are sent unchanged, so your ad server can still expand its own macros. See `SessionConfig` in the API reference of your platform for the details. + ## Platform examples The examples below start a session with session-level `assetParameters` and update them mid-session. See the [OptiView Ads SDK](../player-integration/optiview-ads-sdk/index.mdx) documentation for the full integration. @@ -120,6 +153,8 @@ ads.updateAssetParameters({ cust_params: 'sport=basketball' }); | Resource | Description | | -------------------------------------------------------------------- | ----------------------------------------------- | +| [VAST](../workflows/vast.mdx) | Playing VAST tags with the SDK. | +| [Google Ad Manager](../workflows/google-ad-manager.mdx) | Playing Google pods with the SDK. | | [Google Pod Serving](../integrations/google/pod-serving.mdx) | Required Google parameters and pod decisioning. | -| [Breaks](../concepts/breaks.mdx) | Scheduling breaks with vendor assets. | +| [Breaks](../concepts/breaks.mdx) | Scheduling breaks with VAST and vendor assets. | | [OptiView Ads SDK](../player-integration/optiview-ads-sdk/index.mdx) | Integrating the SDK with your player. | diff --git a/ads/how-to-guides/workflow-integration.md b/ads/how-to-guides/workflow-integration.md index 2a4ce2ec6717..91d36e2d56fe 100644 --- a/ads/how-to-guides/workflow-integration.md +++ b/ads/how-to-guides/workflow-integration.md @@ -41,7 +41,7 @@ Ready-made adapters are available for the OptiView Player (THEOplayer), HLS.js, 2. OptiView Ads reads the stream, detects the markers, and publishes the breaks in the channel's Break Manifest. 3. The OptiView Ads SDK polls the Break Manifest and renders the breaks in your player. -That is the whole integration for server-guided ad insertion (SGAI). For platforms where a client-side SDK is not an option — such as Roku or older connected TV devices — OptiView Ads also supports server-side ad insertion (SSAI) through [Google DAI](../integrations/google/dai.mdx). +That is the whole integration for server-guided ad insertion (SGAI). For platforms where a client-side SDK is not an option — such as Roku or older connected TV devices — OptiView Ads also supports server-side ad insertion (SSAI) through [Google DAI](../integrations/google/dai.mdx). See [Ad workflows](../workflows/index.mdx) for how SGAI and SSAI combine on one channel, and how live and VOD differ. For an end-to-end walkthrough — from creating a channel to seeing a break play out — follow the [Getting started](../getting-started/index.mdx) guide. diff --git a/ads/index.mdx b/ads/index.mdx index 4172b8b874be..28224fab6c80 100644 --- a/ads/index.mdx +++ b/ads/index.mdx @@ -9,7 +9,7 @@ import SidebarDocCardList from '@site/src/components/SidebarDocCardList'; import ThemedImage from '@theme/ThemedImage'; import useBaseUrl from '@docusaurus/useBaseUrl'; -OptiView Ads is an ad insertion service for LIVE content (VOD support coming soon), utilizing Server-Guided Ad Insertion (SGAI) as well as Server-Side Ad Insertion (SSAI). On these pages, you'll learn how to get started with OptiView Ads, model your live streams, schedule ad breaks, and configure the OptiView Ads SDK — the recommended integration approach. +OptiView Ads is a hybrid ad insertion platform for **live** streams and **video-on-demand (VOD)** assets: the same channel and the same breaks can be delivered with Server-Guided Ad Insertion (SGAI) or Server-Side Ad Insertion (SSAI). Ads come from creatives on your own CDN, from VAST tags on your ad server, or from Google Ad Manager. On these pages, you'll learn how to get started with OptiView Ads, choose the [ad workflow](./workflows/index.mdx) that fits your content, schedule ad breaks, and configure the OptiView Ads SDK — the recommended integration approach. By logically redistributing responsibilities in the advertisement workflow, OptiView Ads: @@ -19,7 +19,15 @@ By logically redistributing responsibilities in the advertisement workflow, Opti - Maximizes workflow efficiency by reducing prefetching and over-allocation of inventory. - Enables more relevant ads through a high degree of personalization. -OptiView Ads models each live stream as a **channel**. A channel monitors one or more **origins**, detects or schedules **breaks**, and can use reusable **templates** for consistent ad experiences. It generates a **Break Manifest** for the OptiView Ads SDK to poll and render. +OptiView Ads models each live stream or VOD asset as a **channel**. A channel schedules **breaks** — on a live stream it can also detect them from the ad markers on its **origins** — and can use reusable **templates** for consistent ad experiences. It generates a **Break Manifest** for the OptiView Ads SDK to read and render. + +| Workflow | What it is for | +| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------- | +| [Live](./workflows/live.mdx) | Linear channels and live events: breaks on the live timeline, scheduled, punched, or detected. | +| [VOD](./workflows/vod.mdx) | On-demand assets: pre-roll, mid-rolls at positions in the asset, post-roll, and pause ads. | +| [Static assets](./workflows/static-assets.mdx) | Play creatives from your own CDN, without an ad server. | +| [VAST](./workflows/vast.mdx) | Let your ad server, or a partner's, decide the ads through VAST tags. | +| [Google Ad Manager](./workflows/google-ad-manager.mdx) | Let Google Ad Manager 360 fill your breaks, server-guided (Pod Serving) or server-side (DAI). | -Besides mid-roll breaks on the live timeline, breaks can also be [triggered by player events](./concepts/breaks.mdx#event-based-triggers): **pre-roll** (when playback starts), **pause** (while the viewer is paused), and **post-roll** (when playback ends) — each with an optional delay. +Besides mid-roll breaks on the live timeline or at positions in a VOD asset, breaks can also be [triggered by player events](./concepts/breaks.mdx#event-based-triggers): **pre-roll** (when playback starts), **pause** (while the viewer is paused), and **post-roll** (when playback ends) — each with an optional delay. diff --git a/ads/integrations/google/pod-serving.mdx b/ads/integrations/google/pod-serving.mdx index 3d0d39accd80..581569e85270 100644 --- a/ads/integrations/google/pod-serving.mdx +++ b/ads/integrations/google/pod-serving.mdx @@ -77,7 +77,7 @@ Google performs the decisioning, so no asset URI is needed: once Google has deci The optional `assetParameters` map contains the [Google ad tag parameters](https://support.google.com/admanager/answer/10678356) (`adTagParameters`) for the break. OptiView Ads forwards them to Google when the break is announced, and delivers them to the player through the Break Manifest so they are included on the pod request. -Players can extend these parameters: the OptiView player SDKs accept `adTagParameters` on the ad description (`TheoAdDescription`). When the same parameter is set both on the break and on the player, the player-side value wins. See [Ad tag parameters](../../how-to-guides/ad-tag-parameters.mdx) for the player-side API on each platform. +Players can extend these parameters. The OptiView Ads SDK accepts `assetParameters` in its session configuration; when the same parameter is set both on the break and in the SDK, the break's value wins. See [Ad targeting parameters](../../how-to-guides/ad-tag-parameters.mdx) for the SDK API on each platform. The legacy OptiView Player SDKs accept `adTagParameters` on the ad description (`TheoAdDescription`); there, the player-side value wins. As a rule of thumb: @@ -147,12 +147,12 @@ Additionally, creating a pod break that starts too close to the live point is re ## Related resources -| Resource | Relationship | -| -------------------------------------------------------------- | ------------------------------------------------------------------------ | -| [Google Ad Manager](./index.mdx) | The prerequisites shared by both Google delivery modes. | -| [Google DAI](./dai.mdx) | Server-side (SSAI) delivery for platforms without server-guided support. | -| [Channels](../../concepts/channels.mdx) | Hold the custom asset key used for Google Pod Serving. | -| [Breaks](../../concepts/breaks.mdx) | Carry the vendor asset that Google uses to make ad decisions. | -| [Break Manifest](../../concepts/break-manifest.mdx) | The manifest that announces the channel's breaks to players. | -| [Ad tag parameters](../../how-to-guides/ad-tag-parameters.mdx) | Passing ad tag parameters from the player. | -| [Player integration](../../player-integration/index.mdx) | Set up a player with pod serving. | +| Resource | Relationship | +| ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | +| [Google Ad Manager](./index.mdx) | The prerequisites shared by both Google delivery modes. | +| [Google DAI](./dai.mdx) | Server-side (SSAI) delivery for platforms without server-guided support. | +| [Channels](../../concepts/channels.mdx) | Hold the custom asset key used for Google Pod Serving. | +| [Breaks](../../concepts/breaks.mdx) | Carry the vendor asset that Google uses to make ad decisions. | +| [Break Manifest](../../concepts/break-manifest.mdx) | The manifest that announces the channel's breaks to players. | +| [Ad tag parameters](../../how-to-guides/ad-tag-parameters.mdx) | Passing ad tag parameters from the player. | +| [Google Pod Serving with the SDK](../../workflows/google-ad-manager.mdx) | Set up the OptiView Ads SDK in your app for pod serving. | diff --git a/ads/integrations/index.mdx b/ads/integrations/index.mdx index 13f2eb75c1a6..420aceb6d452 100644 --- a/ads/integrations/index.mdx +++ b/ads/integrations/index.mdx @@ -7,6 +7,8 @@ sidebar_label: Integrations An integration connects OptiView Ads to an ad decisioning or "pod" serving vendor. Vendors are supported by providing [assets of type Vendor](../concepts/breaks.mdx#vendor-assets) in a break variant: the vendor makes the ad decisions, and OptiView Ads delivers the result to players. [Google Ad Manager 360](./google/index.mdx) is the first supported integration. +You do not need an integration to play [static assets](../workflows/static-assets.mdx) from your CDN or [VAST](../workflows/vast.mdx) tags from your own ad server: those breaks work on any channel. + ## Supported vendors | Vendor | Enum value | Delivery | diff --git a/ads/player-integration/index.mdx b/ads/player-integration/index.mdx index f17182f6b40b..5c4fa38e104b 100644 --- a/ads/player-integration/index.mdx +++ b/ads/player-integration/index.mdx @@ -9,7 +9,7 @@ To play the ad breaks you schedule with OptiView Ads, your application needs a p ## OptiView Ads SDK (recommended) -The [OptiView Ads SDK](./optiview-ads-sdk/index.mdx) lets you **bring your own player**. It handles the Break Manifest logic and ad tracking/analytics for you, while your application keeps full control over content playback. It is available for Web, Android, iOS, and React Native, with ready-made adapters for popular players. +The [OptiView Ads SDK](./optiview-ads-sdk/index.mdx) lets you **bring your own player**. It handles the Break Manifest logic and ad tracking/analytics for you, while your application keeps full control over content playback. It is available for Web, Android, iOS, and React Native, with ready-made adapters for popular players, and plays every [ad workflow](./optiview-ads-sdk/index.mdx#ad-workflows): static assets, VAST tags, and Google Ad Manager. This is the recommended path for any new integration. diff --git a/ads/player-integration/optiview-ads-sdk/android.mdx b/ads/player-integration/optiview-ads-sdk/android.mdx index 28c97d7d87ff..3e9e1ab3647d 100644 --- a/ads/player-integration/optiview-ads-sdk/android.mdx +++ b/ads/player-integration/optiview-ads-sdk/android.mdx @@ -10,7 +10,7 @@ On Android and Android TV, the OptiView Ads SDK is a native Kotlin library that ## Prerequisites 1. Retrieve the channel's Break Manifest URL. See [Retrieving the required values](./index.mdx#retrieving-the-required-values). -2. For [Google Pod Serving](../../integrations/google/pod-serving.mdx), have your Google Ad Manager `networkCode` and the channel's `customAssetKey` at hand. +2. Check which [ad workflows](./index.mdx#ad-workflows) your breaks use. On Android, static assets, VAST, and Google Ad Manager all work with the installation below; nothing extra is needed. 3. Install the SDK together with the adapter for your player (see [Installation](#installation) and the player sections below). ## Installation @@ -27,7 +27,7 @@ dependencyResolutionManagement { } ``` -Then add the runtime to your app module. It brings in the core and SDK layers, Media3 and the Google IMA SDK transitively; replace `` with the SDK release you want to use: +Then add the runtime to your app module. It brings in the core and SDK layers, Media3, and the Google IMA SDK (used to play [VAST](../../workflows/vast.mdx) and [Google Ad Manager](../../workflows/google-ad-manager.mdx) breaks) transitively; replace `` with the SDK release you want to use: ```kotlin dependencies { diff --git a/ads/player-integration/optiview-ads-sdk/index.mdx b/ads/player-integration/optiview-ads-sdk/index.mdx index 75286c76d360..babdbfb06f85 100644 --- a/ads/player-integration/optiview-ads-sdk/index.mdx +++ b/ads/player-integration/optiview-ads-sdk/index.mdx @@ -7,7 +7,7 @@ sidebar_label: OptiView Ads SDK The OptiView Ads SDK is the recommended way to integrate OptiView Ads into your application. It is **player-agnostic**: you bring your own player, and the SDK takes care of the OptiView Ads specifics: -- **Break Manifest logic:** the SDK polls the channel's [Break Manifest](../../concepts/break-manifest.mdx) and schedules the announced breaks against your player's timeline. You do not implement any polling or scheduling yourself. +- **Break Manifest logic:** the SDK reads the channel's [Break Manifest](../../concepts/break-manifest.mdx) — polling it on a live stream, fetching it once for a VOD asset — and schedules the announced breaks against your player's timeline. You do not implement any polling or scheduling yourself. - **Ad playback:** the SDK renders the scheduled ads, including the different [break layouts](../../concepts/breaks.mdx#layouts), on top of your content player. - **Ad tracking and analytics:** the SDK reports the ad impressions and tracking events for the ads it plays. @@ -15,7 +15,19 @@ The SDK is available for [Web](./web.mdx), [Android](./android.mdx), [iOS](./ios ## How the SDK works with your player -The SDK never talks to your player directly. All player interaction goes through a small **player adapter** interface, which exposes the playback state the SDK needs — most importantly the stream's timing information (such as the `EXT-X-PROGRAM-DATE-TIME` position on a live HLS stream) that breaks are scheduled against. The SDK ships ready-made adapters for popular players on each platform, and you can implement the adapter interface yourself for any other player. +The SDK never talks to your player directly. All player interaction goes through a small **player adapter** interface, which exposes the playback state the SDK needs — most importantly the stream's timing information that breaks are scheduled against: the `EXT-X-PROGRAM-DATE-TIME` position on a live HLS stream, or the playback position in a VOD asset. The SDK ships ready-made adapters for popular players on each platform, and you can implement the adapter interface yourself for any other player. + +## Ad workflows + +The SDK plays whatever the breaks on your channel carry, for [live](../../workflows/live.mdx) and [VOD](../../workflows/vod.mdx) channels alike, and picks the [delivery mode](../../workflows/index.mdx#hybrid-ad-insertion-sgai-and-ssai) — server-guided or server-side — that the channel sets for the device. Each [asset](../../concepts/breaks.mdx#asset-model) in a break uses one of three ad sources, and one channel can mix them: + +| Ad source | What the break carries | What your app needs on top of the platform integration | +| ---------------------------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- | +| [Static assets](../../workflows/static-assets.mdx) | Direct URLs to video or image creatives, hosted on your CDN. | Nothing. | +| [VAST](../../workflows/vast.mdx) | A VAST tag URL from your ad server. | On Web, Google's client-side IMA SDK (`ima3.js`) on the page. Nothing on Android, iOS, React Native. | +| [Google Ad Manager](../../workflows/google-ad-manager.mdx) | An ad pod decisioned by Google Ad Manager. | On Web, Google's IMA DAI SDK (`ima3_dai.js`) on the page. Nothing on Android, iOS, React Native. | + +The platform guides cover the integration that every workflow shares: installing the SDK, wrapping your player, and starting a session. The [Ad workflows](../../workflows/index.mdx) section describes how to set up breaks for each ad source on live and VOD, which layouts it supports, and how to troubleshoot it. ## Configuration @@ -24,32 +36,36 @@ Configuration is split into two levels: - **SDK configuration** is provided once, when you create the SDK instance. It describes your player and how ads should be presented. - **Session configuration** is provided per channel, when you start a monetization session. It identifies the channel to monetize. +Neither level holds ad server URLs or accounts. What to play, and where to fetch it from, comes from the channel's Break Manifest — including the delivery mode and the settings for [Google Ad Manager](../../workflows/google-ad-manager.mdx). + ### SDK configuration -| Property | Description | -| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -| `player` | The adapter that wraps your content player. **Required.** | -| `container` | The element or view in which the SDK renders ads, stacked above your content player. **Required.** | -| `mode` | The ad insertion model: `sgai` (server-guided, the default) or `ssai` (server-side, for streams where the ads are stitched into the media stream). | -| `gam` | Google Ad Manager configuration for [Google Pod Serving](../../integrations/google/pod-serving.mdx): contains your `networkCode`. | -| `debug` | Enables verbose logging during development. | +| Property | Description | +| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `player` | The adapter that wraps your content player. **Required.** | +| `container` | The element or view in which the SDK renders ads, stacked above your content player. **Required.** | +| `mode` | Optional. The ad insertion model: `sgai` (server-guided) or `ssai` (server-side, for streams where the ads are stitched into the media stream). By default the SDK uses the mode the channel's delivery rules set for the device, and `sgai` when there are none; set it only to override the channel. | +| `gam` | Optional. Google Ad Manager starts automatically when the Break Manifest carries a Google configuration; set `enabled` to `false` to keep Google out of a session. See [Google Ad Manager](../../workflows/google-ad-manager.mdx#turn-google-off-for-a-session). | +| `debug` | Enables verbose logging during development. | The SDK also exposes optional presentation settings — such as ad preloading, break chaining, and tune-in behavior — with sensible defaults. The platform pages describe the platform-specific options. ### Session configuration -| Property | Description | -| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `manifestUrl` | The channel's Break Manifest URL. **Required.** See [Retrieving the required values](#retrieving-the-required-values). | -| `customAssetKey` | The Google Pod Serving custom asset key of the channel. Required to play Google Ad Manager breaks. See [Google Pod Serving](../../integrations/google/pod-serving.mdx). | -| `assetParameters` | Session-level ad parameters, merged with the break's `assetParameters` and forwarded to Google as `adTagParameters`. Use these for player-side values such as device identifiers. See [Ad tag parameters](../../integrations/google/pod-serving.mdx#ad-tag-parameters). | +| Property | Description | +| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `manifestUrl` | The channel's Break Manifest URL. **Required.** See [Retrieving the required values](#retrieving-the-required-values). | +| `assetParameters` | Session-level ad targeting parameters for VAST and Google Ad Manager breaks: appended to VAST tag URLs, or sent to Google as `adTagParameters`. Static assets do not use them. See [Ad targeting parameters](../../how-to-guides/ad-tag-parameters.mdx). | ## Retrieving the required values +The Break Manifest URL is the only value your app needs: + - **Break Manifest URL (`manifestUrl`):** every channel exposes its Break Manifest on a public endpoint. The URL follows the pattern `https://us.markers.optiview.dolby.com/manifest/v1/{orgId}/channels/{channelId}` (replace `us.` with `eu.` for the EU region), using your organization ID and the channel's ID. See the [Break Manifest endpoint](../../concepts/break-manifest.mdx#endpoint) for details. -- **Google `networkCode` and `customAssetKey`:** these come from your Google Ad Manager setup. See the [Google Ad Manager prerequisites](../../integrations/google/index.mdx) and [Google Pod Serving](../../integrations/google/pod-serving.mdx). -## Choose a platform +You do not configure ad server values in the app. VAST tag URLs are set on the breaks, and for Google Ad Manager the network code and the Google asset keys are configured on the channel and delivered to the SDK through the Break Manifest. + +## Next steps import DocCardList from '@theme/DocCardList'; @@ -57,9 +73,9 @@ import DocCardList from '@theme/DocCardList'; ## Related resources -| Resource | Description | -| --------------------------------------------------------------- | ------------------------------------------------------------- | -| [Break Manifest](../../concepts/break-manifest.mdx) | The contract between the OptiView Ads backend and the player. | -| [Channels](../../concepts/channels.mdx) | The channel whose Break Manifest the SDK polls. | -| [Breaks](../../concepts/breaks.mdx) | The breaks the SDK schedules and plays. | -| [Google Pod Serving](../../integrations/google/pod-serving.mdx) | Google Ad Manager configuration for pod-served breaks. | +| Resource | Description | +| -------------------------------------------------------------------- | ------------------------------------------------------------- | +| [Break Manifest](../../concepts/break-manifest.mdx) | The contract between the OptiView Ads backend and the player. | +| [Channels](../../concepts/channels.mdx) | The channel whose Break Manifest the SDK polls. | +| [Breaks](../../concepts/breaks.mdx) | The breaks the SDK schedules and plays. | +| [Ad targeting parameters](../../how-to-guides/ad-tag-parameters.mdx) | Passing targeting parameters to VAST tags and Google. | diff --git a/ads/player-integration/optiview-ads-sdk/ios.mdx b/ads/player-integration/optiview-ads-sdk/ios.mdx index 6cbdcd2f4a44..4b8549d52cf4 100644 --- a/ads/player-integration/optiview-ads-sdk/ios.mdx +++ b/ads/player-integration/optiview-ads-sdk/ios.mdx @@ -10,7 +10,7 @@ On iOS and tvOS, the OptiView Ads SDK is a native Swift library that works with ## Prerequisites 1. Retrieve the channel's Break Manifest URL. See [Retrieving the required values](./index.mdx#retrieving-the-required-values). -2. For [Google Pod Serving](../../integrations/google/pod-serving.mdx), have your Google Ad Manager `networkCode` and the channel's `customAssetKey` at hand. +2. Check which [ad workflows](./index.mdx#ad-workflows) your breaks use. On iOS and tvOS, static assets, VAST, and Google Ad Manager all work with the installation below; nothing extra is needed. 3. Install the SDK together with the adapter for your player (see [Installation](#installation) and the player sections below). ## Installation @@ -30,11 +30,11 @@ target 'MyApp' do end ``` -The runtime pod also brings in the Google IMA SDK. +The runtime pod also brings in the Google IMA SDK, which the SDK uses to play [VAST](../../workflows/vast.mdx) and [Google Ad Manager](../../workflows/google-ad-manager.mdx) breaks. ### Swift Package Manager -Add the package from [https://github.com/Dolby-OptiView/optiview-ads-sdk-spm](https://github.com/Dolby-OptiView/optiview-ads-sdk-spm) and link the `OptiViewAdsRuntime` product. Because the frameworks are binary targets, also add the Google IMA package for each platform you build for: +Add the package from [https://github.com/Dolby-OptiView/optiview-ads-sdk-spm](https://github.com/Dolby-OptiView/optiview-ads-sdk-spm) and link the `OptiViewAdsRuntime` product. Because the frameworks are binary targets, also add the Google IMA package for each platform you build for. The runtime always links against Google IMA, so the package is required even if your breaks only use static assets: ```swift dependencies: [ diff --git a/ads/player-integration/optiview-ads-sdk/react-native.mdx b/ads/player-integration/optiview-ads-sdk/react-native.mdx index c2cb9d5ea433..e269d8bd7c97 100644 --- a/ads/player-integration/optiview-ads-sdk/react-native.mdx +++ b/ads/player-integration/optiview-ads-sdk/react-native.mdx @@ -10,7 +10,7 @@ On React Native, the OptiView Ads SDK bridges the native Android and iOS SDKs be ## Prerequisites 1. Retrieve the channel's Break Manifest URL. See [Retrieving the required values](./index.mdx#retrieving-the-required-values). -2. For [Google Pod Serving](../../integrations/google/pod-serving.mdx), have your Google Ad Manager `networkCode` and the channel's `customAssetKey` at hand. +2. Check which [ad workflows](./index.mdx#ad-workflows) your breaks use. On React Native, static assets, VAST, and Google Ad Manager all work with the installation below; nothing extra is needed. 3. Install the SDK and make its native dependencies resolvable for your platforms (see [Installation](#installation)). ## Installation @@ -57,7 +57,7 @@ import { createOptiViewAds } from '@dolby-optiview/ads-sdk-react-native'; const onPlayerReady = async (player) => { player.source = { sources: [{ src: CONTENT_URL, type: 'application/x-mpegurl' }] }; - const ads = createOptiViewAds(player, { gam: { networkCode: 'NETWORK-CODE' } }); + const ads = createOptiViewAds(player, {}); await ads.startSession({ manifestUrl: 'https://us.markers.optiview.dolby.com/manifest/v1/ORG-ID/channels/CHANNEL-ID', }); @@ -92,7 +92,7 @@ const { player, onVideoEvent } = useReactVideoHandle(); useEffect(() => { if (!player) return; - const ads = createOptiViewAds(player, { gam: { networkCode: 'NETWORK-CODE' } }); + const ads = createOptiViewAds(player, {}); void ads.startSession({ manifestUrl: MANIFEST_URL }); return () => void ads.destroy(); }, [player]); diff --git a/ads/player-integration/optiview-ads-sdk/web.mdx b/ads/player-integration/optiview-ads-sdk/web.mdx index ed81358afe84..cdf7ae22fca3 100644 --- a/ads/player-integration/optiview-ads-sdk/web.mdx +++ b/ads/player-integration/optiview-ads-sdk/web.mdx @@ -10,7 +10,7 @@ On Web, the OptiView Ads SDK works with any HLS-capable player through a player ## Prerequisites 1. Retrieve the channel's Break Manifest URL. See [Retrieving the required values](./index.mdx#retrieving-the-required-values). -2. For [Google Pod Serving](../../integrations/google/pod-serving.mdx), have your Google Ad Manager `networkCode` and the channel's `customAssetKey` at hand. +2. Check which [ad workflows](./index.mdx#ad-workflows) your breaks use. Static assets need nothing extra; [VAST](../../workflows/vast.mdx) and [Google Ad Manager](../../workflows/google-ad-manager.mdx) each need a Google IMA script on the page. 3. Install the SDK together with the adapter for your player (see the player sections below). ## Integration @@ -24,7 +24,6 @@ import { THEOplayerAdapter } from '@dolby-optiview/ads-sdk-adapter-theoplayer'; const sdk = new OptiViewAds({ player: new THEOplayerAdapter(player, container), container: document.getElementById('container'), - gam: { networkCode: 'NETWORK-CODE' }, }); await sdk.startSession({ @@ -34,6 +33,8 @@ await sdk.startSession({ From this point the SDK polls the [Break Manifest](../../concepts/break-manifest.mdx), schedules the breaks against your player's timeline, plays the ads, and reports the impressions. To verify the integration, schedule a break through the API or dashboard and confirm that it plays out. +This integration is the same for every ad workflow. If your breaks use VAST or Google Ad Manager, also load the Google IMA script that the [VAST](../../workflows/vast.mdx#what-your-app-needs) or [Google Ad Manager](../../workflows/google-ad-manager.mdx#what-your-app-needs) page lists. + All configuration options, session settings, and ad events are documented in the [Web API reference](pathname:///ads/v2/api-reference/web/), starting from the [`OptiViewAds`](pathname:///ads/v2/api-reference/web/classes/OptiViewAds.html) class. ## Supported players diff --git a/ads/workflows/google-ad-manager.mdx b/ads/workflows/google-ad-manager.mdx new file mode 100644 index 000000000000..5cec563416ae --- /dev/null +++ b/ads/workflows/google-ad-manager.mdx @@ -0,0 +1,149 @@ +--- +sidebar_position: 5 +sidebar_label: Google Ad Manager +description: Let Google Ad Manager 360 fill your breaks, server-guided or server-side, on live and VOD. +--- + +# Google Ad Manager + +With Google Ad Manager 360, Google decides which ads fill each break. OptiView Ads announces the breaks to Google, Google assembles the ads into a pod, and the pod plays when the break starts. Use this workflow when you sell your inventory through Google Ad Manager 360, and to reach platforms that need server-side ad insertion. + +Google Ad Manager is the ad source that supports both delivery modes of the [hybrid platform](./index.mdx#hybrid-ad-insertion-sgai-and-ssai): + +| | Server-guided (SGAI) | Server-side (SSAI) | +| ---- | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| Live | [Google Pod Serving](../integrations/google/pod-serving.mdx): the SDK inserts Google's ad pods into your stream. | [Google DAI](../integrations/google/dai.mdx): Google stitches the ads into the stream for the player. | +| VOD | Google pod serving for on-demand assets: the SDK inserts Google's ad pods at the break positions of the asset. | Google DAI for on-demand assets: Google stitches the ads into the asset for the player. | + +Prefer SGAI on every platform that runs the OptiView Ads SDK: the media stream stays untouched, and the advanced [layouts](../concepts/breaks.mdx#layouts) such as double box and L-shape are available. Use SSAI for platforms where a client-side SDK is not an option, such as Roku and older connected TV devices. One channel can serve both, [per device](./index.mdx#hybrid-ad-insertion-sgai-and-ssai). + +## Before you start + +- The [Google Ad Manager prerequisites](../integrations/google/index.mdx) — network code and service account — are in place for your organization. +- Your channel is connected to Google: with the custom asset key of your Google stream for [Google Pod Serving](../integrations/google/pod-serving.mdx#configure-your-channel), and with the DAI asset key for [Google DAI](../integrations/google/dai.mdx#configure-your-channel). + +## Live and VOD + +### Live + +- **SGAI** — OptiView Ads announces each break to Google ahead of its start, within the [look-forward time](../integrations/google/index.mdx#look-forward-time), so Google can decision the pod in time. Breaks can be scheduled, [punched](../concepts/breaks.mdx#break-punching), or created by [break detection](../concepts/marker-detection.mdx). See [Google Pod Serving](../integrations/google/pod-serving.mdx) for the Google Ad Manager setup and how to schedule a pod break. +- **SSAI** — the Dolby Ads Proxy inserts the break cues into the stream that Google DAI reads, and Google stitches the decisioned ads into the stream that viewers receive. See [Google DAI](../integrations/google/dai.mdx). +- Allow for the [decisioning margin](../integrations/google/index.mdx#decisioning-margin): a Google break must be created at least a few seconds before its start. + +### VOD + +- **SGAI** — schedule the Google breaks at their positions in the asset, in seconds, on a `mediatime` channel. Google decisions the pods when the viewer's session starts, and the SDK inserts them at the break positions. +- **SSAI** — Google stitches the ads for the asset's breaks into the on-demand stream, and the player plays the stitched asset. +- Because every viewer watches from their own position, ads are decisioned per viewer session rather than per break moment: there is no audience-wide peak at a break start. + +Contact your Dolby OptiView account team to enable Google Ad Manager on your VOD channels. + +## What your app needs + +The SDK reads the Google settings — your network code and the channel's Google asset key — from the channel's Break Manifest, and starts the Google stream session automatically when the session starts. You do not configure them in the app, so your app and the backend always agree on which Google stream the ads belong to. + +| Platform | Requirement | +| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Web | Load Google's IMA DAI SDK on the page, before your application script (see below). | +| Android | Nothing extra: the SDK runtime includes the Google IMA SDK. | +| iOS and tvOS | Nothing extra: the runtime pod includes the Google IMA SDK. With Swift Package Manager, add the Google IMA packages as described in [iOS](../player-integration/optiview-ads-sdk/ios.mdx#swift-package-manager). | +| React Native | Nothing extra: the native SDKs include the Google IMA SDK. | + +On Web, add the IMA DAI loader to your page: + +```html + +``` + +If your channel also uses [VAST](./vast.mdx) breaks, load `ima3.js` as well; the two scripts work side by side. + +### Server-side sessions + +When the channel steers a device to SSAI, the SDK requests the stitched stream from Google and loads it into your content player instead of your original stream URL. Your app keeps the same integration and starts the session with the same Break Manifest URL. On Web, use a content player adapter that exposes its video element, such as the HLS.js, Shaka, or native video adapter. In a server-side session, the SDK still plays the [event-triggered breaks](../concepts/breaks.mdx#event-based-triggers) — pre-roll, pause, and post-roll — on the device. + +:::note[Upgrading from an earlier integration] +Earlier versions of this guide set a `networkCode` in the `gam` configuration and a `customAssetKey` in the session configuration. The SDK no longer accepts them: remove both, and the SDK takes the values from the Break Manifest. +::: + +### Turn Google off for a session + +To keep Google out of a session — for example until the viewer gives consent, or in a build that must not contact Google — set `enabled` to `false` in the `gam` configuration. The SDK then skips the Google breaks in that session and reports `DA-GAM-CONFIG-MISSING`. + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + +```typescript +const sdk = new OptiViewAds({ + player: new THEOplayerAdapter(player, container), + container: document.getElementById('container'), + gam: { enabled: false }, +}); +``` + + + + +```kotlin +val sdk = OptiViewAds( + config = OptiViewAdsConfig( + player = THEOplayerAdapter(theoPlayerView.player), + gam = GamConfig(enabled = false), + ), + renderer = OverlayAdRenderer(adContainer), +) +``` + + + + +```swift +let sdk = OptiViewAds( + config: OptiViewAdsConfig( + player: THEOplayerAdapter(player: theoplayer), + gam: GamConfig(enabled: false) + ), + renderer: OverlayAdRenderer(container: adContainer) +) +``` + + + + +```typescript +const ads = createOptiViewAds(player, { gam: { enabled: false } }); +``` + + + + +## Ad targeting parameters + +For Google, `assetParameters` are sent as Google [ad tag parameters](https://support.google.com/admanager/answer/10678356) (`adTagParameters`). As a rule of thumb: + +- Set the values that describe your content on the break, such as `description_url` and `plcmt`. See [Required Google parameters](../integrations/google/pod-serving.mdx#required-google-parameters). +- Set the values that depend on the playback environment in the SDK, such as `vpa` and `vpmute` and, in apps, the [device and app identity parameters](../integrations/google/pod-serving.mdx#additional-parameters-for-app-inventory). + +When the same key is set in both places, the value on the break wins. See [Ad targeting parameters](../how-to-guides/ad-tag-parameters.mdx) for the merge rules and platform examples. + +## Troubleshooting + +| Diagnostic | What it means | What to do | +| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `DA-GAM-CONFIG-RESOLVED` | Informational: the Google stream session uses the network code and custom asset key in the diagnostic. | Check that they match your Google live stream. | +| `DA-GAM-CONFIG-MISSING` | The Break Manifest carries Google breaks but no usable Google configuration, or Google is turned off with `gam` `enabled: false`. | Check that the channel is configured for Google Pod Serving, or remove the opt-out. | +| `DA-GAM-SESSION-FAILED` | The Google stream session could not be started. | On Web, load `ima3_dai.js` on the page. Otherwise, check the error message in the diagnostic. | + +Breaks that fail in the backend, for example because Google could not decision them in time, end up in the `ERROR` state and never reach the SDK. See [Troubleshooting](../integrations/google/pod-serving.mdx#troubleshooting) on the Google Pod Serving integration page. + +## Related resources + +| Resource | Description | +| ------------------------------------------------------------------------ | --------------------------------------------------------------------- | +| [Google Ad Manager](../integrations/google/index.mdx) | Organization-level prerequisites: network code and service account. | +| [Google Pod Serving integration](../integrations/google/pod-serving.mdx) | Google Ad Manager setup, channel configuration, and pod breaks. | +| [Google DAI integration](../integrations/google/dai.mdx) | Server-side insertion: proxy, live stream, and channel configuration. | +| [Ad targeting parameters](../how-to-guides/ad-tag-parameters.mdx) | Passing ad tag parameters to Google. | +| [VAST](./vast.mdx) | Play VAST tags from your own ad server, without Google Ad Manager. | diff --git a/ads/workflows/index.mdx b/ads/workflows/index.mdx new file mode 100644 index 000000000000..8187a6c94a4c --- /dev/null +++ b/ads/workflows/index.mdx @@ -0,0 +1,60 @@ +--- +sidebar_position: 0 +sidebar_label: Ad workflows +description: How OptiView Ads monetizes live and VOD content with static assets, VAST, and Google Ad Manager. +--- + +# Ad workflows + +OptiView Ads is a **hybrid ad insertion platform**: the same channel and the same breaks can be delivered server-guided (SGAI) or server-side (SSAI), for live streams and for video-on-demand (VOD) assets. This page explains the three choices that together make up your ad workflow: + +1. **Use case** — are you monetizing a [live stream](./live.mdx) or a [VOD asset](./vod.mdx)? +2. **Ad source** — where do the ads come from: [static assets](./static-assets.mdx) from your CDN, [VAST](./vast.mdx) tags from your ad server, or [Google Ad Manager](./google-ad-manager.mdx)? +3. **Delivery mode** — does the player insert the ads (SGAI), or are they stitched into the stream (SSAI)? + +## Hybrid ad insertion: SGAI and SSAI + +| Delivery mode | How it works | Use it for | +| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Server-Guided Ad Insertion (SGAI)** | The OptiView Ads backend publishes the breaks in a side-loaded [Break Manifest](../concepts/break-manifest.mdx). The [OptiView Ads SDK](../player-integration/optiview-ads-sdk/index.mdx) reads it, and plays the ads on top of your content. | Web, mobile, and most connected TV apps. Required for the advanced [layouts](../concepts/breaks.mdx#layouts) such as double box, L-shape, and overlays. | +| **Server-Side Ad Insertion (SSAI)** | The ads are stitched into the media stream before it reaches the player. The player plays one continuous stream. | Platforms where a client-side SDK is not an option, such as Roku and older connected TV devices. | + +Both modes share the same model: you create a [channel](../concepts/channels.mdx), schedule or detect [breaks](../concepts/breaks.mdx) on it, and OptiView Ads delivers them. You do not maintain two ad setups. + +A channel can **steer the delivery mode per device**: for example SGAI on web and mobile, and SSAI on a specific connected TV platform. The Break Manifest then carries the delivery rules, and the SDK picks the mode for the device it runs on when the session starts. In SSAI mode, the SDK still plays the [event-triggered breaks](../concepts/breaks.mdx#event-based-triggers) — pre-roll, pause, and post-roll — on the device, because they depend on what the individual viewer does. + +SSAI is available with [Google Ad Manager](./google-ad-manager.mdx), through Google DAI. Static assets and VAST tags are always played server-guided. + +## Live and VOD + +Live and VOD are different use cases, and a channel is created for one of them. The difference is mainly in how breaks are placed on the timeline and how players receive them: + +| | [Live](./live.mdx) | [VOD](./vod.mdx) | +| ------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| Channel | `streamType: "live"` (the default) | `streamType: "vod"` | +| Break start | A moment on the live timeline: a UTC timestamp (`wallclock`) or a presentation timestamp (`pts`) | A position in the asset: seconds from the start (`mediatime`), or a UTC timestamp (`wallclock`) | +| How breaks are made | Scheduled ahead or on the spot, [punched](../concepts/breaks.mdx#break-punching) live, or detected from ad markers in the stream | Scheduled upfront, for example as pre-roll, mid-rolls, and post-roll | +| Break Manifest | Polled continuously; breaks appear as they become relevant | Fetched once at the start of playback; it lists all breaks | +| Events | [Events](../concepts/events.mdx) group the breaks of a live event | Not used | + +## Supported workflows + +Every ad source works for both live and VOD. One channel, and even one break, can mix ad sources. + +| Ad source | What the break carries | Live | VOD | What your app needs | +| -------------------------------------------- | ----------------------------------------------------- | ----------- | ----------- | -------------------------------------------------------------------------- | +| [Static assets](./static-assets.mdx) | Direct URLs to video or image creatives on your CDN. | SGAI | SGAI | Nothing beyond the SDK integration. | +| [VAST](./vast.mdx) | A VAST tag URL on your ad server, or an advertiser's. | SGAI | SGAI | On Web, Google's client-side IMA SDK (`ima3.js`). | +| [Google Ad Manager](./google-ad-manager.mdx) | An ad pod decisioned by Google Ad Manager 360. | SGAI + SSAI | SGAI + SSAI | On Web, Google's IMA DAI SDK (`ima3_dai.js`). Google Ad Manager 360 setup. | + +### Which ad source should I use? + +- **Static assets** when you know which creative to show: direct-sold campaigns, sponsorships, promos, branded overlays. No ad server is involved. +- **VAST** when your own ad server, or a partner's, decides which ad plays. Any VAST-compliant ad server works, Google Ad Manager tags included. +- **Google Ad Manager** when you sell your inventory through Google Ad Manager 360 and want Google to fill complete ad pods, or need server-side insertion through Google DAI. + +## Next steps + +import DocCardList from '@theme/DocCardList'; + + diff --git a/ads/workflows/live.mdx b/ads/workflows/live.mdx new file mode 100644 index 000000000000..a3a8558c5a30 --- /dev/null +++ b/ads/workflows/live.mdx @@ -0,0 +1,66 @@ +--- +sidebar_position: 1 +sidebar_label: Live +description: Monetize a live stream with OptiView Ads. +--- + +# Live + +A live channel monetizes a linear stream or a live event. Breaks are placed on the live timeline, and players watching the stream — at the live edge or behind it in the DVR window — receive them through the channel's [Break Manifest](../concepts/break-manifest.mdx). + +## Set up a live channel + +A channel is live by default. Choose the [timebase](../concepts/channels.mdx#timebase) that matches the timing information in your stream: + +- **`wallclock`** — breaks start at a UTC timestamp, matched against the stream's own wallclock timeline (`EXT-X-PROGRAM-DATE-TIME` in HLS, the segment timeline in DASH). This is the recommended timebase. +- **`pts`** — breaks start at a presentation timestamp on the encoder's timeline. + +```bash +curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels' \ + -u "$ADS_API_KEY:$ADS_API_SECRET" \ + -H 'Content-Type: application/json' \ + -H 'X-Org-ID: ' \ + -d '{ + "name": "Sports main", + "streamType": "live", + "timebase": "wallclock" + }' +``` + +The [DVR window](../concepts/channels.mdx#dvr-window), [live offset](../concepts/channels.mdx#live-offset), and [ad prefetch window](../concepts/channels.mdx#ad-prefetch-window) settings tune which breaks the Break Manifest contains at any moment. + +## How breaks are created + +On a live stream, breaks can be created in three ways, and you can combine them on one channel: + +- **Scheduled** — create a break with a start time, ahead of time or on the spot. See [Scheduling](../concepts/breaks.mdx#scheduling). +- **Punched** — prepare a break without a start time, and fire it when the moment comes, for example from your production control room. See [Break punching](../concepts/breaks.mdx#break-punching). +- **Detected** — add your stream as an [origin](../concepts/origins.mdx), and OptiView Ads turns the ad markers in the stream, such as SCTE-35 signals, into breaks. See [Break detection](../concepts/marker-detection.mdx). This replaces the ad breaks already in your stream (Dynamic Ad Replacement). + +[Events](../concepts/events.mdx) let you prepare the breaks of a live event, such as a match or a show, upfront. [Templates](../concepts/templates.mdx) store a break configuration once, so scheduling becomes a one-liner. + +Besides breaks on the timeline, a live channel can carry [event-triggered breaks](../concepts/breaks.mdx#event-based-triggers): a pre-roll when the viewer starts watching, a pause ad, and a post-roll. + +## How players receive the breaks + +The SDK polls the Break Manifest during the whole session. A break appears in the manifest shortly before it starts — within the ad prefetch window — so the SDK can prepare the ads, and it stays there while viewers in the DVR window can still reach it. Changes to a break, such as an earlier end, reach the players on the next poll. + +## Delivery modes + +Live channels support both delivery modes of the [hybrid platform](./index.mdx#hybrid-ad-insertion-sgai-and-ssai): + +| Ad source | SGAI | SSAI | +| -------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------ | +| [Static assets](./static-assets.mdx) | Yes | No | +| [VAST](./vast.mdx) | Yes | No | +| [Google Ad Manager](./google-ad-manager.mdx) | Yes, with [Google Pod Serving](../integrations/google/pod-serving.mdx) | Yes, with [Google DAI](../integrations/google/dai.mdx) | + +## Related resources + +| Resource | Description | +| --------------------------------------------------- | ----------------------------------------------------------- | +| [Getting started](../getting-started/index.mdx) | Create a live channel and play your first break end to end. | +| [Channels](../concepts/channels.mdx) | Timebase, DVR window, live offset, and prefetch settings. | +| [Breaks](../concepts/breaks.mdx) | Scheduling, punching, layouts, and the asset model. | +| [Break detection](../concepts/marker-detection.mdx) | Turn the ad markers in your stream into breaks. | +| [VOD](./vod.mdx) | Monetize on-demand assets instead. | diff --git a/ads/workflows/static-assets.mdx b/ads/workflows/static-assets.mdx new file mode 100644 index 000000000000..10c60460a301 --- /dev/null +++ b/ads/workflows/static-assets.mdx @@ -0,0 +1,105 @@ +--- +sidebar_position: 3 +sidebar_label: Static assets +description: Play ad creatives from your own CDN, on live and VOD, without an ad server. +--- + +# Static assets + +With static assets, each break points directly at its ad creatives: video or image files that you host on your own CDN. No ad server is involved — the SDK fetches the creative from the URL on the break and plays it when the break starts. Use this workflow for direct-sold campaigns, sponsorships, promos, and branded overlays where you already know which creative to show. + +| | [Live](./live.mdx) | [VOD](./vod.mdx) | +| -------------- | ---------------------------------- | ---------------------------------- | +| Supported | Yes | Yes | +| Delivery mode | SGAI | SGAI | +| Ad decisioning | None: the break names the creative | None: the break names the creative | + +## What your app needs + +Nothing beyond the integration for your platform: [Web](../player-integration/optiview-ads-sdk/web.mdx), [Android](../player-integration/optiview-ads-sdk/android.mdx), [iOS](../player-integration/optiview-ads-sdk/ios.mdx), or [React Native](../player-integration/optiview-ads-sdk/react-native.mdx). Static assets need no ad server, no Google Ad Manager account, and no extra configuration in the app. + +## Schedule a break with static assets + +A static asset sets `type` to `static` and `uri` to the URL of the creative. The asset is the same for live and VOD; only the break's `start` differs, see [Live and VOD](#live-and-vod). On a live `wallclock` channel: + +```bash +curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//breaks' \ + -u "$ADS_API_KEY:$ADS_API_SECRET" \ + -H 'Content-Type: application/json' \ + -H 'X-Org-ID: ' \ + -d '{ + "start": "", + "duration": 30, + "variant": { + "format": "single", + "assets": [ + { + "type": "static", + "mediaType": "video", + "mimeType": "application/x-mpegurl", + "uri": "https://cdn.example.com/ads/spot.m3u8", + "interaction": { "clickThrough": "https://www.example.com/offer" } + } + ] + } + }' +``` + +The `uri` can also be a list of URLs targeted per device type. See [Static assets](../concepts/breaks.mdx#static-assets) and [Asset URI targeting](../concepts/breaks.mdx#asset-uri-targeting) for the full asset model. + +## Live and VOD + +### Live + +- Schedule the break ahead of time with a UTC `start`, prepare it without a start and [punch](../concepts/breaks.mdx#break-punching) it, or let [break detection](../concepts/marker-detection.mdx) create it from the ad markers in your stream — with a [template](../concepts/templates.mdx) that holds the static assets. +- The SDK receives the break shortly before it starts, within the channel's [ad prefetch window](../concepts/channels.mdx#ad-prefetch-window), and prefetches the creative so the ad starts without delay. +- Static assets always play server-guided. On a channel that steers some devices to SSAI, those devices still play the static [event-triggered breaks](../concepts/breaks.mdx#event-based-triggers) — pre-roll, pause, and post-roll — but not the breaks on the timeline. + +### VOD + +- Set `start` to the position in the asset, in seconds, on a `mediatime` channel — for example `"start": 600` — or use an event trigger for a pre-roll or post-roll. +- The SDK receives all breaks when the session starts, and prepares each creative shortly before its break. +- Enable [snapback](./vod.mdx#seeking-and-snapback) on breaks that viewers must not skip by seeking. + +## Supported layouts + +Static assets work in every [layout](../concepts/breaks.mdx#layouts) and as [pause ads](../concepts/breaks.mdx#pause): + +| Layout | Static asset | +| --------------------- | ---------------------------------------------------------------------------------------- | +| `single` | A video that replaces the content. | +| `double`, `lshape_ad` | A video, with an image or video `companion` that fills the background. | +| `lshape_content` | An image that fills the L-shaped backdrop while your content keeps playing. | +| `overlay` | An image or video on top of your content. | +| Pause ad | An image, or a progressive MP4 video that plays muted, shown while the viewer is paused. | + +An image stays on screen for the asset's `duration`, or for the break's `duration` when the asset has none. + +## Creative formats + +- **HLS (`.m3u8`)** is the recommended format for video creatives on every platform. On connected TVs in particular, the SDK can prefetch an HLS creative ahead of the break, so the ad starts faster. +- **Progressive MP4** also works. On Web, the SDK plays MP4 creatives through the browser's own video element. +- **Images** are used for overlays, companions, L-shape backdrops, and pause ads. + +Set `mimeType` on the asset when you know it. The SDK then knows upfront how to play the creative, instead of having to find out, which makes ad preparation faster. + +## Tracking and reporting + +The SDK reports an OptiView Ads [impression](../how-to-guides/ad-impressions.md) for every break it presents, and emits ad events — such as the start and end of each break and ad — that your app can listen to. See the API reference of your platform for the full list of events. + +Static assets carry no third-party tracking URLs. If an advertiser needs to count impressions in their own ad server, deliver the creative through a [VAST](./vast.mdx) tag instead: the VAST response carries the advertiser's tracking URLs, which are fired while the ad plays. + +## Troubleshooting + +- **The break does not play.** Check that the channel's [Break Manifest](../concepts/break-manifest.mdx) contains the break, and that the creative URL is publicly reachable. +- **Web: the creative fails to load.** The SDK downloads HLS creatives with HTTP requests from your page, so your CDN must allow cross-origin requests (CORS) from your app's origin. +- **A creative cannot be played.** The SDK emits an `aderror` event for the asset, continues with the next asset in the break if there is one, and otherwise returns to your content. + +## Related resources + +| Resource | Description | +| ------------------------------------------------------------ | ------------------------------------------------------------- | +| [Breaks](../concepts/breaks.mdx) | Layouts, variants, controls, and the asset model. | +| [Templates](../concepts/templates.mdx) | Store a break with its static assets once, and reuse it. | +| [VAST](./vast.mdx) | Let your ad server decide which creative to play. | +| [Ad impression tracking](../how-to-guides/ad-impressions.md) | How OptiView Ads counts the breaks presented to your viewers. | diff --git a/ads/workflows/vast.mdx b/ads/workflows/vast.mdx new file mode 100644 index 000000000000..53f4f567477b --- /dev/null +++ b/ads/workflows/vast.mdx @@ -0,0 +1,138 @@ +--- +sidebar_position: 4 +sidebar_label: VAST +description: Let your own ad server, or a partner's, decide the ads through VAST tags, on live and VOD. +--- + +# VAST + +With VAST, each break points at a VAST tag: a URL on your ad server, or an advertiser's, that returns a [VAST](https://iabtechlab.com/standards/vast/) XML document. The ad server decides which creative to play, and its response carries the media files and the tracking URLs. Use this workflow when you run your own ad server, or buy from partners that deliver their ads through VAST tags. + +The SDK requests and plays VAST tags on the device, through Google's client-side IMA SDK. IMA processes the VAST response — it follows wrappers, picks a media file, and fires the tracking URLs. IMA works with any VAST-compliant ad server: you do not need a Google Ad Manager account. A Google Ad Manager VAST tag works too. + +| | [Live](./live.mdx) | [VOD](./vod.mdx) | +| -------------- | --------------------------------------------- | --------------------------------------------- | +| Supported | Yes | Yes | +| Delivery mode | SGAI | SGAI | +| Ad decisioning | Your ad server, when the SDK requests the tag | Your ad server, when the SDK requests the tag | + +## What your app needs + +| Platform | Requirement | +| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Web | Load Google's client-side IMA SDK on the page, before your application script (see below). | +| Android | Nothing extra: the SDK runtime includes the Google IMA SDK. | +| iOS and tvOS | Nothing extra: the runtime pod includes the Google IMA SDK. With Swift Package Manager, add the Google IMA packages as described in [iOS](../player-integration/optiview-ads-sdk/ios.mdx#swift-package-manager). | +| React Native | Nothing extra: the native SDKs include the Google IMA SDK. | + +On Web, add the IMA loader to your page: + +```html + +``` + +Without it, the SDK cannot play VAST breaks: it reports `DA-VAST-IMA-SDK-MISSING` and returns to your content. If your channel also uses [Google Pod Serving](./google-ad-manager.mdx), load `ima3_dai.js` as well; the two scripts work side by side. + +:::caution[Web: include an MP4 media file] +The IMA SDK for HTML5 plays the ad through the browser's own video element, which cannot play HLS outside Safari. Make sure your VAST responses include a progressive MP4 media file, or the ad fails to play in Chrome, Edge, and Firefox. +::: + +## Schedule a VAST break + +A VAST asset sets `type` to `vast` and `uri` to the VAST tag URL. The asset is the same for live and VOD; only the break's `start` differs, see [Live and VOD](#live-and-vod). On a live `wallclock` channel: + +```bash +curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//breaks' \ + -u "$ADS_API_KEY:$ADS_API_SECRET" \ + -H 'Content-Type: application/json' \ + -H 'X-Org-ID: ' \ + -d '{ + "start": "", + "duration": 30, + "variant": { + "format": "single", + "assets": [ + { + "type": "vast", + "mediaType": "video", + "mimeType": "application/xml", + "uri": "https://adserver.example.com/vast?slot=midroll", + "assetParameters": { + "content_genre": "sports" + } + } + ] + } + }' +``` + +The `uri` can also be a list of tag URLs targeted per device type. See [VAST assets](../concepts/breaks.mdx#vast-assets) and [Asset URI targeting](../concepts/breaks.mdx#asset-uri-targeting) for the full asset model. + +## Live and VOD + +The SDK requests the VAST tag on the device, shortly before the break starts. Every viewer therefore gets an individual ad decision, on live and on VOD. + +### Live + +- Schedule, [punch](../concepts/breaks.mdx#break-punching), or [detect](../concepts/marker-detection.mdx) the break as on any live channel; for detected breaks, put the VAST asset in the rule's [template](../concepts/templates.mdx). +- Many viewers reach a live break at the same moment, so your ad server receives a peak of requests at every break start. Make sure it is sized for your concurrent audience. +- On a channel that steers some devices to SSAI, VAST breaks on the timeline are not played on those devices. See [Troubleshooting](#troubleshooting). + +### VOD + +- Set `start` to the position in the asset, in seconds, on a `mediatime` channel, or use an event trigger for a pre-roll, a post-roll, or a pause ad. +- Viewers reach the breaks at different moments, so the requests to your ad server are spread over time. +- Use a VAST tag that returns the right ad length for the break: the break's `duration` is the maximum, and the SDK returns to your content when it is reached. + +## Supported layouts + +VAST describes a linear (video) ad, so VAST assets work in the layouts where an ad video plays: + +| Layout | VAST asset | +| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `single` | Supported. | +| `double`, `lshape_ad` | Supported. The VAST ad plays in the ad box, and the asset's `companion` fills the background. | +| `lshape_content`, `overlay` | Not supported. The SDK does not play the asset and reports `DA-VAST-UNSUPPORTED-FORMAT`. Use a [static asset](./static-assets.mdx) instead. | +| Pause ad | Supported. The SDK reads the image from the VAST companion ads, or a progressive MP4 from the linear ad, and fires its impression tracking when shown. | + +VAST breaks play in server-guided (SGAI) sessions only. + +## Ad targeting parameters + +To personalize the ad request, add `assetParameters`. The SDK appends them to the VAST tag URL as URL-encoded query parameters when it requests the tag. For the break above, with a session-level parameter `device_id` set in the SDK, the request becomes: + +```text +https://adserver.example.com/vast?slot=midroll&content_genre=sports&device_id=abc123 +``` + +Set the parameters in one of two places: + +- **On the break**, for values that are the same for every viewer, such as the content genre. +- **In the SDK**, with `assetParameters` in the session configuration or `updateAssetParameters()`, for values that depend on the viewer or the device. + +When the same key is set in both places, the value on the break wins. Parameter values can also contain macros, such as `$OPTIVIEW_PLAYER_WIDTH$`, that the SDK fills in when it builds the request. See [Ad targeting parameters](../how-to-guides/ad-tag-parameters.mdx) for the merge rules, the macros, and platform examples. + +## Tracking and reporting + +- IMA fires the tracking URLs in the VAST response, such as impressions, quartiles, and clicks, so the ad server counts the ad. +- The SDK reports an OptiView Ads [impression](../how-to-guides/ad-impressions.md) for the break, and emits the same ad events as for any other break. + +## Troubleshooting + +VAST failures never block your content: the SDK emits an `aderror` event, reports a diagnostic, and returns to the content. + +| Diagnostic | What it means | What to do | +| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `DA-VAST-IMA-SDK-MISSING` | Google's client-side IMA SDK is not available. | On Web, load `ima3.js` on the page. | +| `DA-VAST-IMA-ERROR` | IMA could not load, parse, or play the VAST response — for example an unreachable tag, an empty response, or no playable media file. | Test the tag in Google's [VAST Inspector](https://googleads.github.io/googleads-ima-html5/vsi/). On Web, make sure the response includes a progressive MP4 media file. | +| `DA-VAST-UNSUPPORTED-FORMAT` | The VAST asset is in an `overlay` or `lshape_content` break. | Use the `single`, `double`, or `lshape_ad` layout, or a static asset. | +| `DA-VAST-SSAI-UNSUPPORTED` | The VAST asset is in a server-side (SSAI) session. | Play VAST breaks in a server-guided (`sgai`) session. | + +## Related resources + +| Resource | Description | +| ----------------------------------------------------------------- | ------------------------------------------------------------- | +| [Breaks](../concepts/breaks.mdx) | Layouts, variants, controls, and the asset model. | +| [Ad targeting parameters](../how-to-guides/ad-tag-parameters.mdx) | Passing targeting parameters to your ad server. | +| [Static assets](./static-assets.mdx) | Play creatives from your CDN without an ad server. | +| [Google Pod Serving](./google-ad-manager.mdx) | Let Google Ad Manager decision the ads that fill your breaks. | diff --git a/ads/workflows/vod.mdx b/ads/workflows/vod.mdx new file mode 100644 index 000000000000..77c3e702bc90 --- /dev/null +++ b/ads/workflows/vod.mdx @@ -0,0 +1,105 @@ +--- +sidebar_position: 2 +sidebar_label: VOD +description: Monetize video-on-demand assets with OptiView Ads. +--- + +# VOD + +A VOD channel monetizes an on-demand asset: a movie, an episode, a replay, or a clip. Every viewer watches the asset from its own position, so breaks are placed at positions in the asset rather than at moments in time, and the player receives all of them at once when playback starts. + +## Set up a VOD channel + +Create the channel with `streamType` set to `vod`, and choose a timebase: + +- **`mediatime`** — breaks start at a position in the asset, in seconds from its start. For example, `600` is 10 minutes into the asset. This is the recommended timebase for VOD, and it is only available on VOD channels. +- **`wallclock`** — breaks start at a UTC timestamp, matched against the asset's `EXT-X-PROGRAM-DATE-TIME` timeline. Use it for replays of a live stream that keep their original program date-time. Unlike on a live channel, the timestamp may lie in the past. + +```bash +curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels' \ + -u "$ADS_API_KEY:$ADS_API_SECRET" \ + -H 'Content-Type: application/json' \ + -H 'X-Org-ID: ' \ + -d '{ + "name": "Movie: The Big Match", + "streamType": "vod", + "timebase": "mediatime" + }' +``` + +The `streamType` and the `timebase` are set when you create the channel and cannot be changed afterwards. Create one VOD channel per asset, or per group of assets that share the same break positions. + +## Schedule breaks + +On a VOD channel you schedule all breaks upfront. With the `mediatime` timebase, `start` is a number of seconds: + +```bash +curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//breaks' \ + -u "$ADS_API_KEY:$ADS_API_SECRET" \ + -H 'Content-Type: application/json' \ + -H 'X-Org-ID: ' \ + -d '{ + "start": 600, + "duration": 30, + "controls": { "snapback": true }, + "variant": { + "format": "single", + "assets": [ + { + "type": "static", + "mediaType": "video", + "uri": "https://cdn.example.com/ads/spot.m3u8" + } + ] + } + }' +``` + +A typical VOD ad plan combines: + +- **Pre-roll** — a break triggered when playback starts, with an [event trigger](../concepts/breaks.mdx#start) instead of a start position. +- **Mid-rolls** — breaks at positions in the asset, such as `600` and `1800`. +- **Post-roll** — a break triggered when playback ends, with an [end trigger](../concepts/breaks.mdx#end). +- **Pause ads** — shown while the viewer is paused, with a [pause trigger](../concepts/breaks.mdx#pause). + +Breaks on a VOD channel cannot overlap. + +### Seeking and snapback + +VOD viewers seek freely, so decide per break what happens when they skip over it, with the break's [controls](../concepts/breaks.mdx#controls): + +- With `snapback` enabled, a viewer who seeks past a break is taken back to the break first. After the break, playback continues at the position the viewer was seeking to. +- Without `snapback`, the viewer can skip the break. + +A break plays at most once per session: seeking back over a break that has already played does not play it again. + +## How players receive the breaks + +A VOD Break Manifest lists all breaks of the channel, and carries no polling interval. The SDK fetches it once when the session starts, and schedules every break against the playback position of the asset. Changes you make to the breaks apply to the next playback session. + +Your app integrates the SDK in the same way as for live: [Web](../player-integration/optiview-ads-sdk/web.mdx), [Android](../player-integration/optiview-ads-sdk/android.mdx), [iOS](../player-integration/optiview-ads-sdk/ios.mdx), or [React Native](../player-integration/optiview-ads-sdk/react-native.mdx). Start a session with the Break Manifest URL of the VOD channel when you load the asset. + +## What is different from live + +The live-only features do not apply to VOD channels: + +- **No break detection.** VOD channels do not monitor origins for ad markers; you schedule the breaks. +- **No events.** [Events](../concepts/events.mdx) group the breaks of a live event; a VOD asset has no live moment to prepare for. +- **No `pts` timebase.** Use `mediatime` or `wallclock`. + +## Delivery modes + +| Ad source | SGAI | SSAI | +| -------------------------------------------- | ---- | ---- | +| [Static assets](./static-assets.mdx) | Yes | No | +| [VAST](./vast.mdx) | Yes | No | +| [Google Ad Manager](./google-ad-manager.mdx) | Yes | Yes | + +## Related resources + +| Resource | Description | +| ------------------------------------------------ | ------------------------------------------------------- | +| [Breaks](../concepts/breaks.mdx) | Event triggers, controls, layouts, and the asset model. | +| [Channels](../concepts/channels.mdx) | Stream type and timebase. | +| [Break Manifest](../concepts/break-manifest.mdx) | How breaks are delivered to players. | +| [Live](./live.mdx) | Monetize live streams instead. | diff --git a/sidebarsAds.ts b/sidebarsAds.ts index 90892d2e98f7..adc727126457 100644 --- a/sidebarsAds.ts +++ b/sidebarsAds.ts @@ -15,6 +15,17 @@ const sidebars: SidebarsConfig = { link: { type: 'doc', id: 'getting-started/index' }, items: [{ type: 'autogenerated', dirName: 'getting-started' }], }, + { + type: 'category', + label: 'Ad workflows', + description: 'Live and VOD, SGAI and SSAI, with static assets, VAST, or Google Ad Manager.', + collapsed: false, + customProps: { + icon: '🔀', + }, + link: { type: 'doc', id: 'workflows/index' }, + items: ['workflows/live', 'workflows/vod', 'workflows/static-assets', 'workflows/vast', 'workflows/google-ad-manager'], + }, { type: 'category', label: 'Player integration', From 9d59c32a6a4756fd72aa498dbc7ac3821dd2fd92 Mon Sep 17 00:00:00 2001 From: Maarten Rimaux Date: Thu, 22 Oct 2026 21:01:23 +0200 Subject: [PATCH 2/7] Ads: fix spellcheck in workflow docs --- ads/concepts/breaks.mdx | 2 +- ads/workflows/static-assets.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ads/concepts/breaks.mdx b/ads/concepts/breaks.mdx index 3e9f62797ee0..30851639c5b6 100644 --- a/ads/concepts/breaks.mdx +++ b/ads/concepts/breaks.mdx @@ -25,7 +25,7 @@ The [timebase of the channel](./channels.mdx#timebase) defines how a break is sc - **`wallclock`** — the break's `start` is a UTC ISO 8601 timestamp (for example `"2026-07-16T12:15:00.000Z"`). Players match it against the wallclock timeline carried by the stream. `start` is optional on wallclock channels: omitting it creates a [cued break](#cued-breaks). - **`pts`** — the break's `start` is a non-negative number: a presentation timestamp on the encoder's timeline. `start` is required on PTS channels. -- **`mediatime`** — the break's `start` is a non-negative number of seconds from the start of the asset (for example `600`). `start` is required on mediatime channels, which are always [VOD](../workflows/vod.mdx) channels. +- **`mediatime`** — the break's `start` is a non-negative number of seconds from the start of the asset (for example `600`). `start` is required on `mediatime` channels, which are always [VOD](../workflows/vod.mdx) channels. `duration` is always required and is expressed in seconds. It is the **maximum** duration of the break. diff --git a/ads/workflows/static-assets.mdx b/ads/workflows/static-assets.mdx index 10c60460a301..a21edae79b19 100644 --- a/ads/workflows/static-assets.mdx +++ b/ads/workflows/static-assets.mdx @@ -52,7 +52,7 @@ The `uri` can also be a list of URLs targeted per device type. See [Static asset ### Live - Schedule the break ahead of time with a UTC `start`, prepare it without a start and [punch](../concepts/breaks.mdx#break-punching) it, or let [break detection](../concepts/marker-detection.mdx) create it from the ad markers in your stream — with a [template](../concepts/templates.mdx) that holds the static assets. -- The SDK receives the break shortly before it starts, within the channel's [ad prefetch window](../concepts/channels.mdx#ad-prefetch-window), and prefetches the creative so the ad starts without delay. +- The SDK receives the break shortly before it starts, within the channel's [ad prefetch window](../concepts/channels.mdx#ad-prefetch-window), and loads the creative ahead of time so the ad starts without delay. - Static assets always play server-guided. On a channel that steers some devices to SSAI, those devices still play the static [event-triggered breaks](../concepts/breaks.mdx#event-based-triggers) — pre-roll, pause, and post-roll — but not the breaks on the timeline. ### VOD From 95124c031259696690cf9b8162099ef778409a38 Mon Sep 17 00:00:00 2001 From: Maarten Rimaux Date: Thu, 22 Oct 2026 21:32:49 +0200 Subject: [PATCH 3/7] Ads: describe break detection for live and VOD, trim intro --- ads/concepts/channels.mdx | 2 +- ads/index.mdx | 4 ++-- ads/workflows/google-ad-manager.mdx | 2 +- ads/workflows/index.mdx | 14 +++++++------- ads/workflows/static-assets.mdx | 2 +- ads/workflows/vast.mdx | 2 +- ads/workflows/vod.mdx | 8 ++++++-- 7 files changed, 19 insertions(+), 15 deletions(-) diff --git a/ads/concepts/channels.mdx b/ads/concepts/channels.mdx index 44cd08a491cb..3e03898883eb 100644 --- a/ads/concepts/channels.mdx +++ b/ads/concepts/channels.mdx @@ -35,7 +35,7 @@ These channel settings determine how break start times are interpreted and how b The `streamType` determines the use case of the channel: - **`live`** (default) — a live stream. Players poll the Break Manifest continuously and receive breaks as they become relevant. See [Live](../workflows/live.mdx). -- **`vod`** — an on-demand asset. The Break Manifest lists all breaks upfront and players fetch it once. VOD channels do not run break detection and have no events. See [VOD](../workflows/vod.mdx). +- **`vod`** — an on-demand asset. The Break Manifest lists all breaks upfront and players fetch it once. VOD channels have no events. See [VOD](../workflows/vod.mdx). ### Timebase diff --git a/ads/index.mdx b/ads/index.mdx index 28224fab6c80..16a688a7fcf1 100644 --- a/ads/index.mdx +++ b/ads/index.mdx @@ -9,7 +9,7 @@ import SidebarDocCardList from '@site/src/components/SidebarDocCardList'; import ThemedImage from '@theme/ThemedImage'; import useBaseUrl from '@docusaurus/useBaseUrl'; -OptiView Ads is a hybrid ad insertion platform for **live** streams and **video-on-demand (VOD)** assets: the same channel and the same breaks can be delivered with Server-Guided Ad Insertion (SGAI) or Server-Side Ad Insertion (SSAI). Ads come from creatives on your own CDN, from VAST tags on your ad server, or from Google Ad Manager. On these pages, you'll learn how to get started with OptiView Ads, choose the [ad workflow](./workflows/index.mdx) that fits your content, schedule ad breaks, and configure the OptiView Ads SDK — the recommended integration approach. +OptiView Ads is a hybrid ad insertion platform for **live** streams and **video-on-demand (VOD)** assets: the same channel and the same breaks can be delivered with Server-Guided Ad Insertion (SGAI) or Server-Side Ad Insertion (SSAI). Ads come from creatives on your own CDN, from VAST tags on your ad server, or from Google Ad Manager. On these pages, you'll learn how to get started with OptiView Ads, choose the [ad workflow](./workflows/index.mdx) that fits your content, schedule ad breaks, and configure the OptiView Ads SDK. By logically redistributing responsibilities in the advertisement workflow, OptiView Ads: @@ -19,7 +19,7 @@ By logically redistributing responsibilities in the advertisement workflow, Opti - Maximizes workflow efficiency by reducing prefetching and over-allocation of inventory. - Enables more relevant ads through a high degree of personalization. -OptiView Ads models each live stream or VOD asset as a **channel**. A channel schedules **breaks** — on a live stream it can also detect them from the ad markers on its **origins** — and can use reusable **templates** for consistent ad experiences. It generates a **Break Manifest** for the OptiView Ads SDK to read and render. +OptiView Ads models each live stream or VOD asset as a **channel**. A channel schedules **breaks**, or detects them from the ad markers in the stream or asset on its **origins**, and can use reusable **templates** for consistent ad experiences. It generates a **Break Manifest** for the OptiView Ads SDK to read and render. | Workflow | What it is for | | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------- | diff --git a/ads/workflows/google-ad-manager.mdx b/ads/workflows/google-ad-manager.mdx index 5cec563416ae..2708a25ca597 100644 --- a/ads/workflows/google-ad-manager.mdx +++ b/ads/workflows/google-ad-manager.mdx @@ -32,7 +32,7 @@ Prefer SGAI on every platform that runs the OptiView Ads SDK: the media stream s ### VOD -- **SGAI** — schedule the Google breaks at their positions in the asset, in seconds, on a `mediatime` channel. Google decisions the pods when the viewer's session starts, and the SDK inserts them at the break positions. +- **SGAI** — schedule the Google breaks at their positions in the asset, in seconds, on a `mediatime` channel, or let [break detection](../concepts/marker-detection.mdx) create them from the ad markers in the asset. Google decisions the pods when the viewer's session starts, and the SDK inserts them at the break positions. - **SSAI** — Google stitches the ads for the asset's breaks into the on-demand stream, and the player plays the stitched asset. - Because every viewer watches from their own position, ads are decisioned per viewer session rather than per break moment: there is no audience-wide peak at a break start. diff --git a/ads/workflows/index.mdx b/ads/workflows/index.mdx index 8187a6c94a4c..c9efdd055801 100644 --- a/ads/workflows/index.mdx +++ b/ads/workflows/index.mdx @@ -29,13 +29,13 @@ SSAI is available with [Google Ad Manager](./google-ad-manager.mdx), through Goo Live and VOD are different use cases, and a channel is created for one of them. The difference is mainly in how breaks are placed on the timeline and how players receive them: -| | [Live](./live.mdx) | [VOD](./vod.mdx) | -| ------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | -| Channel | `streamType: "live"` (the default) | `streamType: "vod"` | -| Break start | A moment on the live timeline: a UTC timestamp (`wallclock`) or a presentation timestamp (`pts`) | A position in the asset: seconds from the start (`mediatime`), or a UTC timestamp (`wallclock`) | -| How breaks are made | Scheduled ahead or on the spot, [punched](../concepts/breaks.mdx#break-punching) live, or detected from ad markers in the stream | Scheduled upfront, for example as pre-roll, mid-rolls, and post-roll | -| Break Manifest | Polled continuously; breaks appear as they become relevant | Fetched once at the start of playback; it lists all breaks | -| Events | [Events](../concepts/events.mdx) group the breaks of a live event | Not used | +| | [Live](./live.mdx) | [VOD](./vod.mdx) | +| ------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| Channel | `streamType: "live"` (the default) | `streamType: "vod"` | +| Break start | A moment on the live timeline: a UTC timestamp (`wallclock`) or a presentation timestamp (`pts`) | A position in the asset: seconds from the start (`mediatime`), or a UTC timestamp (`wallclock`) | +| How breaks are made | Scheduled ahead or on the spot, [punched](../concepts/breaks.mdx#break-punching) live, or detected from ad markers in the stream | Scheduled upfront, for example as pre-roll, mid-rolls, and post-roll, or detected from ad markers in the asset | +| Break Manifest | Polled continuously; breaks appear as they become relevant | Fetched once at the start of playback; it lists all breaks | +| Events | [Events](../concepts/events.mdx) group the breaks of a live event | Not used | ## Supported workflows diff --git a/ads/workflows/static-assets.mdx b/ads/workflows/static-assets.mdx index a21edae79b19..c79a97634d9d 100644 --- a/ads/workflows/static-assets.mdx +++ b/ads/workflows/static-assets.mdx @@ -57,7 +57,7 @@ The `uri` can also be a list of URLs targeted per device type. See [Static asset ### VOD -- Set `start` to the position in the asset, in seconds, on a `mediatime` channel — for example `"start": 600` — or use an event trigger for a pre-roll or post-roll. +- Set `start` to the position in the asset, in seconds, on a `mediatime` channel — for example `"start": 600` — or use an event trigger for a pre-roll or post-roll. [Break detection](../concepts/marker-detection.mdx) can also create the breaks from the ad markers in the asset, with a [template](../concepts/templates.mdx) that holds the static assets. - The SDK receives all breaks when the session starts, and prepares each creative shortly before its break. - Enable [snapback](./vod.mdx#seeking-and-snapback) on breaks that viewers must not skip by seeking. diff --git a/ads/workflows/vast.mdx b/ads/workflows/vast.mdx index 53f4f567477b..8858ef0e46d1 100644 --- a/ads/workflows/vast.mdx +++ b/ads/workflows/vast.mdx @@ -80,7 +80,7 @@ The SDK requests the VAST tag on the device, shortly before the break starts. Ev ### VOD -- Set `start` to the position in the asset, in seconds, on a `mediatime` channel, or use an event trigger for a pre-roll, a post-roll, or a pause ad. +- Set `start` to the position in the asset, in seconds, on a `mediatime` channel, or use an event trigger for a pre-roll, a post-roll, or a pause ad. For breaks that [break detection](../concepts/marker-detection.mdx) creates from the ad markers in the asset, put the VAST asset in the rule's [template](../concepts/templates.mdx). - Viewers reach the breaks at different moments, so the requests to your ad server are spread over time. - Use a VAST tag that returns the right ad length for the break: the break's `duration` is the maximum, and the SDK returns to your content when it is reached. diff --git a/ads/workflows/vod.mdx b/ads/workflows/vod.mdx index 77c3e702bc90..92dc5d2265b5 100644 --- a/ads/workflows/vod.mdx +++ b/ads/workflows/vod.mdx @@ -31,7 +31,12 @@ The `streamType` and the `timebase` are set when you create the channel and cann ## Schedule breaks -On a VOD channel you schedule all breaks upfront. With the `mediatime` timebase, `start` is a number of seconds: +On a VOD channel, breaks are known before playback starts. Create them in one of two ways, or combine them: + +- **Scheduled** — create each break with its position in the asset, as below. +- **Detected** — add the asset as an [origin](../concepts/origins.mdx), and OptiView Ads turns the ad markers in the asset, such as SCTE-35 signals, into breaks at their positions. See [Break detection](../concepts/marker-detection.mdx). + +With the `mediatime` timebase, `start` is a number of seconds: ```bash curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//breaks' \ @@ -83,7 +88,6 @@ Your app integrates the SDK in the same way as for live: [Web](../player-integra The live-only features do not apply to VOD channels: -- **No break detection.** VOD channels do not monitor origins for ad markers; you schedule the breaks. - **No events.** [Events](../concepts/events.mdx) group the breaks of a live event; a VOD asset has no live moment to prepare for. - **No `pts` timebase.** Use `mediatime` or `wallclock`. From 3866cfffa219cf015f779db23b2a76460eb7ae31 Mon Sep 17 00:00:00 2001 From: Maarten Rimaux Date: Thu, 22 Oct 2026 22:05:41 +0200 Subject: [PATCH 4/7] Ads: organize ad workflows by use case (live, VOD), one self-contained page per ad source --- ads/concepts/breaks.mdx | 6 +- ads/concepts/channels.mdx | 4 +- ads/getting-started/index.mdx | 6 +- ads/how-to-guides/ad-tag-parameters.mdx | 10 +- ads/index.mdx | 11 +- ads/integrations/google/pod-serving.mdx | 18 +-- ads/integrations/index.mdx | 2 +- .../optiview-ads-sdk/android.mdx | 2 +- .../optiview-ads-sdk/index.mdx | 16 +- .../optiview-ads-sdk/ios.mdx | 2 +- .../optiview-ads-sdk/web.mdx | 4 +- ads/workflows/_shared/_gam-app.mdx | 20 +++ ads/workflows/_shared/_gam-ssai-session.mdx | 1 + ads/workflows/_shared/_gam-targeting.mdx | 6 + .../_shared/_gam-troubleshooting.mdx | 7 + ads/workflows/_shared/_gam-turn-off.mdx | 51 ++++++ .../_shared/_static-assets-formats.mdx | 5 + .../_shared/_static-assets-layouts.mdx | 11 ++ .../_static-assets-troubleshooting.mdx | 3 + ads/workflows/_shared/_vast-app.mdx | 20 +++ ads/workflows/_shared/_vast-layouts.mdx | 10 ++ ads/workflows/_shared/_vast-targeting.mdx | 12 ++ ads/workflows/_shared/_vast-tracking.mdx | 2 + .../_shared/_vast-troubleshooting.mdx | 8 + ads/workflows/google-ad-manager.mdx | 149 ------------------ ads/workflows/index.mdx | 24 +-- ads/workflows/live.mdx | 66 -------- ads/workflows/live/google-ad-manager.mdx | 106 +++++++++++++ ads/workflows/live/index.mdx | 66 ++++++++ ads/workflows/live/static-assets.mdx | 96 +++++++++++ ads/workflows/live/vast.mdx | 102 ++++++++++++ ads/workflows/static-assets.mdx | 105 ------------ ads/workflows/vast.mdx | 138 ---------------- ads/workflows/vod/google-ad-manager.mdx | 110 +++++++++++++ ads/workflows/{vod.mdx => vod/index.mdx} | 32 ++-- ads/workflows/vod/static-assets.mdx | 107 +++++++++++++ ads/workflows/vod/vast.mdx | 114 ++++++++++++++ sidebarsAds.ts | 17 +- 38 files changed, 942 insertions(+), 527 deletions(-) create mode 100644 ads/workflows/_shared/_gam-app.mdx create mode 100644 ads/workflows/_shared/_gam-ssai-session.mdx create mode 100644 ads/workflows/_shared/_gam-targeting.mdx create mode 100644 ads/workflows/_shared/_gam-troubleshooting.mdx create mode 100644 ads/workflows/_shared/_gam-turn-off.mdx create mode 100644 ads/workflows/_shared/_static-assets-formats.mdx create mode 100644 ads/workflows/_shared/_static-assets-layouts.mdx create mode 100644 ads/workflows/_shared/_static-assets-troubleshooting.mdx create mode 100644 ads/workflows/_shared/_vast-app.mdx create mode 100644 ads/workflows/_shared/_vast-layouts.mdx create mode 100644 ads/workflows/_shared/_vast-targeting.mdx create mode 100644 ads/workflows/_shared/_vast-tracking.mdx create mode 100644 ads/workflows/_shared/_vast-troubleshooting.mdx delete mode 100644 ads/workflows/google-ad-manager.mdx delete mode 100644 ads/workflows/live.mdx create mode 100644 ads/workflows/live/google-ad-manager.mdx create mode 100644 ads/workflows/live/index.mdx create mode 100644 ads/workflows/live/static-assets.mdx create mode 100644 ads/workflows/live/vast.mdx delete mode 100644 ads/workflows/static-assets.mdx delete mode 100644 ads/workflows/vast.mdx create mode 100644 ads/workflows/vod/google-ad-manager.mdx rename ads/workflows/{vod.mdx => vod/index.mdx} (65%) create mode 100644 ads/workflows/vod/static-assets.mdx create mode 100644 ads/workflows/vod/vast.mdx diff --git a/ads/concepts/breaks.mdx b/ads/concepts/breaks.mdx index 30851639c5b6..25e71368814d 100644 --- a/ads/concepts/breaks.mdx +++ b/ads/concepts/breaks.mdx @@ -25,7 +25,7 @@ The [timebase of the channel](./channels.mdx#timebase) defines how a break is sc - **`wallclock`** — the break's `start` is a UTC ISO 8601 timestamp (for example `"2026-07-16T12:15:00.000Z"`). Players match it against the wallclock timeline carried by the stream. `start` is optional on wallclock channels: omitting it creates a [cued break](#cued-breaks). - **`pts`** — the break's `start` is a non-negative number: a presentation timestamp on the encoder's timeline. `start` is required on PTS channels. -- **`mediatime`** — the break's `start` is a non-negative number of seconds from the start of the asset (for example `600`). `start` is required on `mediatime` channels, which are always [VOD](../workflows/vod.mdx) channels. +- **`mediatime`** — the break's `start` is a non-negative number of seconds from the start of the asset (for example `600`). `start` is required on `mediatime` channels, which are always [VOD](../workflows/vod/index.mdx) channels. `duration` is always required and is expressed in seconds. It is the **maximum** duration of the break. @@ -397,7 +397,7 @@ A `static` asset is a media resource the player retrieves directly — a video o } ``` -See [Static assets](../workflows/static-assets.mdx) for the supported creative formats and layouts in the OptiView Ads SDK. +See [Static assets](../workflows/live/static-assets.mdx) for the supported creative formats and layouts in the OptiView Ads SDK. #### VAST assets @@ -412,7 +412,7 @@ A `vast` asset points to an ad server that responds with a VAST XML document des } ``` -A `vast` asset can also carry `assetParameters`, which the player appends to the VAST tag URL as query parameters. See [VAST](../workflows/vast.mdx) for how the OptiView Ads SDK plays VAST tags, and the layouts they support. +A `vast` asset can also carry `assetParameters`, which the player appends to the VAST tag URL as query parameters. See [VAST](../workflows/live/vast.mdx) for how the OptiView Ads SDK plays VAST tags, and the layouts they support. #### Vendor assets diff --git a/ads/concepts/channels.mdx b/ads/concepts/channels.mdx index 3e03898883eb..7ec215a7cc32 100644 --- a/ads/concepts/channels.mdx +++ b/ads/concepts/channels.mdx @@ -34,8 +34,8 @@ These channel settings determine how break start times are interpreted and how b The `streamType` determines the use case of the channel: -- **`live`** (default) — a live stream. Players poll the Break Manifest continuously and receive breaks as they become relevant. See [Live](../workflows/live.mdx). -- **`vod`** — an on-demand asset. The Break Manifest lists all breaks upfront and players fetch it once. VOD channels have no events. See [VOD](../workflows/vod.mdx). +- **`live`** (default) — a live stream. Players poll the Break Manifest continuously and receive breaks as they become relevant. See [Live](../workflows/live/index.mdx). +- **`vod`** — an on-demand asset. The Break Manifest lists all breaks upfront and players fetch it once. VOD channels have no events. See [VOD](../workflows/vod/index.mdx). ### Timebase diff --git a/ads/getting-started/index.mdx b/ads/getting-started/index.mdx index 0e9c78f1c14f..bdc575e36143 100644 --- a/ads/getting-started/index.mdx +++ b/ads/getting-started/index.mdx @@ -10,7 +10,7 @@ import RebrandingNotice from '../callouts/_rebranding_notice.md'; -OptiView Ads monetizes your live stream with Server-Guided Ad Insertion (SGAI): you schedule ad breaks on a channel, and the player renders them on top of your content — without touching your media stream. This guide takes you from an empty organization to seeing your first ad break play out on your device. It uses a live channel; to monetize on-demand assets, the same steps apply to a [VOD channel](/ads/workflows/vod) with breaks at positions in the asset. +OptiView Ads monetizes your live stream with Server-Guided Ad Insertion (SGAI): you schedule ad breaks on a channel, and the player renders them on top of your content — without touching your media stream. This guide takes you from an empty organization to seeing your first ad break play out on your device. It uses a live channel; to monetize on-demand assets, the same steps apply to a [VOD channel](/ads/workflows/vod/) with breaks at positions in the asset. The examples use the US region (`https://us.ads.optiview.dolby.com` and `https://us.markers.optiview.dolby.com`). For the EU region, replace `us.` with `eu.`. @@ -88,7 +88,7 @@ This integration plays every [ad workflow](/ads/workflows/): static assets from ## 4. Schedule a break -A [break](/ads/concepts/breaks) describes an ad opportunity: when it starts, how long it lasts, and which ad experience plays. The simplest break plays a single full-screen video ad from your CDN, as a [static asset](/ads/workflows/static-assets). +A [break](/ads/concepts/breaks) describes an ad opportunity: when it starts, how long it lasts, and which ad experience plays. The simplest break plays a single full-screen video ad from your CDN, as a [static asset](/ads/workflows/live/static-assets). Dashboard: open the channel → **Breaks → Schedule now**. Or via the API, scheduling a 30-second break a few minutes from now: @@ -115,7 +115,7 @@ curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//bre Replace `` with an ISO 8601 UTC timestamp a few minutes in the future, for example `2026-01-01T12:00:00.000Z`, and the `uri` with the URL of an ad video on your CDN. -To let an ad server choose the ad instead, use a [VAST](/ads/workflows/vast) asset or [Google Ad Manager](/ads/workflows/google-ad-manager). +To let an ad server choose the ad instead, use a [VAST](/ads/workflows/live/vast) asset or [Google Ad Manager](/ads/workflows/live/google-ad-manager). Once you schedule breaks regularly, [templates](/ads/concepts/templates) let you preconfigure the break payload so scheduling becomes a one-liner. diff --git a/ads/how-to-guides/ad-tag-parameters.mdx b/ads/how-to-guides/ad-tag-parameters.mdx index 54f5f4119b3a..42dae32a92b7 100644 --- a/ads/how-to-guides/ad-tag-parameters.mdx +++ b/ads/how-to-guides/ad-tag-parameters.mdx @@ -6,9 +6,9 @@ sidebar_position: 3 When an ad server decides which ad fills a break, you can pass key-value parameters with the ad request to personalize the ads — for example the content genre, the placement type, or custom targeting values. In OptiView Ads, these parameters are called **`assetParameters`**. How they reach the ad server depends on the [ad workflow](../workflows/index.mdx): -- **[VAST](../workflows/vast.mdx):** the SDK appends them to the VAST tag URL as URL-encoded query parameters. -- **[Google Ad Manager](../workflows/google-ad-manager.mdx):** they are sent to Google as [ad tag parameters](https://support.google.com/admanager/answer/10678356) (`adTagParameters`). -- **[Static assets](../workflows/static-assets.mdx)** involve no ad request, so they do not use `assetParameters`. +- **[VAST](../workflows/live/vast.mdx):** the SDK appends them to the VAST tag URL as URL-encoded query parameters. +- **[Google Ad Manager](../workflows/live/google-ad-manager.mdx):** they are sent to Google as [ad tag parameters](https://support.google.com/admanager/answer/10678356) (`adTagParameters`). +- **[Static assets](../workflows/live/static-assets.mdx)** involve no ad request, so they do not use `assetParameters`. You can set `assetParameters` in two places: on the break in the **backend**, and in the **OptiView Ads SDK** on the client. @@ -153,8 +153,8 @@ ads.updateAssetParameters({ cust_params: 'sport=basketball' }); | Resource | Description | | -------------------------------------------------------------------- | ----------------------------------------------- | -| [VAST](../workflows/vast.mdx) | Playing VAST tags with the SDK. | -| [Google Ad Manager](../workflows/google-ad-manager.mdx) | Playing Google pods with the SDK. | +| [VAST](../workflows/live/vast.mdx) | Playing VAST tags with the SDK. | +| [Google Ad Manager](../workflows/live/google-ad-manager.mdx) | Playing Google pods with the SDK. | | [Google Pod Serving](../integrations/google/pod-serving.mdx) | Required Google parameters and pod decisioning. | | [Breaks](../concepts/breaks.mdx) | Scheduling breaks with VAST and vendor assets. | | [OptiView Ads SDK](../player-integration/optiview-ads-sdk/index.mdx) | Integrating the SDK with your player. | diff --git a/ads/index.mdx b/ads/index.mdx index 16a688a7fcf1..bce69653c365 100644 --- a/ads/index.mdx +++ b/ads/index.mdx @@ -21,13 +21,10 @@ By logically redistributing responsibilities in the advertisement workflow, Opti OptiView Ads models each live stream or VOD asset as a **channel**. A channel schedules **breaks**, or detects them from the ad markers in the stream or asset on its **origins**, and can use reusable **templates** for consistent ad experiences. It generates a **Break Manifest** for the OptiView Ads SDK to read and render. -| Workflow | What it is for | -| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------- | -| [Live](./workflows/live.mdx) | Linear channels and live events: breaks on the live timeline, scheduled, punched, or detected. | -| [VOD](./workflows/vod.mdx) | On-demand assets: pre-roll, mid-rolls at positions in the asset, post-roll, and pause ads. | -| [Static assets](./workflows/static-assets.mdx) | Play creatives from your own CDN, without an ad server. | -| [VAST](./workflows/vast.mdx) | Let your ad server, or a partner's, decide the ads through VAST tags. | -| [Google Ad Manager](./workflows/google-ad-manager.mdx) | Let Google Ad Manager 360 fill your breaks, server-guided (Pod Serving) or server-side (DAI). | +| Use case | What it is for | Ad sources | +| ---------------------------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Live](./workflows/live/index.mdx) | Linear channels and live events: breaks on the live timeline, scheduled, punched, or detected. | [Static assets](./workflows/live/static-assets.mdx), [Your ad server (VAST)](./workflows/live/vast.mdx), [Google Ad Manager](./workflows/live/google-ad-manager.mdx) | +| [VOD](./workflows/vod/index.mdx) | On-demand assets: pre-roll, mid-rolls at positions in the asset, post-roll, and pause ads. | [Static assets](./workflows/vod/static-assets.mdx), [Your ad server (VAST)](./workflows/vod/vast.mdx), [Google Ad Manager](./workflows/vod/google-ad-manager.mdx) | ` with the SDK release you want to use: +Then add the runtime to your app module. It brings in the core and SDK layers, Media3, and the Google IMA SDK (used to play [VAST](../../workflows/live/vast.mdx) and [Google Ad Manager](../../workflows/live/google-ad-manager.mdx) breaks) transitively; replace `` with the SDK release you want to use: ```kotlin dependencies { diff --git a/ads/player-integration/optiview-ads-sdk/index.mdx b/ads/player-integration/optiview-ads-sdk/index.mdx index babdbfb06f85..519cdac773dd 100644 --- a/ads/player-integration/optiview-ads-sdk/index.mdx +++ b/ads/player-integration/optiview-ads-sdk/index.mdx @@ -19,13 +19,13 @@ The SDK never talks to your player directly. All player interaction goes through ## Ad workflows -The SDK plays whatever the breaks on your channel carry, for [live](../../workflows/live.mdx) and [VOD](../../workflows/vod.mdx) channels alike, and picks the [delivery mode](../../workflows/index.mdx#hybrid-ad-insertion-sgai-and-ssai) — server-guided or server-side — that the channel sets for the device. Each [asset](../../concepts/breaks.mdx#asset-model) in a break uses one of three ad sources, and one channel can mix them: +The SDK plays whatever the breaks on your channel carry, for [live](../../workflows/live/index.mdx) and [VOD](../../workflows/vod/index.mdx) channels alike, and picks the [delivery mode](../../workflows/index.mdx#hybrid-ad-insertion-sgai-and-ssai) — server-guided or server-side — that the channel sets for the device. Each [asset](../../concepts/breaks.mdx#asset-model) in a break uses one of three ad sources, and one channel can mix them: -| Ad source | What the break carries | What your app needs on top of the platform integration | -| ---------------------------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- | -| [Static assets](../../workflows/static-assets.mdx) | Direct URLs to video or image creatives, hosted on your CDN. | Nothing. | -| [VAST](../../workflows/vast.mdx) | A VAST tag URL from your ad server. | On Web, Google's client-side IMA SDK (`ima3.js`) on the page. Nothing on Android, iOS, React Native. | -| [Google Ad Manager](../../workflows/google-ad-manager.mdx) | An ad pod decisioned by Google Ad Manager. | On Web, Google's IMA DAI SDK (`ima3_dai.js`) on the page. Nothing on Android, iOS, React Native. | +| Ad source | Live | VOD | What the break carries | What your app needs on top of the platform integration | +| --------------------- | -------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- | +| Static assets | [Live](../../workflows/live/static-assets.mdx) | [VOD](../../workflows/vod/static-assets.mdx) | Direct URLs to video or image creatives, hosted on your CDN. | Nothing. | +| Your ad server (VAST) | [Live](../../workflows/live/vast.mdx) | [VOD](../../workflows/vod/vast.mdx) | A VAST tag URL from your ad server. | On Web, Google's client-side IMA SDK (`ima3.js`) on the page. Nothing on Android, iOS, React Native. | +| Google Ad Manager | [Live](../../workflows/live/google-ad-manager.mdx) | [VOD](../../workflows/vod/google-ad-manager.mdx) | An ad pod decisioned by Google Ad Manager. | On Web, Google's IMA DAI SDK (`ima3_dai.js`) on the page. Nothing on Android, iOS, React Native. | The platform guides cover the integration that every workflow shares: installing the SDK, wrapping your player, and starting a session. The [Ad workflows](../../workflows/index.mdx) section describes how to set up breaks for each ad source on live and VOD, which layouts it supports, and how to troubleshoot it. @@ -36,7 +36,7 @@ Configuration is split into two levels: - **SDK configuration** is provided once, when you create the SDK instance. It describes your player and how ads should be presented. - **Session configuration** is provided per channel, when you start a monetization session. It identifies the channel to monetize. -Neither level holds ad server URLs or accounts. What to play, and where to fetch it from, comes from the channel's Break Manifest — including the delivery mode and the settings for [Google Ad Manager](../../workflows/google-ad-manager.mdx). +Neither level holds ad server URLs or accounts. What to play, and where to fetch it from, comes from the channel's Break Manifest — including the delivery mode and the settings for [Google Ad Manager](../../workflows/live/google-ad-manager.mdx). ### SDK configuration @@ -45,7 +45,7 @@ Neither level holds ad server URLs or accounts. What to play, and where to fetch | `player` | The adapter that wraps your content player. **Required.** | | `container` | The element or view in which the SDK renders ads, stacked above your content player. **Required.** | | `mode` | Optional. The ad insertion model: `sgai` (server-guided) or `ssai` (server-side, for streams where the ads are stitched into the media stream). By default the SDK uses the mode the channel's delivery rules set for the device, and `sgai` when there are none; set it only to override the channel. | -| `gam` | Optional. Google Ad Manager starts automatically when the Break Manifest carries a Google configuration; set `enabled` to `false` to keep Google out of a session. See [Google Ad Manager](../../workflows/google-ad-manager.mdx#turn-google-off-for-a-session). | +| `gam` | Optional. Google Ad Manager starts automatically when the Break Manifest carries a Google configuration; set `enabled` to `false` to keep Google out of a session. See [Google Ad Manager](../../workflows/live/google-ad-manager.mdx#turn-google-off-for-a-session). | | `debug` | Enables verbose logging during development. | The SDK also exposes optional presentation settings — such as ad preloading, break chaining, and tune-in behavior — with sensible defaults. The platform pages describe the platform-specific options. diff --git a/ads/player-integration/optiview-ads-sdk/ios.mdx b/ads/player-integration/optiview-ads-sdk/ios.mdx index 4b8549d52cf4..5ec916aff2d6 100644 --- a/ads/player-integration/optiview-ads-sdk/ios.mdx +++ b/ads/player-integration/optiview-ads-sdk/ios.mdx @@ -30,7 +30,7 @@ target 'MyApp' do end ``` -The runtime pod also brings in the Google IMA SDK, which the SDK uses to play [VAST](../../workflows/vast.mdx) and [Google Ad Manager](../../workflows/google-ad-manager.mdx) breaks. +The runtime pod also brings in the Google IMA SDK, which the SDK uses to play [VAST](../../workflows/live/vast.mdx) and [Google Ad Manager](../../workflows/live/google-ad-manager.mdx) breaks. ### Swift Package Manager diff --git a/ads/player-integration/optiview-ads-sdk/web.mdx b/ads/player-integration/optiview-ads-sdk/web.mdx index cdf7ae22fca3..b1d8fb4168b9 100644 --- a/ads/player-integration/optiview-ads-sdk/web.mdx +++ b/ads/player-integration/optiview-ads-sdk/web.mdx @@ -10,7 +10,7 @@ On Web, the OptiView Ads SDK works with any HLS-capable player through a player ## Prerequisites 1. Retrieve the channel's Break Manifest URL. See [Retrieving the required values](./index.mdx#retrieving-the-required-values). -2. Check which [ad workflows](./index.mdx#ad-workflows) your breaks use. Static assets need nothing extra; [VAST](../../workflows/vast.mdx) and [Google Ad Manager](../../workflows/google-ad-manager.mdx) each need a Google IMA script on the page. +2. Check which [ad workflows](./index.mdx#ad-workflows) your breaks use. Static assets need nothing extra; [VAST](../../workflows/live/vast.mdx) and [Google Ad Manager](../../workflows/live/google-ad-manager.mdx) each need a Google IMA script on the page. 3. Install the SDK together with the adapter for your player (see the player sections below). ## Integration @@ -33,7 +33,7 @@ await sdk.startSession({ From this point the SDK polls the [Break Manifest](../../concepts/break-manifest.mdx), schedules the breaks against your player's timeline, plays the ads, and reports the impressions. To verify the integration, schedule a break through the API or dashboard and confirm that it plays out. -This integration is the same for every ad workflow. If your breaks use VAST or Google Ad Manager, also load the Google IMA script that the [VAST](../../workflows/vast.mdx#what-your-app-needs) or [Google Ad Manager](../../workflows/google-ad-manager.mdx#what-your-app-needs) page lists. +This integration is the same for every ad workflow. If your breaks use VAST or Google Ad Manager, also load the Google IMA script that the [VAST](../../workflows/live/vast.mdx#what-your-app-needs) or [Google Ad Manager](../../workflows/live/google-ad-manager.mdx#what-your-app-needs) page lists. All configuration options, session settings, and ad events are documented in the [Web API reference](pathname:///ads/v2/api-reference/web/), starting from the [`OptiViewAds`](pathname:///ads/v2/api-reference/web/classes/OptiViewAds.html) class. diff --git a/ads/workflows/_shared/_gam-app.mdx b/ads/workflows/_shared/_gam-app.mdx new file mode 100644 index 000000000000..c3d562101afa --- /dev/null +++ b/ads/workflows/_shared/_gam-app.mdx @@ -0,0 +1,20 @@ +The SDK reads the Google settings — your network code and the channel's Google asset key — from the channel's Break Manifest, and starts the Google stream session automatically when the session starts. You do not configure them in the app, so your app and the backend always agree on which Google stream the ads belong to. + +| Platform | Requirement | +| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Web | Load Google's IMA DAI SDK on the page, before your application script (see below). | +| Android | Nothing extra: the SDK runtime includes the Google IMA SDK. | +| iOS and tvOS | Nothing extra: the runtime pod includes the Google IMA SDK. With Swift Package Manager, add the Google IMA packages as described in [iOS](../../player-integration/optiview-ads-sdk/ios.mdx#swift-package-manager). | +| React Native | Nothing extra: the native SDKs include the Google IMA SDK. | + +On Web, add the IMA DAI loader to your page: + +```html + +``` + +If your channel also has VAST breaks, load `ima3.js` as well; the two scripts work side by side. + +:::note[Upgrading from an earlier integration] +Earlier versions of this guide set a `networkCode` in the `gam` configuration and a `customAssetKey` in the session configuration. The SDK no longer accepts them: remove both, and the SDK takes the values from the Break Manifest. +::: diff --git a/ads/workflows/_shared/_gam-ssai-session.mdx b/ads/workflows/_shared/_gam-ssai-session.mdx new file mode 100644 index 000000000000..8593a2090931 --- /dev/null +++ b/ads/workflows/_shared/_gam-ssai-session.mdx @@ -0,0 +1 @@ +When the channel steers a device to SSAI, the SDK requests the stitched stream from Google and loads it into your content player instead of your original stream URL. Your app keeps the same integration and starts the session with the same Break Manifest URL. On Web, use a content player adapter that exposes its video element, such as the HLS.js, Shaka, or native video adapter. In a server-side session, the SDK still plays the [event-triggered breaks](../../concepts/breaks.mdx#event-based-triggers) — pre-roll, pause, and post-roll — on the device. diff --git a/ads/workflows/_shared/_gam-targeting.mdx b/ads/workflows/_shared/_gam-targeting.mdx new file mode 100644 index 000000000000..168a93e154c6 --- /dev/null +++ b/ads/workflows/_shared/_gam-targeting.mdx @@ -0,0 +1,6 @@ +For Google, `assetParameters` are sent as Google [ad tag parameters](https://support.google.com/admanager/answer/10678356) (`adTagParameters`). As a rule of thumb: + +- Set the values that describe your content on the break, such as `description_url` and `plcmt`. See [Required Google parameters](../../integrations/google/pod-serving.mdx#required-google-parameters). +- Set the values that depend on the playback environment in the SDK, such as `vpa` and `vpmute` and, in apps, the [device and app identity parameters](../../integrations/google/pod-serving.mdx#additional-parameters-for-app-inventory). + +When the same key is set in both places, the value on the break wins. See [Ad targeting parameters](../../how-to-guides/ad-tag-parameters.mdx) for the merge rules and platform examples. diff --git a/ads/workflows/_shared/_gam-troubleshooting.mdx b/ads/workflows/_shared/_gam-troubleshooting.mdx new file mode 100644 index 000000000000..86369507796a --- /dev/null +++ b/ads/workflows/_shared/_gam-troubleshooting.mdx @@ -0,0 +1,7 @@ +| Diagnostic | What it means | What to do | +| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `DA-GAM-CONFIG-RESOLVED` | Informational: the Google stream session uses the network code and asset key in the diagnostic. | Check that they match your Google stream. | +| `DA-GAM-CONFIG-MISSING` | The Break Manifest carries Google breaks but no usable Google configuration, or Google is turned off with `gam` `enabled: false`. | Check that the channel is connected to Google, or remove the opt-out. | +| `DA-GAM-SESSION-FAILED` | The Google stream session could not be started. | On Web, load `ima3_dai.js` on the page. Otherwise, check the error message in the diagnostic. | + +Breaks that fail in the backend, for example because Google could not decision them in time, end up in the `ERROR` state and never reach the SDK. See [Troubleshooting](../../integrations/google/pod-serving.mdx#troubleshooting) on the Google Pod Serving integration page for the possible reasons. diff --git a/ads/workflows/_shared/_gam-turn-off.mdx b/ads/workflows/_shared/_gam-turn-off.mdx new file mode 100644 index 000000000000..4459002a3ec9 --- /dev/null +++ b/ads/workflows/_shared/_gam-turn-off.mdx @@ -0,0 +1,51 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +To keep Google out of a session — for example until the viewer gives consent, or in a build that must not contact Google — set `enabled` to `false` in the `gam` configuration. The SDK then skips the Google breaks in that session and reports `DA-GAM-CONFIG-MISSING`. + + + + +```typescript +const sdk = new OptiViewAds({ + player: new THEOplayerAdapter(player, container), + container: document.getElementById('container'), + gam: { enabled: false }, +}); +``` + + + + +```kotlin +val sdk = OptiViewAds( + config = OptiViewAdsConfig( + player = THEOplayerAdapter(theoPlayerView.player), + gam = GamConfig(enabled = false), + ), + renderer = OverlayAdRenderer(adContainer), +) +``` + + + + +```swift +let sdk = OptiViewAds( + config: OptiViewAdsConfig( + player: THEOplayerAdapter(player: theoplayer), + gam: GamConfig(enabled: false) + ), + renderer: OverlayAdRenderer(container: adContainer) +) +``` + + + + +```typescript +const ads = createOptiViewAds(player, { gam: { enabled: false } }); +``` + + + diff --git a/ads/workflows/_shared/_static-assets-formats.mdx b/ads/workflows/_shared/_static-assets-formats.mdx new file mode 100644 index 000000000000..9b75a3f4ae8a --- /dev/null +++ b/ads/workflows/_shared/_static-assets-formats.mdx @@ -0,0 +1,5 @@ +- **HLS (`.m3u8`)** is the recommended format for video creatives on every platform. On connected TVs in particular, the SDK can load an HLS creative ahead of the break, so the ad starts faster. +- **Progressive MP4** also works. On Web, the SDK plays MP4 creatives through the browser's own video element. +- **Images** are used for overlays, companions, L-shape backdrops, and pause ads. + +Set `mimeType` on the asset when you know it. The SDK then knows upfront how to play the creative, instead of having to find out, which makes ad preparation faster. diff --git a/ads/workflows/_shared/_static-assets-layouts.mdx b/ads/workflows/_shared/_static-assets-layouts.mdx new file mode 100644 index 000000000000..962933f4c04b --- /dev/null +++ b/ads/workflows/_shared/_static-assets-layouts.mdx @@ -0,0 +1,11 @@ +Static assets work in every [layout](../../concepts/breaks.mdx#layouts) and as [pause ads](../../concepts/breaks.mdx#pause): + +| Layout | Static asset | +| --------------------- | ---------------------------------------------------------------------------------------- | +| `single` | A video that replaces the content. | +| `double`, `lshape_ad` | A video, with an image or video `companion` that fills the background. | +| `lshape_content` | An image that fills the L-shaped backdrop while your content keeps playing. | +| `overlay` | An image or video on top of your content. | +| Pause ad | An image, or a progressive MP4 video that plays muted, shown while the viewer is paused. | + +An image stays on screen for the asset's `duration`, or for the break's `duration` when the asset has none. diff --git a/ads/workflows/_shared/_static-assets-troubleshooting.mdx b/ads/workflows/_shared/_static-assets-troubleshooting.mdx new file mode 100644 index 000000000000..287f0377da19 --- /dev/null +++ b/ads/workflows/_shared/_static-assets-troubleshooting.mdx @@ -0,0 +1,3 @@ +- **The break does not play.** Check that the channel's [Break Manifest](../../concepts/break-manifest.mdx) contains the break, and that the creative URL is publicly reachable. +- **Web: the creative fails to load.** The SDK downloads HLS creatives with HTTP requests from your page, so your CDN must allow cross-origin requests (CORS) from your app's origin. +- **A creative cannot be played.** The SDK emits an `aderror` event for the asset, continues with the next asset in the break if there is one, and otherwise returns to your content. diff --git a/ads/workflows/_shared/_vast-app.mdx b/ads/workflows/_shared/_vast-app.mdx new file mode 100644 index 000000000000..8c6b141c9d2e --- /dev/null +++ b/ads/workflows/_shared/_vast-app.mdx @@ -0,0 +1,20 @@ +The SDK requests and plays VAST tags on the device, through Google's client-side IMA SDK. IMA processes the VAST response — it follows wrappers, picks a media file, and fires the tracking URLs. IMA works with any VAST-compliant ad server: you do not need a Google Ad Manager account, although a Google Ad Manager VAST tag works too. + +| Platform | Requirement | +| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Web | Load Google's client-side IMA SDK on the page, before your application script (see below). | +| Android | Nothing extra: the SDK runtime includes the Google IMA SDK. | +| iOS and tvOS | Nothing extra: the runtime pod includes the Google IMA SDK. With Swift Package Manager, add the Google IMA packages as described in [iOS](../../player-integration/optiview-ads-sdk/ios.mdx#swift-package-manager). | +| React Native | Nothing extra: the native SDKs include the Google IMA SDK. | + +On Web, add the IMA loader to your page: + +```html + +``` + +Without it, the SDK cannot play VAST breaks: it reports `DA-VAST-IMA-SDK-MISSING` and returns to your content. If your channel also has Google Ad Manager breaks, load `ima3_dai.js` as well; the two scripts work side by side. + +:::caution[Web: include an MP4 media file] +The IMA SDK for HTML5 plays the ad through the browser's own video element, which cannot play HLS outside Safari. Make sure your VAST responses include a progressive MP4 media file, or the ad fails to play in Chrome, Edge, and Firefox. +::: diff --git a/ads/workflows/_shared/_vast-layouts.mdx b/ads/workflows/_shared/_vast-layouts.mdx new file mode 100644 index 000000000000..4234a9cf1271 --- /dev/null +++ b/ads/workflows/_shared/_vast-layouts.mdx @@ -0,0 +1,10 @@ +VAST describes a linear (video) ad, so VAST assets work in the layouts where an ad video plays: + +| Layout | VAST asset | +| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `single` | Supported. | +| `double`, `lshape_ad` | Supported. The VAST ad plays in the ad box, and the asset's `companion` fills the background. | +| `lshape_content`, `overlay` | Not supported. The SDK does not play the asset and reports `DA-VAST-UNSUPPORTED-FORMAT`. Use a static asset instead. | +| Pause ad | Supported. The SDK reads the image from the VAST companion ads, or a progressive MP4 from the linear ad, and fires its impression tracking when shown. | + +VAST breaks play in server-guided (SGAI) sessions only. diff --git a/ads/workflows/_shared/_vast-targeting.mdx b/ads/workflows/_shared/_vast-targeting.mdx new file mode 100644 index 000000000000..7a35c0bc7c27 --- /dev/null +++ b/ads/workflows/_shared/_vast-targeting.mdx @@ -0,0 +1,12 @@ +To personalize the ad request, add `assetParameters`. The SDK appends them to the VAST tag URL as URL-encoded query parameters when it requests the tag. For the break above, with a session-level parameter `device_id` set in the SDK, the request becomes: + +```text +https://adserver.example.com/vast?slot=midroll&content_genre=sports&device_id=abc123 +``` + +Set the parameters in one of two places: + +- **On the break**, for values that are the same for every viewer, such as the content genre. +- **In the SDK**, with `assetParameters` in the session configuration or `updateAssetParameters()`, for values that depend on the viewer or the device. + +When the same key is set in both places, the value on the break wins. Parameter values can also contain macros, such as `$OPTIVIEW_PLAYER_WIDTH$`, that the SDK fills in when it builds the request. See [Ad targeting parameters](../../how-to-guides/ad-tag-parameters.mdx) for the merge rules, the macros, and platform examples. diff --git a/ads/workflows/_shared/_vast-tracking.mdx b/ads/workflows/_shared/_vast-tracking.mdx new file mode 100644 index 000000000000..731db36eb40d --- /dev/null +++ b/ads/workflows/_shared/_vast-tracking.mdx @@ -0,0 +1,2 @@ +- IMA fires the tracking URLs in the VAST response, such as impressions, quartiles, and clicks, so the ad server counts the ad. +- The SDK reports an OptiView Ads [impression](../../how-to-guides/ad-impressions.md) for the break, and emits the same ad events as for any other break. diff --git a/ads/workflows/_shared/_vast-troubleshooting.mdx b/ads/workflows/_shared/_vast-troubleshooting.mdx new file mode 100644 index 000000000000..8e9ef8295aec --- /dev/null +++ b/ads/workflows/_shared/_vast-troubleshooting.mdx @@ -0,0 +1,8 @@ +VAST failures never block your content: the SDK emits an `aderror` event, reports a diagnostic, and returns to the content. + +| Diagnostic | What it means | What to do | +| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `DA-VAST-IMA-SDK-MISSING` | Google's client-side IMA SDK is not available. | On Web, load `ima3.js` on the page. | +| `DA-VAST-IMA-ERROR` | IMA could not load, parse, or play the VAST response — for example an unreachable tag, an empty response, or no playable media file. | Test the tag in Google's [VAST Inspector](https://googleads.github.io/googleads-ima-html5/vsi/). On Web, make sure the response includes a progressive MP4 media file. | +| `DA-VAST-UNSUPPORTED-FORMAT` | The VAST asset is in an `overlay` or `lshape_content` break. | Use the `single`, `double`, or `lshape_ad` layout, or a static asset. | +| `DA-VAST-SSAI-UNSUPPORTED` | The VAST asset is in a server-side (SSAI) session. | Play VAST breaks in a server-guided (`sgai`) session. | diff --git a/ads/workflows/google-ad-manager.mdx b/ads/workflows/google-ad-manager.mdx deleted file mode 100644 index 2708a25ca597..000000000000 --- a/ads/workflows/google-ad-manager.mdx +++ /dev/null @@ -1,149 +0,0 @@ ---- -sidebar_position: 5 -sidebar_label: Google Ad Manager -description: Let Google Ad Manager 360 fill your breaks, server-guided or server-side, on live and VOD. ---- - -# Google Ad Manager - -With Google Ad Manager 360, Google decides which ads fill each break. OptiView Ads announces the breaks to Google, Google assembles the ads into a pod, and the pod plays when the break starts. Use this workflow when you sell your inventory through Google Ad Manager 360, and to reach platforms that need server-side ad insertion. - -Google Ad Manager is the ad source that supports both delivery modes of the [hybrid platform](./index.mdx#hybrid-ad-insertion-sgai-and-ssai): - -| | Server-guided (SGAI) | Server-side (SSAI) | -| ---- | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -| Live | [Google Pod Serving](../integrations/google/pod-serving.mdx): the SDK inserts Google's ad pods into your stream. | [Google DAI](../integrations/google/dai.mdx): Google stitches the ads into the stream for the player. | -| VOD | Google pod serving for on-demand assets: the SDK inserts Google's ad pods at the break positions of the asset. | Google DAI for on-demand assets: Google stitches the ads into the asset for the player. | - -Prefer SGAI on every platform that runs the OptiView Ads SDK: the media stream stays untouched, and the advanced [layouts](../concepts/breaks.mdx#layouts) such as double box and L-shape are available. Use SSAI for platforms where a client-side SDK is not an option, such as Roku and older connected TV devices. One channel can serve both, [per device](./index.mdx#hybrid-ad-insertion-sgai-and-ssai). - -## Before you start - -- The [Google Ad Manager prerequisites](../integrations/google/index.mdx) — network code and service account — are in place for your organization. -- Your channel is connected to Google: with the custom asset key of your Google stream for [Google Pod Serving](../integrations/google/pod-serving.mdx#configure-your-channel), and with the DAI asset key for [Google DAI](../integrations/google/dai.mdx#configure-your-channel). - -## Live and VOD - -### Live - -- **SGAI** — OptiView Ads announces each break to Google ahead of its start, within the [look-forward time](../integrations/google/index.mdx#look-forward-time), so Google can decision the pod in time. Breaks can be scheduled, [punched](../concepts/breaks.mdx#break-punching), or created by [break detection](../concepts/marker-detection.mdx). See [Google Pod Serving](../integrations/google/pod-serving.mdx) for the Google Ad Manager setup and how to schedule a pod break. -- **SSAI** — the Dolby Ads Proxy inserts the break cues into the stream that Google DAI reads, and Google stitches the decisioned ads into the stream that viewers receive. See [Google DAI](../integrations/google/dai.mdx). -- Allow for the [decisioning margin](../integrations/google/index.mdx#decisioning-margin): a Google break must be created at least a few seconds before its start. - -### VOD - -- **SGAI** — schedule the Google breaks at their positions in the asset, in seconds, on a `mediatime` channel, or let [break detection](../concepts/marker-detection.mdx) create them from the ad markers in the asset. Google decisions the pods when the viewer's session starts, and the SDK inserts them at the break positions. -- **SSAI** — Google stitches the ads for the asset's breaks into the on-demand stream, and the player plays the stitched asset. -- Because every viewer watches from their own position, ads are decisioned per viewer session rather than per break moment: there is no audience-wide peak at a break start. - -Contact your Dolby OptiView account team to enable Google Ad Manager on your VOD channels. - -## What your app needs - -The SDK reads the Google settings — your network code and the channel's Google asset key — from the channel's Break Manifest, and starts the Google stream session automatically when the session starts. You do not configure them in the app, so your app and the backend always agree on which Google stream the ads belong to. - -| Platform | Requirement | -| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Web | Load Google's IMA DAI SDK on the page, before your application script (see below). | -| Android | Nothing extra: the SDK runtime includes the Google IMA SDK. | -| iOS and tvOS | Nothing extra: the runtime pod includes the Google IMA SDK. With Swift Package Manager, add the Google IMA packages as described in [iOS](../player-integration/optiview-ads-sdk/ios.mdx#swift-package-manager). | -| React Native | Nothing extra: the native SDKs include the Google IMA SDK. | - -On Web, add the IMA DAI loader to your page: - -```html - -``` - -If your channel also uses [VAST](./vast.mdx) breaks, load `ima3.js` as well; the two scripts work side by side. - -### Server-side sessions - -When the channel steers a device to SSAI, the SDK requests the stitched stream from Google and loads it into your content player instead of your original stream URL. Your app keeps the same integration and starts the session with the same Break Manifest URL. On Web, use a content player adapter that exposes its video element, such as the HLS.js, Shaka, or native video adapter. In a server-side session, the SDK still plays the [event-triggered breaks](../concepts/breaks.mdx#event-based-triggers) — pre-roll, pause, and post-roll — on the device. - -:::note[Upgrading from an earlier integration] -Earlier versions of this guide set a `networkCode` in the `gam` configuration and a `customAssetKey` in the session configuration. The SDK no longer accepts them: remove both, and the SDK takes the values from the Break Manifest. -::: - -### Turn Google off for a session - -To keep Google out of a session — for example until the viewer gives consent, or in a build that must not contact Google — set `enabled` to `false` in the `gam` configuration. The SDK then skips the Google breaks in that session and reports `DA-GAM-CONFIG-MISSING`. - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - - - - -```typescript -const sdk = new OptiViewAds({ - player: new THEOplayerAdapter(player, container), - container: document.getElementById('container'), - gam: { enabled: false }, -}); -``` - - - - -```kotlin -val sdk = OptiViewAds( - config = OptiViewAdsConfig( - player = THEOplayerAdapter(theoPlayerView.player), - gam = GamConfig(enabled = false), - ), - renderer = OverlayAdRenderer(adContainer), -) -``` - - - - -```swift -let sdk = OptiViewAds( - config: OptiViewAdsConfig( - player: THEOplayerAdapter(player: theoplayer), - gam: GamConfig(enabled: false) - ), - renderer: OverlayAdRenderer(container: adContainer) -) -``` - - - - -```typescript -const ads = createOptiViewAds(player, { gam: { enabled: false } }); -``` - - - - -## Ad targeting parameters - -For Google, `assetParameters` are sent as Google [ad tag parameters](https://support.google.com/admanager/answer/10678356) (`adTagParameters`). As a rule of thumb: - -- Set the values that describe your content on the break, such as `description_url` and `plcmt`. See [Required Google parameters](../integrations/google/pod-serving.mdx#required-google-parameters). -- Set the values that depend on the playback environment in the SDK, such as `vpa` and `vpmute` and, in apps, the [device and app identity parameters](../integrations/google/pod-serving.mdx#additional-parameters-for-app-inventory). - -When the same key is set in both places, the value on the break wins. See [Ad targeting parameters](../how-to-guides/ad-tag-parameters.mdx) for the merge rules and platform examples. - -## Troubleshooting - -| Diagnostic | What it means | What to do | -| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -| `DA-GAM-CONFIG-RESOLVED` | Informational: the Google stream session uses the network code and custom asset key in the diagnostic. | Check that they match your Google live stream. | -| `DA-GAM-CONFIG-MISSING` | The Break Manifest carries Google breaks but no usable Google configuration, or Google is turned off with `gam` `enabled: false`. | Check that the channel is configured for Google Pod Serving, or remove the opt-out. | -| `DA-GAM-SESSION-FAILED` | The Google stream session could not be started. | On Web, load `ima3_dai.js` on the page. Otherwise, check the error message in the diagnostic. | - -Breaks that fail in the backend, for example because Google could not decision them in time, end up in the `ERROR` state and never reach the SDK. See [Troubleshooting](../integrations/google/pod-serving.mdx#troubleshooting) on the Google Pod Serving integration page. - -## Related resources - -| Resource | Description | -| ------------------------------------------------------------------------ | --------------------------------------------------------------------- | -| [Google Ad Manager](../integrations/google/index.mdx) | Organization-level prerequisites: network code and service account. | -| [Google Pod Serving integration](../integrations/google/pod-serving.mdx) | Google Ad Manager setup, channel configuration, and pod breaks. | -| [Google DAI integration](../integrations/google/dai.mdx) | Server-side insertion: proxy, live stream, and channel configuration. | -| [Ad targeting parameters](../how-to-guides/ad-tag-parameters.mdx) | Passing ad tag parameters to Google. | -| [VAST](./vast.mdx) | Play VAST tags from your own ad server, without Google Ad Manager. | diff --git a/ads/workflows/index.mdx b/ads/workflows/index.mdx index c9efdd055801..3bb2e74c654f 100644 --- a/ads/workflows/index.mdx +++ b/ads/workflows/index.mdx @@ -6,12 +6,14 @@ description: How OptiView Ads monetizes live and VOD content with static assets, # Ad workflows -OptiView Ads is a **hybrid ad insertion platform**: the same channel and the same breaks can be delivered server-guided (SGAI) or server-side (SSAI), for live streams and for video-on-demand (VOD) assets. This page explains the three choices that together make up your ad workflow: +OptiView Ads is a **hybrid ad insertion platform**: the same channel and the same breaks can be delivered server-guided (SGAI) or server-side (SSAI), for live streams and for video-on-demand (VOD) assets. Your ad workflow comes down to three choices: -1. **Use case** — are you monetizing a [live stream](./live.mdx) or a [VOD asset](./vod.mdx)? -2. **Ad source** — where do the ads come from: [static assets](./static-assets.mdx) from your CDN, [VAST](./vast.mdx) tags from your ad server, or [Google Ad Manager](./google-ad-manager.mdx)? +1. **Use case** — are you monetizing a [live stream](./live/index.mdx) or a [VOD asset](./vod/index.mdx)? +2. **Ad source** — where do the ads come from: static assets from your CDN, your ad server through VAST tags, or Google Ad Manager? 3. **Delivery mode** — does the player insert the ads (SGAI), or are they stitched into the stream (SSAI)? +Pick your use case and ad source in the [table below](#supported-workflows): each combination has its own page with everything you need to set it up. + ## Hybrid ad insertion: SGAI and SSAI | Delivery mode | How it works | Use it for | @@ -23,13 +25,13 @@ Both modes share the same model: you create a [channel](../concepts/channels.mdx A channel can **steer the delivery mode per device**: for example SGAI on web and mobile, and SSAI on a specific connected TV platform. The Break Manifest then carries the delivery rules, and the SDK picks the mode for the device it runs on when the session starts. In SSAI mode, the SDK still plays the [event-triggered breaks](../concepts/breaks.mdx#event-based-triggers) — pre-roll, pause, and post-roll — on the device, because they depend on what the individual viewer does. -SSAI is available with [Google Ad Manager](./google-ad-manager.mdx), through Google DAI. Static assets and VAST tags are always played server-guided. +SSAI is available with Google Ad Manager, through Google DAI. Static assets and VAST tags are always played server-guided. ## Live and VOD Live and VOD are different use cases, and a channel is created for one of them. The difference is mainly in how breaks are placed on the timeline and how players receive them: -| | [Live](./live.mdx) | [VOD](./vod.mdx) | +| | [Live](./live/index.mdx) | [VOD](./vod/index.mdx) | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | | Channel | `streamType: "live"` (the default) | `streamType: "vod"` | | Break start | A moment on the live timeline: a UTC timestamp (`wallclock`) or a presentation timestamp (`pts`) | A position in the asset: seconds from the start (`mediatime`), or a UTC timestamp (`wallclock`) | @@ -41,16 +43,16 @@ Live and VOD are different use cases, and a channel is created for one of them. Every ad source works for both live and VOD. One channel, and even one break, can mix ad sources. -| Ad source | What the break carries | Live | VOD | What your app needs | -| -------------------------------------------- | ----------------------------------------------------- | ----------- | ----------- | -------------------------------------------------------------------------- | -| [Static assets](./static-assets.mdx) | Direct URLs to video or image creatives on your CDN. | SGAI | SGAI | Nothing beyond the SDK integration. | -| [VAST](./vast.mdx) | A VAST tag URL on your ad server, or an advertiser's. | SGAI | SGAI | On Web, Google's client-side IMA SDK (`ima3.js`). | -| [Google Ad Manager](./google-ad-manager.mdx) | An ad pod decisioned by Google Ad Manager 360. | SGAI + SSAI | SGAI + SSAI | On Web, Google's IMA DAI SDK (`ima3_dai.js`). Google Ad Manager 360 setup. | +| Ad source | What the break carries | Live | VOD | What your app needs | +| --------------------- | ----------------------------------------------------- | ------------------------------------------- | ------------------------------------------ | -------------------------------------------------------------------------- | +| Static assets | Direct URLs to video or image creatives on your CDN. | [SGAI](./live/static-assets.mdx) | [SGAI](./vod/static-assets.mdx) | Nothing beyond the SDK integration. | +| Your ad server (VAST) | A VAST tag URL on your ad server, or an advertiser's. | [SGAI](./live/vast.mdx) | [SGAI](./vod/vast.mdx) | On Web, Google's client-side IMA SDK (`ima3.js`). | +| Google Ad Manager | An ad pod decisioned by Google Ad Manager 360. | [SGAI + SSAI](./live/google-ad-manager.mdx) | [SGAI + SSAI](./vod/google-ad-manager.mdx) | On Web, Google's IMA DAI SDK (`ima3_dai.js`). Google Ad Manager 360 setup. | ### Which ad source should I use? - **Static assets** when you know which creative to show: direct-sold campaigns, sponsorships, promos, branded overlays. No ad server is involved. -- **VAST** when your own ad server, or a partner's, decides which ad plays. Any VAST-compliant ad server works, Google Ad Manager tags included. +- **Your ad server (VAST)** when your own ad server, or a partner's, decides which ad plays. Any VAST-compliant ad server works, Google Ad Manager tags included. - **Google Ad Manager** when you sell your inventory through Google Ad Manager 360 and want Google to fill complete ad pods, or need server-side insertion through Google DAI. ## Next steps diff --git a/ads/workflows/live.mdx b/ads/workflows/live.mdx deleted file mode 100644 index a3a8558c5a30..000000000000 --- a/ads/workflows/live.mdx +++ /dev/null @@ -1,66 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: Live -description: Monetize a live stream with OptiView Ads. ---- - -# Live - -A live channel monetizes a linear stream or a live event. Breaks are placed on the live timeline, and players watching the stream — at the live edge or behind it in the DVR window — receive them through the channel's [Break Manifest](../concepts/break-manifest.mdx). - -## Set up a live channel - -A channel is live by default. Choose the [timebase](../concepts/channels.mdx#timebase) that matches the timing information in your stream: - -- **`wallclock`** — breaks start at a UTC timestamp, matched against the stream's own wallclock timeline (`EXT-X-PROGRAM-DATE-TIME` in HLS, the segment timeline in DASH). This is the recommended timebase. -- **`pts`** — breaks start at a presentation timestamp on the encoder's timeline. - -```bash -curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels' \ - -u "$ADS_API_KEY:$ADS_API_SECRET" \ - -H 'Content-Type: application/json' \ - -H 'X-Org-ID: ' \ - -d '{ - "name": "Sports main", - "streamType": "live", - "timebase": "wallclock" - }' -``` - -The [DVR window](../concepts/channels.mdx#dvr-window), [live offset](../concepts/channels.mdx#live-offset), and [ad prefetch window](../concepts/channels.mdx#ad-prefetch-window) settings tune which breaks the Break Manifest contains at any moment. - -## How breaks are created - -On a live stream, breaks can be created in three ways, and you can combine them on one channel: - -- **Scheduled** — create a break with a start time, ahead of time or on the spot. See [Scheduling](../concepts/breaks.mdx#scheduling). -- **Punched** — prepare a break without a start time, and fire it when the moment comes, for example from your production control room. See [Break punching](../concepts/breaks.mdx#break-punching). -- **Detected** — add your stream as an [origin](../concepts/origins.mdx), and OptiView Ads turns the ad markers in the stream, such as SCTE-35 signals, into breaks. See [Break detection](../concepts/marker-detection.mdx). This replaces the ad breaks already in your stream (Dynamic Ad Replacement). - -[Events](../concepts/events.mdx) let you prepare the breaks of a live event, such as a match or a show, upfront. [Templates](../concepts/templates.mdx) store a break configuration once, so scheduling becomes a one-liner. - -Besides breaks on the timeline, a live channel can carry [event-triggered breaks](../concepts/breaks.mdx#event-based-triggers): a pre-roll when the viewer starts watching, a pause ad, and a post-roll. - -## How players receive the breaks - -The SDK polls the Break Manifest during the whole session. A break appears in the manifest shortly before it starts — within the ad prefetch window — so the SDK can prepare the ads, and it stays there while viewers in the DVR window can still reach it. Changes to a break, such as an earlier end, reach the players on the next poll. - -## Delivery modes - -Live channels support both delivery modes of the [hybrid platform](./index.mdx#hybrid-ad-insertion-sgai-and-ssai): - -| Ad source | SGAI | SSAI | -| -------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------ | -| [Static assets](./static-assets.mdx) | Yes | No | -| [VAST](./vast.mdx) | Yes | No | -| [Google Ad Manager](./google-ad-manager.mdx) | Yes, with [Google Pod Serving](../integrations/google/pod-serving.mdx) | Yes, with [Google DAI](../integrations/google/dai.mdx) | - -## Related resources - -| Resource | Description | -| --------------------------------------------------- | ----------------------------------------------------------- | -| [Getting started](../getting-started/index.mdx) | Create a live channel and play your first break end to end. | -| [Channels](../concepts/channels.mdx) | Timebase, DVR window, live offset, and prefetch settings. | -| [Breaks](../concepts/breaks.mdx) | Scheduling, punching, layouts, and the asset model. | -| [Break detection](../concepts/marker-detection.mdx) | Turn the ad markers in your stream into breaks. | -| [VOD](./vod.mdx) | Monetize on-demand assets instead. | diff --git a/ads/workflows/live/google-ad-manager.mdx b/ads/workflows/live/google-ad-manager.mdx new file mode 100644 index 000000000000..dd5d4e9bc08b --- /dev/null +++ b/ads/workflows/live/google-ad-manager.mdx @@ -0,0 +1,106 @@ +--- +sidebar_position: 3 +sidebar_label: Google Ad Manager +description: Let Google Ad Manager 360 fill the breaks of a live stream, server-guided (Pod Serving) or server-side (DAI). +--- + +# Google Ad Manager on live + +import AppNeeds from '../_shared/_gam-app.mdx'; +import SsaiSession from '../_shared/_gam-ssai-session.mdx'; +import TurnOff from '../_shared/_gam-turn-off.mdx'; +import Targeting from '../_shared/_gam-targeting.mdx'; +import Troubleshooting from '../_shared/_gam-troubleshooting.mdx'; + +With Google Ad Manager 360, Google decides which ads fill each break of your live stream. OptiView Ads announces the breaks to Google ahead of time, Google assembles the ads into a pod, and the pod plays when the break starts. Use this workflow when you sell your inventory through Google Ad Manager 360, and to reach platforms that need server-side ad insertion. + +| | Google Ad Manager on live | +| -------------- | ----------------------------------------------------------------------------------------- | +| Delivery mode | Server-guided with Google Pod Serving (SGAI), server-side with Google DAI (SSAI), or both | +| Ad decisioning | Google Ad Manager, ahead of the break | +| Break creation | Scheduled, punched, or detected from the ad markers in your stream | +| Your app needs | The OptiView Ads SDK; on Web also Google's IMA DAI SDK | + +## Choose a delivery mode + +| Delivery mode | How it works | Use it for | +| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | +| [Google Pod Serving](../../integrations/google/pod-serving.mdx) (SGAI) | Google decisions the pod; the SDK inserts it into your untouched stream, guided by the Break Manifest. | Web, mobile, and most connected TV apps. Required for the double box, L-shape, and overlay layouts. | +| [Google DAI](../../integrations/google/dai.mdx) (SSAI) | The Dolby Ads Proxy inserts the break cues into the stream Google reads; Google stitches the ads into the stream for viewers. | Platforms where a client-side SDK is not an option, such as Roku and older connected TV devices. | + +One channel can serve both: the channel steers the [delivery mode per device](../index.mdx#hybrid-ad-insertion-sgai-and-ssai), and the SDK picks it up from the Break Manifest. + +## Before you start + +- The [Google Ad Manager prerequisites](../../integrations/google/index.mdx) — network code and service account — are in place for your organization. +- A [live channel](./index.mdx#set-up-a-live-channel), connected to Google: with the custom asset key of your Google live stream for [Google Pod Serving](../../integrations/google/pod-serving.mdx#configure-your-channel), and with the DAI asset key for [Google DAI](../../integrations/google/dai.mdx#configure-your-channel). +- The OptiView Ads SDK in your app: [Web](../../player-integration/optiview-ads-sdk/web.mdx), [Android](../../player-integration/optiview-ads-sdk/android.mdx), [iOS](../../player-integration/optiview-ads-sdk/ios.mdx), or [React Native](../../player-integration/optiview-ads-sdk/react-native.mdx). + +## Schedule a break + +A Google break carries a [vendor asset](../../concepts/breaks.mdx#vendor-assets) with `vendor` set to `gam` and `vendorParameters.type` set to `pod`. Google performs the decisioning, so the asset needs no URI. The same break serves both delivery modes. + +```bash +curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//breaks' \ + -u "$ADS_API_KEY:$ADS_API_SECRET" \ + -H 'Content-Type: application/json' \ + -H 'X-Org-ID: ' \ + -d '{ + "start": "2026-07-16T12:15:00.000Z", + "duration": 60, + "variant": { + "format": "single", + "assets": [ + { + "type": "vendor", + "vendor": "gam", + "vendorParameters": { "type": "pod" }, + "assetParameters": { + "description_url": "https://www.example.com/sports/live.html", + "plcmt": "1" + } + } + ] + } + }' +``` + +- OptiView Ads announces the break to Google within the [look-forward time](../../integrations/google/index.mdx#look-forward-time) before its start, so Google can decision the pod in time. +- Create the break at least the [decisioning margin](../../integrations/google/index.mdx#decisioning-margin) before its start, or it is rejected. +- The break starts in the `PREPARING` state, and becomes `READY` once Google has decisioned it. See [How pod decisioning works](../../integrations/google/pod-serving.mdx#how-pod-decisioning-works). + +### Other ways to create the break + +- **Punch it live.** Create the break without a `start`. Google decisions it ahead of time, and the break waits in the `CUED` state until you [punch](../../concepts/breaks.mdx#break-punching) it. +- **Detect it.** Add your stream as an [origin](../../concepts/origins.mdx) and configure a [marker rule](../../concepts/marker-detection.mdx) whose [template](../../concepts/templates.mdx) holds the Google vendor asset. + +## What your app needs + + + +### Server-side sessions + + + +### Turn Google off for a session + + + +## Ad targeting parameters + + + +## Troubleshooting + + + +## Related resources + +| Resource | Description | +| --------------------------------------------------------------------------- | --------------------------------------------------------------------- | +| [Live](./index.mdx) | Live channels: timebase, break creation, and delivery modes. | +| [Google Ad Manager](../../integrations/google/index.mdx) | Organization-level prerequisites: network code and service account. | +| [Google Pod Serving integration](../../integrations/google/pod-serving.mdx) | Google Ad Manager setup, channel configuration, and pod breaks. | +| [Google DAI integration](../../integrations/google/dai.mdx) | Server-side insertion: proxy, live stream, and channel configuration. | +| [Ad targeting parameters](../../how-to-guides/ad-tag-parameters.mdx) | Passing ad tag parameters to Google. | +| [Google Ad Manager on VOD](../vod/google-ad-manager.mdx) | The same workflow for on-demand assets. | diff --git a/ads/workflows/live/index.mdx b/ads/workflows/live/index.mdx new file mode 100644 index 000000000000..838a285dbb85 --- /dev/null +++ b/ads/workflows/live/index.mdx @@ -0,0 +1,66 @@ +--- +sidebar_position: 1 +sidebar_label: Live +description: Monetize a live stream with OptiView Ads. +--- + +# Live + +A live channel monetizes a linear stream or a live event. Breaks are placed on the live timeline, and players watching the stream — at the live edge or behind it in the DVR window — receive them through the channel's [Break Manifest](../../concepts/break-manifest.mdx). + +## Set up a live channel + +A channel is live by default. Choose the [timebase](../../concepts/channels.mdx#timebase) that matches the timing information in your stream: + +- **`wallclock`** — breaks start at a UTC timestamp, matched against the stream's own wallclock timeline (`EXT-X-PROGRAM-DATE-TIME` in HLS, the segment timeline in DASH). This is the recommended timebase. +- **`pts`** — breaks start at a presentation timestamp on the encoder's timeline. + +```bash +curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels' \ + -u "$ADS_API_KEY:$ADS_API_SECRET" \ + -H 'Content-Type: application/json' \ + -H 'X-Org-ID: ' \ + -d '{ + "name": "Sports main", + "streamType": "live", + "timebase": "wallclock" + }' +``` + +The [DVR window](../../concepts/channels.mdx#dvr-window), [live offset](../../concepts/channels.mdx#live-offset), and [ad prefetch window](../../concepts/channels.mdx#ad-prefetch-window) settings tune which breaks the Break Manifest contains at any moment. + +## How breaks are created + +On a live stream, breaks can be created in three ways, and you can combine them on one channel: + +- **Scheduled** — create a break with a start time, ahead of time or on the spot. See [Scheduling](../../concepts/breaks.mdx#scheduling). +- **Punched** — prepare a break without a start time, and fire it when the moment comes, for example from your production control room. See [Break punching](../../concepts/breaks.mdx#break-punching). +- **Detected** — add your stream as an [origin](../../concepts/origins.mdx), and OptiView Ads turns the ad markers in the stream, such as SCTE-35 signals, into breaks. See [Break detection](../../concepts/marker-detection.mdx). This replaces the ad breaks already in your stream (Dynamic Ad Replacement). + +[Events](../../concepts/events.mdx) let you prepare the breaks of a live event, such as a match or a show, upfront. [Templates](../../concepts/templates.mdx) store a break configuration once, so scheduling becomes a one-liner. + +Besides breaks on the timeline, a live channel can carry [event-triggered breaks](../../concepts/breaks.mdx#event-based-triggers): a pre-roll when the viewer starts watching, a pause ad, and a post-roll. + +## How players receive the breaks + +The SDK polls the Break Manifest during the whole session. A break appears in the manifest shortly before it starts — within the ad prefetch window — so the SDK can prepare the ads, and it stays there while viewers in the DVR window can still reach it. Changes to a break, such as an earlier end, reach the players on the next poll. + +## Choose an ad source + +Each ad source has its own page with everything you need for live: the break setup, what your app needs, the supported layouts, and troubleshooting. Live channels support both delivery modes of the [hybrid platform](../index.mdx#hybrid-ad-insertion-sgai-and-ssai): + +| Ad source | SGAI | SSAI | +| -------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------- | +| [Static assets](./static-assets.mdx) | Yes | No | +| [Your ad server (VAST)](./vast.mdx) | Yes | No | +| [Google Ad Manager](./google-ad-manager.mdx) | Yes, with [Google Pod Serving](../../integrations/google/pod-serving.mdx) | Yes, with [Google DAI](../../integrations/google/dai.mdx) | + +## Related resources + +| Resource | Description | +| ------------------------------------------------------ | ----------------------------------------------------------- | +| [Getting started](../../getting-started/index.mdx) | Create a live channel and play your first break end to end. | +| [Channels](../../concepts/channels.mdx) | Timebase, DVR window, live offset, and prefetch settings. | +| [Breaks](../../concepts/breaks.mdx) | Scheduling, punching, layouts, and the asset model. | +| [Break detection](../../concepts/marker-detection.mdx) | Turn the ad markers in your stream into breaks. | +| [VOD](../vod/index.mdx) | Monetize on-demand assets instead. | diff --git a/ads/workflows/live/static-assets.mdx b/ads/workflows/live/static-assets.mdx new file mode 100644 index 000000000000..f24d7c71ab0a --- /dev/null +++ b/ads/workflows/live/static-assets.mdx @@ -0,0 +1,96 @@ +--- +sidebar_position: 1 +sidebar_label: Static assets +description: Play ad creatives from your own CDN in a live stream, without an ad server. +--- + +# Static assets on live + +import Layouts from '../_shared/_static-assets-layouts.mdx'; +import Formats from '../_shared/_static-assets-formats.mdx'; +import Troubleshooting from '../_shared/_static-assets-troubleshooting.mdx'; + +With static assets, each break points directly at its ad creatives: video or image files that you host on your own CDN. No ad server is involved — the SDK fetches the creative from the URL on the break and plays it when the break starts. Use this workflow on live streams for direct-sold campaigns, sponsorships, promos, and branded overlays where you already know which creative to show. + +| | Static assets on live | +| -------------- | ------------------------------------------------------------------ | +| Delivery mode | Server-guided (SGAI) | +| Ad decisioning | None: the break names the creative | +| Break creation | Scheduled, punched, or detected from the ad markers in your stream | +| Your app needs | The OptiView Ads SDK for your platform; nothing else | + +## Before you start + +- A [live channel](./index.mdx#set-up-a-live-channel). The examples use the `wallclock` timebase. +- The OptiView Ads SDK in your app: [Web](../../player-integration/optiview-ads-sdk/web.mdx), [Android](../../player-integration/optiview-ads-sdk/android.mdx), [iOS](../../player-integration/optiview-ads-sdk/ios.mdx), or [React Native](../../player-integration/optiview-ads-sdk/react-native.mdx). Static assets need no ad server, no Google Ad Manager account, and no extra configuration in the app. +- Your creatives on a CDN that the viewers' devices can reach. + +## Schedule a break + +A static asset sets `type` to `static` and `uri` to the URL of the creative. On a `wallclock` channel, `start` is the UTC moment in your stream when the break begins: + +```bash +curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//breaks' \ + -u "$ADS_API_KEY:$ADS_API_SECRET" \ + -H 'Content-Type: application/json' \ + -H 'X-Org-ID: ' \ + -d '{ + "start": "2026-07-16T12:15:00.000Z", + "duration": 30, + "variant": { + "format": "single", + "assets": [ + { + "type": "static", + "mediaType": "video", + "mimeType": "application/x-mpegurl", + "uri": "https://cdn.example.com/ads/spot.m3u8", + "interaction": { "clickThrough": "https://www.example.com/offer" } + } + ] + } + }' +``` + +The `uri` can also be a list of URLs targeted per device type. See [Static assets](../../concepts/breaks.mdx#static-assets) and [Asset URI targeting](../../concepts/breaks.mdx#asset-uri-targeting) for the full asset model. + +### Other ways to create the break + +- **Punch it live.** Create the break without a `start`, and [punch](../../concepts/breaks.mdx#break-punching) it when the moment comes, for example from your production control room. +- **Detect it.** Add your stream as an [origin](../../concepts/origins.mdx) and configure a [marker rule](../../concepts/marker-detection.mdx) whose [template](../../concepts/templates.mdx) holds the static assets. Every matching ad marker in the stream, such as an SCTE-35 signal, becomes a break. +- **Trigger it on a player event.** Set `start` to `{ "type": "event", "event": "start" }` for a pre-roll when the viewer tunes in, `"pause"` for a pause ad, or `"end"` for a post-roll. See [Event based triggers](../../concepts/breaks.mdx#event-based-triggers). + +## How the break plays + +- The SDK receives the break through the channel's [Break Manifest](../../concepts/break-manifest.mdx) shortly before it starts, within the channel's [ad prefetch window](../../concepts/channels.mdx#ad-prefetch-window), and loads the creative ahead of time so the ad starts without delay. +- Viewers behind the live edge, in the [DVR window](../../concepts/channels.mdx#dvr-window), play the break when their playhead reaches it. +- Static assets always play server-guided. On a channel that steers some devices to [SSAI](../index.mdx#hybrid-ad-insertion-sgai-and-ssai), those devices still play the static event-triggered breaks — pre-roll, pause, and post-roll — but not the breaks on the timeline. + +## Supported layouts + + + +## Creative formats + + + +## Tracking and reporting + +The SDK reports an OptiView Ads [impression](../../how-to-guides/ad-impressions.md) for every break it presents, and emits ad events — such as the start and end of each break and ad — that your app can listen to. See the API reference of your platform for the full list of events. + +Static assets carry no third-party tracking URLs. If an advertiser needs to count impressions in their own ad server, deliver the creative through a [VAST tag](./vast.mdx) instead: the VAST response carries the advertiser's tracking URLs, which are fired while the ad plays. + +## Troubleshooting + + + +## Related resources + +| Resource | Description | +| --------------------------------------------------------------- | ------------------------------------------------------------- | +| [Live](./index.mdx) | Live channels: timebase, break creation, and delivery modes. | +| [Breaks](../../concepts/breaks.mdx) | Layouts, variants, controls, and the asset model. | +| [Templates](../../concepts/templates.mdx) | Store a break with its static assets once, and reuse it. | +| [Your ad server (VAST) on live](./vast.mdx) | Let your ad server decide which creative to play. | +| [Static assets on VOD](../vod/static-assets.mdx) | The same workflow for on-demand assets. | +| [Ad impression tracking](../../how-to-guides/ad-impressions.md) | How OptiView Ads counts the breaks presented to your viewers. | diff --git a/ads/workflows/live/vast.mdx b/ads/workflows/live/vast.mdx new file mode 100644 index 000000000000..bdadf119d0c8 --- /dev/null +++ b/ads/workflows/live/vast.mdx @@ -0,0 +1,102 @@ +--- +sidebar_position: 2 +sidebar_label: Your ad server (VAST) +description: Let your own ad server, or a partner's, decide the ads in a live stream through VAST tags. +--- + +# Your ad server (VAST) on live + +import AppNeeds from '../_shared/_vast-app.mdx'; +import Layouts from '../_shared/_vast-layouts.mdx'; +import Targeting from '../_shared/_vast-targeting.mdx'; +import Tracking from '../_shared/_vast-tracking.mdx'; +import Troubleshooting from '../_shared/_vast-troubleshooting.mdx'; + +With VAST, each break points at a VAST tag: a URL on your ad server, or an advertiser's, that returns a [VAST](https://iabtechlab.com/standards/vast/) XML document. The ad server decides which creative to play, and its response carries the media files and the tracking URLs. Use this workflow on live streams when you run your own ad server, or buy from partners that deliver their ads through VAST tags. + +| | Your ad server (VAST) on live | +| -------------- | ------------------------------------------------------------------ | +| Delivery mode | Server-guided (SGAI) | +| Ad decisioning | Your ad server, per viewer, when the SDK requests the tag | +| Break creation | Scheduled, punched, or detected from the ad markers in your stream | +| Your app needs | The OptiView Ads SDK; on Web also Google's client-side IMA SDK | + +## Before you start + +- A [live channel](./index.mdx#set-up-a-live-channel). The examples use the `wallclock` timebase. +- The OptiView Ads SDK in your app: [Web](../../player-integration/optiview-ads-sdk/web.mdx), [Android](../../player-integration/optiview-ads-sdk/android.mdx), [iOS](../../player-integration/optiview-ads-sdk/ios.mdx), or [React Native](../../player-integration/optiview-ads-sdk/react-native.mdx). +- A VAST tag URL from your ad server, or an advertiser's. + +## What your app needs + + + +## Schedule a break + +A VAST asset sets `type` to `vast` and `uri` to the VAST tag URL. On a `wallclock` channel, `start` is the UTC moment in your stream when the break begins: + +```bash +curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//breaks' \ + -u "$ADS_API_KEY:$ADS_API_SECRET" \ + -H 'Content-Type: application/json' \ + -H 'X-Org-ID: ' \ + -d '{ + "start": "2026-07-16T12:15:00.000Z", + "duration": 30, + "variant": { + "format": "single", + "assets": [ + { + "type": "vast", + "mediaType": "video", + "mimeType": "application/xml", + "uri": "https://adserver.example.com/vast?slot=midroll", + "assetParameters": { + "content_genre": "sports" + } + } + ] + } + }' +``` + +The `uri` can also be a list of tag URLs targeted per device type. See [VAST assets](../../concepts/breaks.mdx#vast-assets) and [Asset URI targeting](../../concepts/breaks.mdx#asset-uri-targeting) for the full asset model. + +### Other ways to create the break + +- **Punch it live.** Create the break without a `start`, and [punch](../../concepts/breaks.mdx#break-punching) it when the moment comes. +- **Detect it.** Add your stream as an [origin](../../concepts/origins.mdx) and configure a [marker rule](../../concepts/marker-detection.mdx) whose [template](../../concepts/templates.mdx) holds the VAST asset. Every matching ad marker in the stream becomes a break. +- **Trigger it on a player event.** Set `start` to `{ "type": "event", "event": "start" }` for a pre-roll when the viewer tunes in, `"pause"` for a pause ad, or `"end"` for a post-roll. See [Event based triggers](../../concepts/breaks.mdx#event-based-triggers). + +## How the break plays + +- The SDK receives the break through the channel's [Break Manifest](../../concepts/break-manifest.mdx) shortly before it starts, and requests the VAST tag on the device. Every viewer gets an individual ad decision. +- Many viewers reach a live break at the same moment, so your ad server receives a peak of requests at every break start. Make sure it is sized for your concurrent audience. +- On a channel that steers some devices to [SSAI](../index.mdx#hybrid-ad-insertion-sgai-and-ssai), VAST breaks on the timeline are not played on those devices. + +## Supported layouts + + + +## Ad targeting parameters + + + +## Tracking and reporting + + + +## Troubleshooting + + + +## Related resources + +| Resource | Description | +| -------------------------------------------------------------------- | ------------------------------------------------------------ | +| [Live](./index.mdx) | Live channels: timebase, break creation, and delivery modes. | +| [Breaks](../../concepts/breaks.mdx) | Layouts, variants, controls, and the asset model. | +| [Ad targeting parameters](../../how-to-guides/ad-tag-parameters.mdx) | Passing targeting parameters to your ad server. | +| [Static assets on live](./static-assets.mdx) | Play creatives from your CDN without an ad server. | +| [Google Ad Manager on live](./google-ad-manager.mdx) | Let Google Ad Manager fill your breaks. | +| [Your ad server (VAST) on VOD](../vod/vast.mdx) | The same workflow for on-demand assets. | diff --git a/ads/workflows/static-assets.mdx b/ads/workflows/static-assets.mdx deleted file mode 100644 index c79a97634d9d..000000000000 --- a/ads/workflows/static-assets.mdx +++ /dev/null @@ -1,105 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: Static assets -description: Play ad creatives from your own CDN, on live and VOD, without an ad server. ---- - -# Static assets - -With static assets, each break points directly at its ad creatives: video or image files that you host on your own CDN. No ad server is involved — the SDK fetches the creative from the URL on the break and plays it when the break starts. Use this workflow for direct-sold campaigns, sponsorships, promos, and branded overlays where you already know which creative to show. - -| | [Live](./live.mdx) | [VOD](./vod.mdx) | -| -------------- | ---------------------------------- | ---------------------------------- | -| Supported | Yes | Yes | -| Delivery mode | SGAI | SGAI | -| Ad decisioning | None: the break names the creative | None: the break names the creative | - -## What your app needs - -Nothing beyond the integration for your platform: [Web](../player-integration/optiview-ads-sdk/web.mdx), [Android](../player-integration/optiview-ads-sdk/android.mdx), [iOS](../player-integration/optiview-ads-sdk/ios.mdx), or [React Native](../player-integration/optiview-ads-sdk/react-native.mdx). Static assets need no ad server, no Google Ad Manager account, and no extra configuration in the app. - -## Schedule a break with static assets - -A static asset sets `type` to `static` and `uri` to the URL of the creative. The asset is the same for live and VOD; only the break's `start` differs, see [Live and VOD](#live-and-vod). On a live `wallclock` channel: - -```bash -curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//breaks' \ - -u "$ADS_API_KEY:$ADS_API_SECRET" \ - -H 'Content-Type: application/json' \ - -H 'X-Org-ID: ' \ - -d '{ - "start": "", - "duration": 30, - "variant": { - "format": "single", - "assets": [ - { - "type": "static", - "mediaType": "video", - "mimeType": "application/x-mpegurl", - "uri": "https://cdn.example.com/ads/spot.m3u8", - "interaction": { "clickThrough": "https://www.example.com/offer" } - } - ] - } - }' -``` - -The `uri` can also be a list of URLs targeted per device type. See [Static assets](../concepts/breaks.mdx#static-assets) and [Asset URI targeting](../concepts/breaks.mdx#asset-uri-targeting) for the full asset model. - -## Live and VOD - -### Live - -- Schedule the break ahead of time with a UTC `start`, prepare it without a start and [punch](../concepts/breaks.mdx#break-punching) it, or let [break detection](../concepts/marker-detection.mdx) create it from the ad markers in your stream — with a [template](../concepts/templates.mdx) that holds the static assets. -- The SDK receives the break shortly before it starts, within the channel's [ad prefetch window](../concepts/channels.mdx#ad-prefetch-window), and loads the creative ahead of time so the ad starts without delay. -- Static assets always play server-guided. On a channel that steers some devices to SSAI, those devices still play the static [event-triggered breaks](../concepts/breaks.mdx#event-based-triggers) — pre-roll, pause, and post-roll — but not the breaks on the timeline. - -### VOD - -- Set `start` to the position in the asset, in seconds, on a `mediatime` channel — for example `"start": 600` — or use an event trigger for a pre-roll or post-roll. [Break detection](../concepts/marker-detection.mdx) can also create the breaks from the ad markers in the asset, with a [template](../concepts/templates.mdx) that holds the static assets. -- The SDK receives all breaks when the session starts, and prepares each creative shortly before its break. -- Enable [snapback](./vod.mdx#seeking-and-snapback) on breaks that viewers must not skip by seeking. - -## Supported layouts - -Static assets work in every [layout](../concepts/breaks.mdx#layouts) and as [pause ads](../concepts/breaks.mdx#pause): - -| Layout | Static asset | -| --------------------- | ---------------------------------------------------------------------------------------- | -| `single` | A video that replaces the content. | -| `double`, `lshape_ad` | A video, with an image or video `companion` that fills the background. | -| `lshape_content` | An image that fills the L-shaped backdrop while your content keeps playing. | -| `overlay` | An image or video on top of your content. | -| Pause ad | An image, or a progressive MP4 video that plays muted, shown while the viewer is paused. | - -An image stays on screen for the asset's `duration`, or for the break's `duration` when the asset has none. - -## Creative formats - -- **HLS (`.m3u8`)** is the recommended format for video creatives on every platform. On connected TVs in particular, the SDK can prefetch an HLS creative ahead of the break, so the ad starts faster. -- **Progressive MP4** also works. On Web, the SDK plays MP4 creatives through the browser's own video element. -- **Images** are used for overlays, companions, L-shape backdrops, and pause ads. - -Set `mimeType` on the asset when you know it. The SDK then knows upfront how to play the creative, instead of having to find out, which makes ad preparation faster. - -## Tracking and reporting - -The SDK reports an OptiView Ads [impression](../how-to-guides/ad-impressions.md) for every break it presents, and emits ad events — such as the start and end of each break and ad — that your app can listen to. See the API reference of your platform for the full list of events. - -Static assets carry no third-party tracking URLs. If an advertiser needs to count impressions in their own ad server, deliver the creative through a [VAST](./vast.mdx) tag instead: the VAST response carries the advertiser's tracking URLs, which are fired while the ad plays. - -## Troubleshooting - -- **The break does not play.** Check that the channel's [Break Manifest](../concepts/break-manifest.mdx) contains the break, and that the creative URL is publicly reachable. -- **Web: the creative fails to load.** The SDK downloads HLS creatives with HTTP requests from your page, so your CDN must allow cross-origin requests (CORS) from your app's origin. -- **A creative cannot be played.** The SDK emits an `aderror` event for the asset, continues with the next asset in the break if there is one, and otherwise returns to your content. - -## Related resources - -| Resource | Description | -| ------------------------------------------------------------ | ------------------------------------------------------------- | -| [Breaks](../concepts/breaks.mdx) | Layouts, variants, controls, and the asset model. | -| [Templates](../concepts/templates.mdx) | Store a break with its static assets once, and reuse it. | -| [VAST](./vast.mdx) | Let your ad server decide which creative to play. | -| [Ad impression tracking](../how-to-guides/ad-impressions.md) | How OptiView Ads counts the breaks presented to your viewers. | diff --git a/ads/workflows/vast.mdx b/ads/workflows/vast.mdx deleted file mode 100644 index 8858ef0e46d1..000000000000 --- a/ads/workflows/vast.mdx +++ /dev/null @@ -1,138 +0,0 @@ ---- -sidebar_position: 4 -sidebar_label: VAST -description: Let your own ad server, or a partner's, decide the ads through VAST tags, on live and VOD. ---- - -# VAST - -With VAST, each break points at a VAST tag: a URL on your ad server, or an advertiser's, that returns a [VAST](https://iabtechlab.com/standards/vast/) XML document. The ad server decides which creative to play, and its response carries the media files and the tracking URLs. Use this workflow when you run your own ad server, or buy from partners that deliver their ads through VAST tags. - -The SDK requests and plays VAST tags on the device, through Google's client-side IMA SDK. IMA processes the VAST response — it follows wrappers, picks a media file, and fires the tracking URLs. IMA works with any VAST-compliant ad server: you do not need a Google Ad Manager account. A Google Ad Manager VAST tag works too. - -| | [Live](./live.mdx) | [VOD](./vod.mdx) | -| -------------- | --------------------------------------------- | --------------------------------------------- | -| Supported | Yes | Yes | -| Delivery mode | SGAI | SGAI | -| Ad decisioning | Your ad server, when the SDK requests the tag | Your ad server, when the SDK requests the tag | - -## What your app needs - -| Platform | Requirement | -| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Web | Load Google's client-side IMA SDK on the page, before your application script (see below). | -| Android | Nothing extra: the SDK runtime includes the Google IMA SDK. | -| iOS and tvOS | Nothing extra: the runtime pod includes the Google IMA SDK. With Swift Package Manager, add the Google IMA packages as described in [iOS](../player-integration/optiview-ads-sdk/ios.mdx#swift-package-manager). | -| React Native | Nothing extra: the native SDKs include the Google IMA SDK. | - -On Web, add the IMA loader to your page: - -```html - -``` - -Without it, the SDK cannot play VAST breaks: it reports `DA-VAST-IMA-SDK-MISSING` and returns to your content. If your channel also uses [Google Pod Serving](./google-ad-manager.mdx), load `ima3_dai.js` as well; the two scripts work side by side. - -:::caution[Web: include an MP4 media file] -The IMA SDK for HTML5 plays the ad through the browser's own video element, which cannot play HLS outside Safari. Make sure your VAST responses include a progressive MP4 media file, or the ad fails to play in Chrome, Edge, and Firefox. -::: - -## Schedule a VAST break - -A VAST asset sets `type` to `vast` and `uri` to the VAST tag URL. The asset is the same for live and VOD; only the break's `start` differs, see [Live and VOD](#live-and-vod). On a live `wallclock` channel: - -```bash -curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//breaks' \ - -u "$ADS_API_KEY:$ADS_API_SECRET" \ - -H 'Content-Type: application/json' \ - -H 'X-Org-ID: ' \ - -d '{ - "start": "", - "duration": 30, - "variant": { - "format": "single", - "assets": [ - { - "type": "vast", - "mediaType": "video", - "mimeType": "application/xml", - "uri": "https://adserver.example.com/vast?slot=midroll", - "assetParameters": { - "content_genre": "sports" - } - } - ] - } - }' -``` - -The `uri` can also be a list of tag URLs targeted per device type. See [VAST assets](../concepts/breaks.mdx#vast-assets) and [Asset URI targeting](../concepts/breaks.mdx#asset-uri-targeting) for the full asset model. - -## Live and VOD - -The SDK requests the VAST tag on the device, shortly before the break starts. Every viewer therefore gets an individual ad decision, on live and on VOD. - -### Live - -- Schedule, [punch](../concepts/breaks.mdx#break-punching), or [detect](../concepts/marker-detection.mdx) the break as on any live channel; for detected breaks, put the VAST asset in the rule's [template](../concepts/templates.mdx). -- Many viewers reach a live break at the same moment, so your ad server receives a peak of requests at every break start. Make sure it is sized for your concurrent audience. -- On a channel that steers some devices to SSAI, VAST breaks on the timeline are not played on those devices. See [Troubleshooting](#troubleshooting). - -### VOD - -- Set `start` to the position in the asset, in seconds, on a `mediatime` channel, or use an event trigger for a pre-roll, a post-roll, or a pause ad. For breaks that [break detection](../concepts/marker-detection.mdx) creates from the ad markers in the asset, put the VAST asset in the rule's [template](../concepts/templates.mdx). -- Viewers reach the breaks at different moments, so the requests to your ad server are spread over time. -- Use a VAST tag that returns the right ad length for the break: the break's `duration` is the maximum, and the SDK returns to your content when it is reached. - -## Supported layouts - -VAST describes a linear (video) ad, so VAST assets work in the layouts where an ad video plays: - -| Layout | VAST asset | -| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `single` | Supported. | -| `double`, `lshape_ad` | Supported. The VAST ad plays in the ad box, and the asset's `companion` fills the background. | -| `lshape_content`, `overlay` | Not supported. The SDK does not play the asset and reports `DA-VAST-UNSUPPORTED-FORMAT`. Use a [static asset](./static-assets.mdx) instead. | -| Pause ad | Supported. The SDK reads the image from the VAST companion ads, or a progressive MP4 from the linear ad, and fires its impression tracking when shown. | - -VAST breaks play in server-guided (SGAI) sessions only. - -## Ad targeting parameters - -To personalize the ad request, add `assetParameters`. The SDK appends them to the VAST tag URL as URL-encoded query parameters when it requests the tag. For the break above, with a session-level parameter `device_id` set in the SDK, the request becomes: - -```text -https://adserver.example.com/vast?slot=midroll&content_genre=sports&device_id=abc123 -``` - -Set the parameters in one of two places: - -- **On the break**, for values that are the same for every viewer, such as the content genre. -- **In the SDK**, with `assetParameters` in the session configuration or `updateAssetParameters()`, for values that depend on the viewer or the device. - -When the same key is set in both places, the value on the break wins. Parameter values can also contain macros, such as `$OPTIVIEW_PLAYER_WIDTH$`, that the SDK fills in when it builds the request. See [Ad targeting parameters](../how-to-guides/ad-tag-parameters.mdx) for the merge rules, the macros, and platform examples. - -## Tracking and reporting - -- IMA fires the tracking URLs in the VAST response, such as impressions, quartiles, and clicks, so the ad server counts the ad. -- The SDK reports an OptiView Ads [impression](../how-to-guides/ad-impressions.md) for the break, and emits the same ad events as for any other break. - -## Troubleshooting - -VAST failures never block your content: the SDK emits an `aderror` event, reports a diagnostic, and returns to the content. - -| Diagnostic | What it means | What to do | -| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `DA-VAST-IMA-SDK-MISSING` | Google's client-side IMA SDK is not available. | On Web, load `ima3.js` on the page. | -| `DA-VAST-IMA-ERROR` | IMA could not load, parse, or play the VAST response — for example an unreachable tag, an empty response, or no playable media file. | Test the tag in Google's [VAST Inspector](https://googleads.github.io/googleads-ima-html5/vsi/). On Web, make sure the response includes a progressive MP4 media file. | -| `DA-VAST-UNSUPPORTED-FORMAT` | The VAST asset is in an `overlay` or `lshape_content` break. | Use the `single`, `double`, or `lshape_ad` layout, or a static asset. | -| `DA-VAST-SSAI-UNSUPPORTED` | The VAST asset is in a server-side (SSAI) session. | Play VAST breaks in a server-guided (`sgai`) session. | - -## Related resources - -| Resource | Description | -| ----------------------------------------------------------------- | ------------------------------------------------------------- | -| [Breaks](../concepts/breaks.mdx) | Layouts, variants, controls, and the asset model. | -| [Ad targeting parameters](../how-to-guides/ad-tag-parameters.mdx) | Passing targeting parameters to your ad server. | -| [Static assets](./static-assets.mdx) | Play creatives from your CDN without an ad server. | -| [Google Pod Serving](./google-ad-manager.mdx) | Let Google Ad Manager decision the ads that fill your breaks. | diff --git a/ads/workflows/vod/google-ad-manager.mdx b/ads/workflows/vod/google-ad-manager.mdx new file mode 100644 index 000000000000..7b39cc964fce --- /dev/null +++ b/ads/workflows/vod/google-ad-manager.mdx @@ -0,0 +1,110 @@ +--- +sidebar_position: 3 +sidebar_label: Google Ad Manager +description: Let Google Ad Manager 360 fill the breaks of on-demand assets, server-guided or server-side. +--- + +# Google Ad Manager on VOD + +import AppNeeds from '../_shared/_gam-app.mdx'; +import SsaiSession from '../_shared/_gam-ssai-session.mdx'; +import TurnOff from '../_shared/_gam-turn-off.mdx'; +import Targeting from '../_shared/_gam-targeting.mdx'; +import Troubleshooting from '../_shared/_gam-troubleshooting.mdx'; + +With Google Ad Manager 360, Google decides which ads fill the breaks of your on-demand assets. Google assembles the ads for each break into a pod, and the pod plays when the viewer reaches the break. Use this workflow when you sell your VOD inventory through Google Ad Manager 360, and to reach platforms that need server-side ad insertion. + +| | Google Ad Manager on VOD | +| -------------- | -------------------------------------------------------------------------- | +| Delivery mode | Server-guided (SGAI), server-side (SSAI), or both | +| Ad decisioning | Google Ad Manager, per viewer session | +| Break creation | Scheduled at positions in the asset, or detected from the ad markers in it | +| Your app needs | The OptiView Ads SDK; on Web also Google's IMA DAI SDK | + +Contact your Dolby OptiView account team to enable Google Ad Manager on your VOD channels. + +## Choose a delivery mode + +| Delivery mode | How it works | Use it for | +| ------------- | ------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------- | +| Server-guided | Google decisions the pods; the SDK inserts them at the break positions of your untouched asset. | Web, mobile, and most connected TV apps. Required for the double box, L-shape, and overlay layouts. | +| Server-side | Google stitches the ads for the asset's breaks into the on-demand stream, and the player plays the stitched asset. | Platforms where a client-side SDK is not an option, such as Roku and older connected TV devices. | + +One channel can serve both: the channel steers the [delivery mode per device](../index.mdx#hybrid-ad-insertion-sgai-and-ssai), and the SDK picks it up from the Break Manifest. + +## Before you start + +- The [Google Ad Manager prerequisites](../../integrations/google/index.mdx) — network code and service account — are in place for your organization. +- A [VOD channel](./index.mdx#set-up-a-vod-channel), connected to Google. The examples use the `mediatime` timebase. +- The OptiView Ads SDK in your app: [Web](../../player-integration/optiview-ads-sdk/web.mdx), [Android](../../player-integration/optiview-ads-sdk/android.mdx), [iOS](../../player-integration/optiview-ads-sdk/ios.mdx), or [React Native](../../player-integration/optiview-ads-sdk/react-native.mdx). + +## Schedule a break + +A Google break carries a [vendor asset](../../concepts/breaks.mdx#vendor-assets) with `vendor` set to `gam` and `vendorParameters.type` set to `pod`. Google performs the decisioning, so the asset needs no URI. On a `mediatime` channel, `start` is the position in the asset, in seconds: + +```bash +curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//breaks' \ + -u "$ADS_API_KEY:$ADS_API_SECRET" \ + -H 'Content-Type: application/json' \ + -H 'X-Org-ID: ' \ + -d '{ + "start": 600, + "duration": 60, + "controls": { "snapback": true }, + "variant": { + "format": "single", + "assets": [ + { + "type": "vendor", + "vendor": "gam", + "vendorParameters": { "type": "pod" }, + "assetParameters": { + "description_url": "https://www.example.com/movies/the-big-match.html", + "plcmt": "1" + } + } + ] + } + }' +``` + +### Detect the breaks + +Instead of scheduling every break, add the asset as an [origin](../../concepts/origins.mdx) and configure a [marker rule](../../concepts/marker-detection.mdx) whose [template](../../concepts/templates.mdx) holds the Google vendor asset. Every matching ad marker in the asset becomes a break at its position. + +## How the break plays + +- **Server-guided:** the SDK fetches the channel's [Break Manifest](../../concepts/break-manifest.mdx) once when the session starts, and inserts Google's pods at the break positions as the viewer reaches them. +- **Server-side:** Google stitches the ads into the asset, and the player plays the stitched stream. +- Ads are decisioned per viewer session rather than per break moment, because every viewer watches from their own position: there is no audience-wide peak at a break start. +- With `snapback`, a viewer who seeks past a break is taken back to the break first. See [Seeking and snapback](./index.mdx#seeking-and-snapback). + +## What your app needs + + + +### Server-side sessions + + + +### Turn Google off for a session + + + +## Ad targeting parameters + + + +## Troubleshooting + + + +## Related resources + +| Resource | Description | +| -------------------------------------------------------------------- | ------------------------------------------------------------------- | +| [VOD](./index.mdx) | VOD channels: timebase, seeking, and delivery modes. | +| [Google Ad Manager](../../integrations/google/index.mdx) | Organization-level prerequisites: network code and service account. | +| [Ad targeting parameters](../../how-to-guides/ad-tag-parameters.mdx) | Passing ad tag parameters to Google. | +| [Your ad server (VAST) on VOD](./vast.mdx) | Play VAST tags from your own ad server, without Google Ad Manager. | +| [Google Ad Manager on live](../live/google-ad-manager.mdx) | The same workflow for live streams. | diff --git a/ads/workflows/vod.mdx b/ads/workflows/vod/index.mdx similarity index 65% rename from ads/workflows/vod.mdx rename to ads/workflows/vod/index.mdx index 92dc5d2265b5..95aac608da8a 100644 --- a/ads/workflows/vod.mdx +++ b/ads/workflows/vod/index.mdx @@ -34,7 +34,7 @@ The `streamType` and the `timebase` are set when you create the channel and cann On a VOD channel, breaks are known before playback starts. Create them in one of two ways, or combine them: - **Scheduled** — create each break with its position in the asset, as below. -- **Detected** — add the asset as an [origin](../concepts/origins.mdx), and OptiView Ads turns the ad markers in the asset, such as SCTE-35 signals, into breaks at their positions. See [Break detection](../concepts/marker-detection.mdx). +- **Detected** — add the asset as an [origin](../../concepts/origins.mdx), and OptiView Ads turns the ad markers in the asset, such as SCTE-35 signals, into breaks at their positions. See [Break detection](../../concepts/marker-detection.mdx). With the `mediatime` timebase, `start` is a number of seconds: @@ -62,16 +62,16 @@ curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//bre A typical VOD ad plan combines: -- **Pre-roll** — a break triggered when playback starts, with an [event trigger](../concepts/breaks.mdx#start) instead of a start position. +- **Pre-roll** — a break triggered when playback starts, with an [event trigger](../../concepts/breaks.mdx#start) instead of a start position. - **Mid-rolls** — breaks at positions in the asset, such as `600` and `1800`. -- **Post-roll** — a break triggered when playback ends, with an [end trigger](../concepts/breaks.mdx#end). -- **Pause ads** — shown while the viewer is paused, with a [pause trigger](../concepts/breaks.mdx#pause). +- **Post-roll** — a break triggered when playback ends, with an [end trigger](../../concepts/breaks.mdx#end). +- **Pause ads** — shown while the viewer is paused, with a [pause trigger](../../concepts/breaks.mdx#pause). Breaks on a VOD channel cannot overlap. ### Seeking and snapback -VOD viewers seek freely, so decide per break what happens when they skip over it, with the break's [controls](../concepts/breaks.mdx#controls): +VOD viewers seek freely, so decide per break what happens when they skip over it, with the break's [controls](../../concepts/breaks.mdx#controls): - With `snapback` enabled, a viewer who seeks past a break is taken back to the break first. After the break, playback continues at the position the viewer was seeking to. - Without `snapback`, the viewer can skip the break. @@ -82,28 +82,30 @@ A break plays at most once per session: seeking back over a break that has alrea A VOD Break Manifest lists all breaks of the channel, and carries no polling interval. The SDK fetches it once when the session starts, and schedules every break against the playback position of the asset. Changes you make to the breaks apply to the next playback session. -Your app integrates the SDK in the same way as for live: [Web](../player-integration/optiview-ads-sdk/web.mdx), [Android](../player-integration/optiview-ads-sdk/android.mdx), [iOS](../player-integration/optiview-ads-sdk/ios.mdx), or [React Native](../player-integration/optiview-ads-sdk/react-native.mdx). Start a session with the Break Manifest URL of the VOD channel when you load the asset. +Your app integrates the SDK in the same way as for live: [Web](../../player-integration/optiview-ads-sdk/web.mdx), [Android](../../player-integration/optiview-ads-sdk/android.mdx), [iOS](../../player-integration/optiview-ads-sdk/ios.mdx), or [React Native](../../player-integration/optiview-ads-sdk/react-native.mdx). Start a session with the Break Manifest URL of the VOD channel when you load the asset. ## What is different from live The live-only features do not apply to VOD channels: -- **No events.** [Events](../concepts/events.mdx) group the breaks of a live event; a VOD asset has no live moment to prepare for. +- **No events.** [Events](../../concepts/events.mdx) group the breaks of a live event; a VOD asset has no live moment to prepare for. - **No `pts` timebase.** Use `mediatime` or `wallclock`. -## Delivery modes +## Choose an ad source + +Each ad source has its own page with everything you need for VOD: the break setup, what your app needs, the supported layouts, and troubleshooting. VOD channels support both delivery modes of the [hybrid platform](../index.mdx#hybrid-ad-insertion-sgai-and-ssai): | Ad source | SGAI | SSAI | | -------------------------------------------- | ---- | ---- | | [Static assets](./static-assets.mdx) | Yes | No | -| [VAST](./vast.mdx) | Yes | No | +| [Your ad server (VAST)](./vast.mdx) | Yes | No | | [Google Ad Manager](./google-ad-manager.mdx) | Yes | Yes | ## Related resources -| Resource | Description | -| ------------------------------------------------ | ------------------------------------------------------- | -| [Breaks](../concepts/breaks.mdx) | Event triggers, controls, layouts, and the asset model. | -| [Channels](../concepts/channels.mdx) | Stream type and timebase. | -| [Break Manifest](../concepts/break-manifest.mdx) | How breaks are delivered to players. | -| [Live](./live.mdx) | Monetize live streams instead. | +| Resource | Description | +| --------------------------------------------------- | ------------------------------------------------------- | +| [Breaks](../../concepts/breaks.mdx) | Event triggers, controls, layouts, and the asset model. | +| [Channels](../../concepts/channels.mdx) | Stream type and timebase. | +| [Break Manifest](../../concepts/break-manifest.mdx) | How breaks are delivered to players. | +| [Live](../live/index.mdx) | Monetize live streams instead. | diff --git a/ads/workflows/vod/static-assets.mdx b/ads/workflows/vod/static-assets.mdx new file mode 100644 index 000000000000..d602b7bb721c --- /dev/null +++ b/ads/workflows/vod/static-assets.mdx @@ -0,0 +1,107 @@ +--- +sidebar_position: 1 +sidebar_label: Static assets +description: Play ad creatives from your own CDN in on-demand assets, without an ad server. +--- + +# Static assets on VOD + +import Layouts from '../_shared/_static-assets-layouts.mdx'; +import Formats from '../_shared/_static-assets-formats.mdx'; +import Troubleshooting from '../_shared/_static-assets-troubleshooting.mdx'; + +With static assets, each break points directly at its ad creatives: video or image files that you host on your own CDN. No ad server is involved — the SDK fetches the creative from the URL on the break and plays it when the viewer reaches the break. Use this workflow on movies, episodes, replays, and clips for direct-sold campaigns, sponsorships, promos, and branded overlays where you already know which creative to show. + +| | Static assets on VOD | +| -------------- | -------------------------------------------------------------------------- | +| Delivery mode | Server-guided (SGAI) | +| Ad decisioning | None: the break names the creative | +| Break creation | Scheduled at positions in the asset, or detected from the ad markers in it | +| Your app needs | The OptiView Ads SDK for your platform; nothing else | + +## Before you start + +- A [VOD channel](./index.mdx#set-up-a-vod-channel). The examples use the `mediatime` timebase. +- The OptiView Ads SDK in your app: [Web](../../player-integration/optiview-ads-sdk/web.mdx), [Android](../../player-integration/optiview-ads-sdk/android.mdx), [iOS](../../player-integration/optiview-ads-sdk/ios.mdx), or [React Native](../../player-integration/optiview-ads-sdk/react-native.mdx). Static assets need no ad server, no Google Ad Manager account, and no extra configuration in the app. +- Your creatives on a CDN that the viewers' devices can reach. + +## Schedule a break + +A static asset sets `type` to `static` and `uri` to the URL of the creative. On a `mediatime` channel, `start` is the position in the asset, in seconds. This mid-roll plays 10 minutes in, and viewers cannot skip it by seeking: + +```bash +curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//breaks' \ + -u "$ADS_API_KEY:$ADS_API_SECRET" \ + -H 'Content-Type: application/json' \ + -H 'X-Org-ID: ' \ + -d '{ + "start": 600, + "duration": 30, + "controls": { "snapback": true }, + "variant": { + "format": "single", + "assets": [ + { + "type": "static", + "mediaType": "video", + "mimeType": "application/x-mpegurl", + "uri": "https://cdn.example.com/ads/spot.m3u8", + "interaction": { "clickThrough": "https://www.example.com/offer" } + } + ] + } + }' +``` + +The `uri` can also be a list of URLs targeted per device type. See [Static assets](../../concepts/breaks.mdx#static-assets) and [Asset URI targeting](../../concepts/breaks.mdx#asset-uri-targeting) for the full asset model. + +### Pre-roll, post-roll, and pause ads + +Set `start` to a player event instead of a position: + +| Break | `start` | +| --------- | --------------------------------------- | +| Pre-roll | `{ "type": "event", "event": "start" }` | +| Post-roll | `{ "type": "event", "event": "end" }` | +| Pause ad | `{ "type": "event", "event": "pause" }` | + +A pause ad is typically an image in the `overlay` layout. See [Event based triggers](../../concepts/breaks.mdx#event-based-triggers). + +### Detect the breaks + +Instead of scheduling every break, add the asset as an [origin](../../concepts/origins.mdx) and configure a [marker rule](../../concepts/marker-detection.mdx) whose [template](../../concepts/templates.mdx) holds the static assets. Every matching ad marker in the asset, such as an SCTE-35 signal, becomes a break at its position. + +## How the break plays + +- The SDK fetches the channel's [Break Manifest](../../concepts/break-manifest.mdx) once when the session starts. It lists every break, and the SDK loads each creative shortly before its break. +- With `snapback`, a viewer who seeks past a break is taken back to the break first; afterwards, playback continues where the viewer was seeking to. Without it, viewers can skip the break by seeking. See [Seeking and snapback](./index.mdx#seeking-and-snapback). +- A break plays at most once per session. + +## Supported layouts + + + +## Creative formats + + + +## Tracking and reporting + +The SDK reports an OptiView Ads [impression](../../how-to-guides/ad-impressions.md) for every break it presents, and emits ad events — such as the start and end of each break and ad — that your app can listen to. See the API reference of your platform for the full list of events. + +Static assets carry no third-party tracking URLs. If an advertiser needs to count impressions in their own ad server, deliver the creative through a [VAST tag](./vast.mdx) instead: the VAST response carries the advertiser's tracking URLs, which are fired while the ad plays. + +## Troubleshooting + + + +## Related resources + +| Resource | Description | +| --------------------------------------------------------------- | ------------------------------------------------------------- | +| [VOD](./index.mdx) | VOD channels: timebase, seeking, and delivery modes. | +| [Breaks](../../concepts/breaks.mdx) | Layouts, variants, controls, and the asset model. | +| [Templates](../../concepts/templates.mdx) | Store a break with its static assets once, and reuse it. | +| [Your ad server (VAST) on VOD](./vast.mdx) | Let your ad server decide which creative to play. | +| [Static assets on live](../live/static-assets.mdx) | The same workflow for live streams. | +| [Ad impression tracking](../../how-to-guides/ad-impressions.md) | How OptiView Ads counts the breaks presented to your viewers. | diff --git a/ads/workflows/vod/vast.mdx b/ads/workflows/vod/vast.mdx new file mode 100644 index 000000000000..12c07277598f --- /dev/null +++ b/ads/workflows/vod/vast.mdx @@ -0,0 +1,114 @@ +--- +sidebar_position: 2 +sidebar_label: Your ad server (VAST) +description: Let your own ad server, or a partner's, decide the ads in on-demand assets through VAST tags. +--- + +# Your ad server (VAST) on VOD + +import AppNeeds from '../_shared/_vast-app.mdx'; +import Layouts from '../_shared/_vast-layouts.mdx'; +import Targeting from '../_shared/_vast-targeting.mdx'; +import Tracking from '../_shared/_vast-tracking.mdx'; +import Troubleshooting from '../_shared/_vast-troubleshooting.mdx'; + +With VAST, each break points at a VAST tag: a URL on your ad server, or an advertiser's, that returns a [VAST](https://iabtechlab.com/standards/vast/) XML document. The ad server decides which creative to play, and its response carries the media files and the tracking URLs. Use this workflow on movies, episodes, replays, and clips when you run your own ad server, or buy from partners that deliver their ads through VAST tags. + +| | Your ad server (VAST) on VOD | +| -------------- | -------------------------------------------------------------------------- | +| Delivery mode | Server-guided (SGAI) | +| Ad decisioning | Your ad server, per viewer, when the SDK requests the tag | +| Break creation | Scheduled at positions in the asset, or detected from the ad markers in it | +| Your app needs | The OptiView Ads SDK; on Web also Google's client-side IMA SDK | + +## Before you start + +- A [VOD channel](./index.mdx#set-up-a-vod-channel). The examples use the `mediatime` timebase. +- The OptiView Ads SDK in your app: [Web](../../player-integration/optiview-ads-sdk/web.mdx), [Android](../../player-integration/optiview-ads-sdk/android.mdx), [iOS](../../player-integration/optiview-ads-sdk/ios.mdx), or [React Native](../../player-integration/optiview-ads-sdk/react-native.mdx). +- A VAST tag URL from your ad server, or an advertiser's. + +## What your app needs + + + +## Schedule a break + +A VAST asset sets `type` to `vast` and `uri` to the VAST tag URL. On a `mediatime` channel, `start` is the position in the asset, in seconds. This mid-roll plays 10 minutes in, and viewers cannot skip it by seeking: + +```bash +curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//breaks' \ + -u "$ADS_API_KEY:$ADS_API_SECRET" \ + -H 'Content-Type: application/json' \ + -H 'X-Org-ID: ' \ + -d '{ + "start": 600, + "duration": 30, + "controls": { "snapback": true }, + "variant": { + "format": "single", + "assets": [ + { + "type": "vast", + "mediaType": "video", + "mimeType": "application/xml", + "uri": "https://adserver.example.com/vast?slot=midroll", + "assetParameters": { + "content_genre": "sports" + } + } + ] + } + }' +``` + +The `uri` can also be a list of tag URLs targeted per device type. See [VAST assets](../../concepts/breaks.mdx#vast-assets) and [Asset URI targeting](../../concepts/breaks.mdx#asset-uri-targeting) for the full asset model. + +### Pre-roll, post-roll, and pause ads + +Set `start` to a player event instead of a position: + +| Break | `start` | +| --------- | --------------------------------------- | +| Pre-roll | `{ "type": "event", "event": "start" }` | +| Post-roll | `{ "type": "event", "event": "end" }` | +| Pause ad | `{ "type": "event", "event": "pause" }` | + +See [Event based triggers](../../concepts/breaks.mdx#event-based-triggers). + +### Detect the breaks + +Instead of scheduling every break, add the asset as an [origin](../../concepts/origins.mdx) and configure a [marker rule](../../concepts/marker-detection.mdx) whose [template](../../concepts/templates.mdx) holds the VAST asset. Every matching ad marker in the asset becomes a break at its position. + +## How the break plays + +- The SDK fetches the channel's [Break Manifest](../../concepts/break-manifest.mdx) once when the session starts, and requests each VAST tag on the device shortly before the viewer reaches its break. Every viewer gets an individual ad decision. +- Viewers reach the breaks at different moments, so the requests to your ad server are spread over time. +- The break's `duration` is the maximum: use a VAST tag that returns the right ad length, because the SDK returns to your content when the duration is reached. +- With `snapback`, a viewer who seeks past a break is taken back to the break first. See [Seeking and snapback](./index.mdx#seeking-and-snapback). + +## Supported layouts + + + +## Ad targeting parameters + + + +## Tracking and reporting + + + +## Troubleshooting + + + +## Related resources + +| Resource | Description | +| -------------------------------------------------------------------- | ---------------------------------------------------- | +| [VOD](./index.mdx) | VOD channels: timebase, seeking, and delivery modes. | +| [Breaks](../../concepts/breaks.mdx) | Layouts, variants, controls, and the asset model. | +| [Ad targeting parameters](../../how-to-guides/ad-tag-parameters.mdx) | Passing targeting parameters to your ad server. | +| [Static assets on VOD](./static-assets.mdx) | Play creatives from your CDN without an ad server. | +| [Google Ad Manager on VOD](./google-ad-manager.mdx) | Let Google Ad Manager fill your breaks. | +| [Your ad server (VAST) on live](../live/vast.mdx) | The same workflow for live streams. | diff --git a/sidebarsAds.ts b/sidebarsAds.ts index adc727126457..0ad12873f04e 100644 --- a/sidebarsAds.ts +++ b/sidebarsAds.ts @@ -24,7 +24,22 @@ const sidebars: SidebarsConfig = { icon: '🔀', }, link: { type: 'doc', id: 'workflows/index' }, - items: ['workflows/live', 'workflows/vod', 'workflows/static-assets', 'workflows/vast', 'workflows/google-ad-manager'], + items: [ + { + type: 'category', + label: 'Live', + description: 'Monetize live streams and live events.', + link: { type: 'doc', id: 'workflows/live/index' }, + items: ['workflows/live/static-assets', 'workflows/live/vast', 'workflows/live/google-ad-manager'], + }, + { + type: 'category', + label: 'VOD', + description: 'Monetize on-demand assets.', + link: { type: 'doc', id: 'workflows/vod/index' }, + items: ['workflows/vod/static-assets', 'workflows/vod/vast', 'workflows/vod/google-ad-manager'], + }, + ], }, { type: 'category', From f2b366eda5bb1aeed22f4dbf12d22df1d7ae5941 Mon Sep 17 00:00:00 2001 From: Maarten Rimaux Date: Fri, 23 Oct 2026 11:17:00 +0200 Subject: [PATCH 5/7] Ads: name layouts, drop Google opt-out and upgrade notes, simplify workflow matrix --- .../optiview-ads-sdk/index.mdx | 2 +- ads/workflows/_shared/_gam-app.mdx | 4 -- .../_shared/_gam-troubleshooting.mdx | 10 ++-- ads/workflows/_shared/_gam-turn-off.mdx | 51 ------------------- .../_shared/_static-assets-layouts.mdx | 18 ++++--- ads/workflows/_shared/_vast-app.mdx | 4 -- ads/workflows/_shared/_vast-layouts.mdx | 17 ++++--- ads/workflows/index.mdx | 12 ++--- ads/workflows/live/google-ad-manager.mdx | 5 -- ads/workflows/vod/google-ad-manager.mdx | 5 -- 10 files changed, 32 insertions(+), 96 deletions(-) delete mode 100644 ads/workflows/_shared/_gam-turn-off.mdx diff --git a/ads/player-integration/optiview-ads-sdk/index.mdx b/ads/player-integration/optiview-ads-sdk/index.mdx index 519cdac773dd..6d2381f70e17 100644 --- a/ads/player-integration/optiview-ads-sdk/index.mdx +++ b/ads/player-integration/optiview-ads-sdk/index.mdx @@ -45,7 +45,7 @@ Neither level holds ad server URLs or accounts. What to play, and where to fetch | `player` | The adapter that wraps your content player. **Required.** | | `container` | The element or view in which the SDK renders ads, stacked above your content player. **Required.** | | `mode` | Optional. The ad insertion model: `sgai` (server-guided) or `ssai` (server-side, for streams where the ads are stitched into the media stream). By default the SDK uses the mode the channel's delivery rules set for the device, and `sgai` when there are none; set it only to override the channel. | -| `gam` | Optional. Google Ad Manager starts automatically when the Break Manifest carries a Google configuration; set `enabled` to `false` to keep Google out of a session. See [Google Ad Manager](../../workflows/live/google-ad-manager.mdx#turn-google-off-for-a-session). | +| `gam` | Optional. Google Ad Manager configuration. Google Ad Manager starts automatically when the Break Manifest carries a Google configuration. See [Google Ad Manager](../../workflows/live/google-ad-manager.mdx). | | `debug` | Enables verbose logging during development. | The SDK also exposes optional presentation settings — such as ad preloading, break chaining, and tune-in behavior — with sensible defaults. The platform pages describe the platform-specific options. diff --git a/ads/workflows/_shared/_gam-app.mdx b/ads/workflows/_shared/_gam-app.mdx index c3d562101afa..389f93bb2ef6 100644 --- a/ads/workflows/_shared/_gam-app.mdx +++ b/ads/workflows/_shared/_gam-app.mdx @@ -14,7 +14,3 @@ On Web, add the IMA DAI loader to your page: ``` If your channel also has VAST breaks, load `ima3.js` as well; the two scripts work side by side. - -:::note[Upgrading from an earlier integration] -Earlier versions of this guide set a `networkCode` in the `gam` configuration and a `customAssetKey` in the session configuration. The SDK no longer accepts them: remove both, and the SDK takes the values from the Break Manifest. -::: diff --git a/ads/workflows/_shared/_gam-troubleshooting.mdx b/ads/workflows/_shared/_gam-troubleshooting.mdx index 86369507796a..55113dccd5c6 100644 --- a/ads/workflows/_shared/_gam-troubleshooting.mdx +++ b/ads/workflows/_shared/_gam-troubleshooting.mdx @@ -1,7 +1,7 @@ -| Diagnostic | What it means | What to do | -| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -| `DA-GAM-CONFIG-RESOLVED` | Informational: the Google stream session uses the network code and asset key in the diagnostic. | Check that they match your Google stream. | -| `DA-GAM-CONFIG-MISSING` | The Break Manifest carries Google breaks but no usable Google configuration, or Google is turned off with `gam` `enabled: false`. | Check that the channel is connected to Google, or remove the opt-out. | -| `DA-GAM-SESSION-FAILED` | The Google stream session could not be started. | On Web, load `ima3_dai.js` on the page. Otherwise, check the error message in the diagnostic. | +| Diagnostic | What it means | What to do | +| ------------------------ | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `DA-GAM-CONFIG-RESOLVED` | Informational: the Google stream session uses the network code and asset key in the diagnostic. | Check that they match your Google stream. | +| `DA-GAM-CONFIG-MISSING` | The Break Manifest carries Google breaks but no usable Google configuration. | Check that the channel is connected to Google. | +| `DA-GAM-SESSION-FAILED` | The Google stream session could not be started. | On Web, load `ima3_dai.js` on the page. Otherwise, check the error message in the diagnostic. | Breaks that fail in the backend, for example because Google could not decision them in time, end up in the `ERROR` state and never reach the SDK. See [Troubleshooting](../../integrations/google/pod-serving.mdx#troubleshooting) on the Google Pod Serving integration page for the possible reasons. diff --git a/ads/workflows/_shared/_gam-turn-off.mdx b/ads/workflows/_shared/_gam-turn-off.mdx deleted file mode 100644 index 4459002a3ec9..000000000000 --- a/ads/workflows/_shared/_gam-turn-off.mdx +++ /dev/null @@ -1,51 +0,0 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -To keep Google out of a session — for example until the viewer gives consent, or in a build that must not contact Google — set `enabled` to `false` in the `gam` configuration. The SDK then skips the Google breaks in that session and reports `DA-GAM-CONFIG-MISSING`. - - - - -```typescript -const sdk = new OptiViewAds({ - player: new THEOplayerAdapter(player, container), - container: document.getElementById('container'), - gam: { enabled: false }, -}); -``` - - - - -```kotlin -val sdk = OptiViewAds( - config = OptiViewAdsConfig( - player = THEOplayerAdapter(theoPlayerView.player), - gam = GamConfig(enabled = false), - ), - renderer = OverlayAdRenderer(adContainer), -) -``` - - - - -```swift -let sdk = OptiViewAds( - config: OptiViewAdsConfig( - player: THEOplayerAdapter(player: theoplayer), - gam: GamConfig(enabled: false) - ), - renderer: OverlayAdRenderer(container: adContainer) -) -``` - - - - -```typescript -const ads = createOptiViewAds(player, { gam: { enabled: false } }); -``` - - - diff --git a/ads/workflows/_shared/_static-assets-layouts.mdx b/ads/workflows/_shared/_static-assets-layouts.mdx index 962933f4c04b..61e29571fa97 100644 --- a/ads/workflows/_shared/_static-assets-layouts.mdx +++ b/ads/workflows/_shared/_static-assets-layouts.mdx @@ -1,11 +1,13 @@ -Static assets work in every [layout](../../concepts/breaks.mdx#layouts) and as [pause ads](../../concepts/breaks.mdx#pause): +Static assets work in every [layout](../../concepts/breaks.mdx#layouts): -| Layout | Static asset | -| --------------------- | ---------------------------------------------------------------------------------------- | -| `single` | A video that replaces the content. | -| `double`, `lshape_ad` | A video, with an image or video `companion` that fills the background. | -| `lshape_content` | An image that fills the L-shaped backdrop while your content keeps playing. | -| `overlay` | An image or video on top of your content. | -| Pause ad | An image, or a progressive MP4 video that plays muted, shown while the viewer is paused. | +| Layout | Static asset | +| --------------- | ----------------------------------------------------------------------------- | +| Single | A video that replaces the content. | +| Double box | A video next to your content, with an image or video `companion` behind both. | +| L-shape ad | A video, with an image or video `companion` that fills the L-shaped backdrop. | +| L-shape content | An image that fills the L-shaped backdrop while your content keeps playing. | +| Overlay | An image or video on top of your content. | An image stays on screen for the asset's `duration`, or for the break's `duration` when the asset has none. + +Static assets can also be used for [pause ads](../../concepts/breaks.mdx#pause): an image, or a progressive MP4 video that plays muted, shown while the viewer is paused. diff --git a/ads/workflows/_shared/_vast-app.mdx b/ads/workflows/_shared/_vast-app.mdx index 8c6b141c9d2e..3b1c56f7d71b 100644 --- a/ads/workflows/_shared/_vast-app.mdx +++ b/ads/workflows/_shared/_vast-app.mdx @@ -14,7 +14,3 @@ On Web, add the IMA loader to your page: ``` Without it, the SDK cannot play VAST breaks: it reports `DA-VAST-IMA-SDK-MISSING` and returns to your content. If your channel also has Google Ad Manager breaks, load `ima3_dai.js` as well; the two scripts work side by side. - -:::caution[Web: include an MP4 media file] -The IMA SDK for HTML5 plays the ad through the browser's own video element, which cannot play HLS outside Safari. Make sure your VAST responses include a progressive MP4 media file, or the ad fails to play in Chrome, Edge, and Firefox. -::: diff --git a/ads/workflows/_shared/_vast-layouts.mdx b/ads/workflows/_shared/_vast-layouts.mdx index 4234a9cf1271..6a7721bc813f 100644 --- a/ads/workflows/_shared/_vast-layouts.mdx +++ b/ads/workflows/_shared/_vast-layouts.mdx @@ -1,10 +1,13 @@ -VAST describes a linear (video) ad, so VAST assets work in the layouts where an ad video plays: +VAST describes a linear (video) ad, so VAST assets work in the [layouts](../../concepts/breaks.mdx#layouts) where an ad video plays: -| Layout | VAST asset | -| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `single` | Supported. | -| `double`, `lshape_ad` | Supported. The VAST ad plays in the ad box, and the asset's `companion` fills the background. | -| `lshape_content`, `overlay` | Not supported. The SDK does not play the asset and reports `DA-VAST-UNSUPPORTED-FORMAT`. Use a static asset instead. | -| Pause ad | Supported. The SDK reads the image from the VAST companion ads, or a progressive MP4 from the linear ad, and fires its impression tracking when shown. | +| Layout | VAST asset | +| --------------- | -------------------------------------------------------------------------------------------------------------------- | +| Single | Supported. | +| Double box | Supported. The VAST ad plays in the ad box, and the asset's `companion` fills the background. | +| L-shape ad | Supported. The VAST ad plays in the ad window, and the asset's `companion` fills the L-shaped backdrop. | +| L-shape content | Not supported. The SDK does not play the asset and reports `DA-VAST-UNSUPPORTED-FORMAT`. Use a static asset instead. | +| Overlay | Not supported. The SDK does not play the asset and reports `DA-VAST-UNSUPPORTED-FORMAT`. Use a static asset instead. | + +VAST assets can also be used for [pause ads](../../concepts/breaks.mdx#pause): the SDK reads the image from the VAST companion ads, or a progressive MP4 from the linear ad, and fires its impression tracking when shown. VAST breaks play in server-guided (SGAI) sessions only. diff --git a/ads/workflows/index.mdx b/ads/workflows/index.mdx index 3bb2e74c654f..54b3923c6e50 100644 --- a/ads/workflows/index.mdx +++ b/ads/workflows/index.mdx @@ -12,7 +12,7 @@ OptiView Ads is a **hybrid ad insertion platform**: the same channel and the sam 2. **Ad source** — where do the ads come from: static assets from your CDN, your ad server through VAST tags, or Google Ad Manager? 3. **Delivery mode** — does the player insert the ads (SGAI), or are they stitched into the stream (SSAI)? -Pick your use case and ad source in the [table below](#supported-workflows): each combination has its own page with everything you need to set it up. +Start from your use case, [Live](./live/index.mdx) or [VOD](./vod/index.mdx): each has a page per ad source with everything you need to set it up. ## Hybrid ad insertion: SGAI and SSAI @@ -43,11 +43,11 @@ Live and VOD are different use cases, and a channel is created for one of them. Every ad source works for both live and VOD. One channel, and even one break, can mix ad sources. -| Ad source | What the break carries | Live | VOD | What your app needs | -| --------------------- | ----------------------------------------------------- | ------------------------------------------- | ------------------------------------------ | -------------------------------------------------------------------------- | -| Static assets | Direct URLs to video or image creatives on your CDN. | [SGAI](./live/static-assets.mdx) | [SGAI](./vod/static-assets.mdx) | Nothing beyond the SDK integration. | -| Your ad server (VAST) | A VAST tag URL on your ad server, or an advertiser's. | [SGAI](./live/vast.mdx) | [SGAI](./vod/vast.mdx) | On Web, Google's client-side IMA SDK (`ima3.js`). | -| Google Ad Manager | An ad pod decisioned by Google Ad Manager 360. | [SGAI + SSAI](./live/google-ad-manager.mdx) | [SGAI + SSAI](./vod/google-ad-manager.mdx) | On Web, Google's IMA DAI SDK (`ima3_dai.js`). Google Ad Manager 360 setup. | +| Ad source | What the break carries | Delivery mode | What your app needs | +| --------------------- | ----------------------------------------------------- | ------------- | -------------------------------------------------------------------------- | +| Static assets | Direct URLs to video or image creatives on your CDN. | SGAI | Nothing beyond the SDK integration. | +| Your ad server (VAST) | A VAST tag URL on your ad server, or an advertiser's. | SGAI | On Web, Google's client-side IMA SDK (`ima3.js`). | +| Google Ad Manager | An ad pod decisioned by Google Ad Manager 360. | SGAI + SSAI | On Web, Google's IMA DAI SDK (`ima3_dai.js`). Google Ad Manager 360 setup. | ### Which ad source should I use? diff --git a/ads/workflows/live/google-ad-manager.mdx b/ads/workflows/live/google-ad-manager.mdx index dd5d4e9bc08b..940759563746 100644 --- a/ads/workflows/live/google-ad-manager.mdx +++ b/ads/workflows/live/google-ad-manager.mdx @@ -8,7 +8,6 @@ description: Let Google Ad Manager 360 fill the breaks of a live stream, server- import AppNeeds from '../_shared/_gam-app.mdx'; import SsaiSession from '../_shared/_gam-ssai-session.mdx'; -import TurnOff from '../_shared/_gam-turn-off.mdx'; import Targeting from '../_shared/_gam-targeting.mdx'; import Troubleshooting from '../_shared/_gam-troubleshooting.mdx'; @@ -82,10 +81,6 @@ curl -X POST 'https://us.ads.optiview.dolby.com/api/v1/channels//bre -### Turn Google off for a session - - - ## Ad targeting parameters diff --git a/ads/workflows/vod/google-ad-manager.mdx b/ads/workflows/vod/google-ad-manager.mdx index 7b39cc964fce..c40abd5fb98c 100644 --- a/ads/workflows/vod/google-ad-manager.mdx +++ b/ads/workflows/vod/google-ad-manager.mdx @@ -8,7 +8,6 @@ description: Let Google Ad Manager 360 fill the breaks of on-demand assets, serv import AppNeeds from '../_shared/_gam-app.mdx'; import SsaiSession from '../_shared/_gam-ssai-session.mdx'; -import TurnOff from '../_shared/_gam-turn-off.mdx'; import Targeting from '../_shared/_gam-targeting.mdx'; import Troubleshooting from '../_shared/_gam-troubleshooting.mdx'; @@ -87,10 +86,6 @@ Instead of scheduling every break, add the asset as an [origin](../../concepts/o -### Turn Google off for a session - - - ## Ad targeting parameters From 5e7b8fb2205d62f63e19fbb6d4b9b47b5b7b0ec2 Mon Sep 17 00:00:00 2001 From: Maarten Rimaux Date: Fri, 23 Oct 2026 14:51:14 +0200 Subject: [PATCH 6/7] Ads: add asset parameter macros guide, trim legacy notes --- ads/getting-started/index.mdx | 2 +- ads/how-to-guides/ad-tag-parameters.mdx | 17 +- ads/how-to-guides/asset-parameter-macros.mdx | 270 ++++++++++++++++++ ads/integrations/google/pod-serving.mdx | 2 +- .../optiview-ads-sdk/index.mdx | 8 +- 5 files changed, 281 insertions(+), 18 deletions(-) create mode 100644 ads/how-to-guides/asset-parameter-macros.mdx diff --git a/ads/getting-started/index.mdx b/ads/getting-started/index.mdx index bdc575e36143..9f98da987adb 100644 --- a/ads/getting-started/index.mdx +++ b/ads/getting-started/index.mdx @@ -125,7 +125,7 @@ Start playback of your stream on your device. Shortly before the scheduled start You can follow along on both sides: -- **In the dashboard or API:** the break's [lifecycle status](/ads/concepts/breaks#break-lifecycle) is `READY` (a Google pod break passes through `PREPARING` first), and moves to `SIGNALED` once it is announced to players. +- **In the dashboard or API:** the break's [lifecycle status](/ads/concepts/breaks#break-lifecycle) is `READY`, and moves to `SIGNALED` once it is announced to players. - **In the player:** the ad plays at the scheduled time and your content resumes afterwards. If the break does not play, verify that the Break Manifest URL from step 2 returns the break, and that your stream carries the time metadata required by the channel's timebase. diff --git a/ads/how-to-guides/ad-tag-parameters.mdx b/ads/how-to-guides/ad-tag-parameters.mdx index 42dae32a92b7..c93028a8a8ce 100644 --- a/ads/how-to-guides/ad-tag-parameters.mdx +++ b/ads/how-to-guides/ad-tag-parameters.mdx @@ -7,8 +7,8 @@ sidebar_position: 3 When an ad server decides which ad fills a break, you can pass key-value parameters with the ad request to personalize the ads — for example the content genre, the placement type, or custom targeting values. In OptiView Ads, these parameters are called **`assetParameters`**. How they reach the ad server depends on the [ad workflow](../workflows/index.mdx): - **[VAST](../workflows/live/vast.mdx):** the SDK appends them to the VAST tag URL as URL-encoded query parameters. -- **[Google Ad Manager](../workflows/live/google-ad-manager.mdx):** they are sent to Google as [ad tag parameters](https://support.google.com/admanager/answer/10678356) (`adTagParameters`). -- **[Static assets](../workflows/live/static-assets.mdx)** involve no ad request, so they do not use `assetParameters`. +- **[Google Ad Manager](../workflows/live/google-ad-manager.mdx):** they are sent to Google as ad tag parameters (`adTagParameters`). See Google's [list of all recognized ad tag parameters](https://support.google.com/admanager/answer/10678356#expand-all). +- **[Static assets](../workflows/live/static-assets.mdx):** the SDK appends them as query parameters to the URL of the creative it requests. You can set `assetParameters` in two places: on the break in the **backend**, and in the **OptiView Ads SDK** on the client. @@ -71,17 +71,9 @@ As a rule of thumb: ## Macros -A parameter value can contain macros: `$NAME$` tokens that the SDK replaces when it builds the ad request. Macros let a value on the break carry information that is only known on the device. The SDK provides these built-in macros: +A parameter value can contain macros: `$NAME$` tokens that the SDK replaces with a value from the device when it builds the ad request. For example, `"size": "$OPTIVIEW_PLAYER_WIDTH$x$OPTIVIEW_PLAYER_HEIGHT$"` is sent as `size=1920x1080`. The SDK has built-in macros for the player size, the ad duration, and the user agent, and your app can register its own. -| Macro | Value | -| ----------------------------------- | ---------------------------------------------------------------------------- | -| `$OPTIVIEW_PLAYER_WIDTH$` | Width of the ad container, in logical pixels. | -| `$OPTIVIEW_PLAYER_HEIGHT$` | Height of the ad container, in logical pixels. | -| `$OPTIVIEW_BREAK_DURATION_SECONDS$` | Duration of the ad, in seconds: the asset's `duration`, else the break's. | -| `$OPTIVIEW_BREAK_DURATION_MS$` | The same duration, in whole milliseconds. | -| `$OPTIVIEW_USER_AGENT$` | The user agent of the device. Not available on iOS; register your own value. | - -For example, `"size": "$OPTIVIEW_PLAYER_WIDTH$x$OPTIVIEW_PLAYER_HEIGHT$"` is sent as `size=1920x1080`. You can register your own macros, or override a built-in one, with `assetParameterMacros` in the session configuration. Tokens the SDK does not know, such as `$PUBLISHER_ID$`, are sent unchanged, so your ad server can still expand its own macros. See `SessionConfig` in the API reference of your platform for the details. +See [Asset parameter macros](./asset-parameter-macros.mdx) for how macros work, the built-in macros, registering and updating your own, and leaving out a parameter with an empty macro. ## Platform examples @@ -153,6 +145,7 @@ ads.updateAssetParameters({ cust_params: 'sport=basketball' }); | Resource | Description | | -------------------------------------------------------------------- | ----------------------------------------------- | +| [Asset parameter macros](./asset-parameter-macros.mdx) | Device values in parameter values. | | [VAST](../workflows/live/vast.mdx) | Playing VAST tags with the SDK. | | [Google Ad Manager](../workflows/live/google-ad-manager.mdx) | Playing Google pods with the SDK. | | [Google Pod Serving](../integrations/google/pod-serving.mdx) | Required Google parameters and pod decisioning. | diff --git a/ads/how-to-guides/asset-parameter-macros.mdx b/ads/how-to-guides/asset-parameter-macros.mdx new file mode 100644 index 000000000000..9a00d0b8d2d0 --- /dev/null +++ b/ads/how-to-guides/asset-parameter-macros.mdx @@ -0,0 +1,270 @@ +--- +sidebar_position: 3.5 +sidebar_label: Asset parameter macros +--- + +# Asset parameter macros + +A break is defined once in the backend, but some targeting values are only known on the viewer's device: the size of the player, the length of the ad slot, the viewer's team, or a consent string. **Macros** bridge that gap. A macro is a placeholder token inside an [asset parameter](./ad-tag-parameters.mdx) value. The OptiView Ads SDK replaces it with the actual value on the device, at the moment it builds the ad request. + +## How macros work + +A macro is a token of the form `$NAME$`: a `$`, a name made of letters, digits, and underscores, and a closing `$`. Put one or more tokens anywhere in a parameter value, on the break, in the session configuration, or in an `updateAssetParameters()` call: + +```json +{ + "type": "vast", + "mediaType": "video", + "uri": "https://adserver.example.com/vast?slot=midroll", + "assetParameters": { + "size": "$OPTIVIEW_PLAYER_WIDTH$x$OPTIVIEW_PLAYER_HEIGHT$", + "team": "$TEAM$" + } +} +``` + +When the SDK requests this VAST tag on a 1920×1080 player, for a viewer whose app registered `$TEAM$` as `ajax`, the request becomes: + +```text +https://adserver.example.com/vast?slot=midroll&size=1920x1080&team=ajax +``` + +The rules: + +- **Resolved per ad request.** The SDK fills in the macros every time it builds an ad request, so a value that changes during the session, such as the player size, is always current. +- **Whole tokens only.** Matching is case-sensitive and uses the full token: `$APP$` never matches inside `$APP_NAME$`. +- **Several tokens per value.** A value can combine text and any number of tokens, as `size` does above. +- **A lone `$` is left alone.** A `$` without a closing `$`, and forms such as `$$` or `${NAME}`, are not macros and are sent unchanged. + +## Where macros apply + +The SDK resolves macros in every asset parameter it sends, for every ad source: + +| Ad source | Where the resolved parameters go | +| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Static assets | Appended as query parameters to the URL the SDK requests: the asset's `uri`, a static companion, or a pause ad. For HLS and DASH, only the master playlist or MPD request carries them. | +| VAST | Appended as query parameters to the VAST tag URL. | +| Google Ad Manager | Sent to Google as ad tag parameters (`adTagParameters`). | + +:::caution[Signed static asset URLs] +Do not use asset parameters on a static asset with a signed URL or a URL that carries an access token. The added query parameters can invalidate the signature. Parameters set in the SDK are added to every static asset request in the session. +::: + +## Built-in macros + +The SDK provides these macros on every platform, unless noted: + +| Macro | Value | +| ----------------------------------- | ------------------------------------------------------------------------------------- | +| `$OPTIVIEW_PLAYER_WIDTH$` | Width of the ad container, in logical pixels. | +| `$OPTIVIEW_PLAYER_HEIGHT$` | Height of the ad container, in logical pixels. | +| `$OPTIVIEW_BREAK_DURATION_SECONDS$` | Duration of the ad, in seconds: the asset's `duration`, otherwise the break's. | +| `$OPTIVIEW_BREAK_DURATION_MS$` | The same duration, in whole milliseconds. | +| `$OPTIVIEW_USER_AGENT$` | The user agent of the device. Not available on iOS and tvOS: register your own value. | + +The names are also exported by the SDK, so you do not have to type them: `OPTIVIEW_ASSET_PARAMETER_MACROS` on Web and React Native, `OptiViewAssetParameterMacros` on Android, iOS, and tvOS. + +## Register your own macros + +Register your own macros with `assetParameterMacros` in the session configuration. Each macro is keyed by its full token, including both `$` signs, and its value is either fixed or a callback. The SDK calls a callback each time it builds an ad request, so it can return the current value. + +To override a built-in macro, register the same name: your value wins. + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + +```typescript +await sdk.startSession({ + manifestUrl: 'https://us.markers.optiview.dolby.com/manifest/v1/ORG-ID/channels/CHANNEL-ID', + assetParameterMacros: { + $SEGMENT$: 'sports', + $TEAM$: () => currentTeam(), + }, +}); +``` + + + + +```kotlin +sdk.startSession( + SessionConfig( + manifestUrl = "https://us.markers.optiview.dolby.com/manifest/v1/ORG-ID/channels/CHANNEL-ID", + assetParameterMacros = mapOf( + "\$SEGMENT\$" to { "sports" }, + "\$TEAM\$" to { currentTeam() }, + ), + ) +) +``` + +A fixed value is a callback that always returns the same string. + + + + +```swift +try await sdk.startSession( + SessionConfig( + manifestUrl: "https://us.markers.optiview.dolby.com/manifest/v1/ORG-ID/channels/CHANNEL-ID", + assetParameterMacros: [ + "$SEGMENT$": { "sports" }, + "$TEAM$": { currentTeam() }, + "$OPTIVIEW_USER_AGENT$": { userAgent }, + ] + ) +) +``` + +A fixed value is a closure that always returns the same string. iOS and tvOS have no built-in user agent, so register `$OPTIVIEW_USER_AGENT$` yourself if your ad server needs it. + + + + +```typescript +await ads.startSession({ + manifestUrl: 'https://us.markers.optiview.dolby.com/manifest/v1/ORG-ID/channels/CHANNEL-ID', + assetParameterMacros: { + $SEGMENT$: 'sports', + $TEAM$: () => currentTeam(), + }, +}); +``` + + + + +Registered macros are cleared when the session ends. + +### Update macros during a session + +Call `updateAssetParameterMacros()` to change macros while the session runs, for example when the viewer switches teams. The call merges the given names into the session's macros; names you leave out keep their current value. The new values apply to the next ad request: an ad that has already been requested is not requested again. + + + + +```typescript +sdk.updateAssetParameterMacros({ $TEAM$: 'psv' }); +``` + + + + +```kotlin +sdk.updateAssetParameterMacros(mapOf("\$TEAM\$" to { "psv" })) +``` + + + + +```swift +sdk.updateAssetParameterMacros(["$TEAM$": { "psv" }]) +``` + + + + +```typescript +await ads.updateAssetParameterMacros({ $TEAM$: 'psv' }); +``` + + + + +To remove a macro you registered, pass `undefined` for it on Web and React Native, or `null` on Android and `nil` on iOS. A built-in macro with the same name then applies again. + +## Leave out a parameter with an empty macro + +Sometimes a parameter must not be sent at all, for example a consent string before the viewer has given consent. Mark the macro **empty**, and the SDK leaves out every parameter that uses it: + + + + +```typescript +await sdk.startSession({ + manifestUrl: 'https://us.markers.optiview.dolby.com/manifest/v1/ORG-ID/channels/CHANNEL-ID', + assetParameterMacros: { + $CONSENT$: () => (hasConsent() ? consentString() : null), + }, +}); +``` + +On Web and React Native, `null` marks a macro empty. + + + + +```kotlin +sdk.startSession( + SessionConfig( + manifestUrl = "https://us.markers.optiview.dolby.com/manifest/v1/ORG-ID/channels/CHANNEL-ID", + assetParameterMacroValues = mapOf( + "\$CONSENT\$" to { + if (hasConsent()) AssetParameterMacroValue.Text(consentString()) + else AssetParameterMacroValue.Empty + }, + ), + ) +) +``` + +On Android, register the macro in `assetParameterMacroValues` and return `AssetParameterMacroValue.Empty`. Use `updateAssetParameterMacroValues()` to change such a macro during the session. + + + + +```swift +try await sdk.startSession( + SessionConfig( + manifestUrl: "https://us.markers.optiview.dolby.com/manifest/v1/ORG-ID/channels/CHANNEL-ID", + assetParameterMacroValues: [ + "$CONSENT$": { hasConsent() ? .text(consentString()) : .empty }, + ] + ) +) +``` + +On iOS and tvOS, register the macro in `assetParameterMacroValues` and return `.empty`. Use `updateAssetParameterMacros(values:)` to change such a macro during the session. + + + + +```typescript +await ads.startSession({ + manifestUrl: 'https://us.markers.optiview.dolby.com/manifest/v1/ORG-ID/channels/CHANNEL-ID', + assetParameterMacros: { + $CONSENT$: () => (hasConsent() ? consentString() : null), + }, +}); +``` + + + + +What is left out depends on the value: + +| Parameter value | What the SDK leaves out | +| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| A plain value, such as `"gdpr_consent": "$CONSENT$"` | The whole parameter. | +| Google Ad Manager `cust_params`, such as `"genre=sports&consent=$CONSENT$"` | Only the `&`-separated pair with the empty macro: `cust_params=genre=sports` is still sent. If no pair is left, the whole parameter. | +| A static asset value with `&`-separated pairs | Only the pairs with the empty macro, as for `cust_params`. | +| A VAST `cust_params` value | The whole parameter. | + +## Tokens the SDK cannot fill in + +A token without a value is never removed: the SDK sends the parameter with the token as it is. + +- **Your ad server's own macros.** A token that is neither built in nor registered, such as `$PUBLISHER_ID$`, is sent unchanged. Your ad server can then expand it on its side. +- **A built-in macro without a value**, such as `$OPTIVIEW_USER_AGENT$` on iOS, an unknown `$OPTIVIEW_*` name, or a registered macro whose callback returns no value, is also sent unchanged. The SDK reports it with the `DA-ASSET-MACRO-UNKNOWN` diagnostic, so you can spot a missing value during development. + +## Related resources + +| Resource | Description | +| -------------------------------------------------------------------- | -------------------------------------------------------------- | +| [Ad targeting parameters](./ad-tag-parameters.mdx) | Where asset parameters are set, and how the layers are merged. | +| [Static assets on live](../workflows/live/static-assets.mdx) | Playing creatives from your CDN. | +| [Your ad server (VAST) on live](../workflows/live/vast.mdx) | Playing VAST tags with the SDK. | +| [Google Ad Manager on live](../workflows/live/google-ad-manager.mdx) | Playing Google pods with the SDK. | diff --git a/ads/integrations/google/pod-serving.mdx b/ads/integrations/google/pod-serving.mdx index f3ea35da750b..9ad87bb1aada 100644 --- a/ads/integrations/google/pod-serving.mdx +++ b/ads/integrations/google/pod-serving.mdx @@ -77,7 +77,7 @@ Google performs the decisioning, so no asset URI is needed: once Google has deci The optional `assetParameters` map contains the [Google ad tag parameters](https://support.google.com/admanager/answer/10678356) (`adTagParameters`) for the break. OptiView Ads forwards them to Google when the break is announced, and delivers them to the player through the Break Manifest so they are included on the pod request. -Players can extend these parameters. The OptiView Ads SDK accepts `assetParameters` in its session configuration; when the same parameter is set both on the break and in the SDK, the break's value wins. See [Ad targeting parameters](../../how-to-guides/ad-tag-parameters.mdx) for the SDK API on each platform. The legacy OptiView Player SDKs accept `adTagParameters` on the ad description (`TheoAdDescription`); there, the player-side value wins. +Players can extend these parameters. The OptiView Ads SDK accepts `assetParameters` in its session configuration; when the same parameter is set both on the break and in the SDK, the break's value wins. See [Ad targeting parameters](../../how-to-guides/ad-tag-parameters.mdx) for the SDK API on each platform. As a rule of thumb: diff --git a/ads/player-integration/optiview-ads-sdk/index.mdx b/ads/player-integration/optiview-ads-sdk/index.mdx index 6d2381f70e17..694ba9bfd722 100644 --- a/ads/player-integration/optiview-ads-sdk/index.mdx +++ b/ads/player-integration/optiview-ads-sdk/index.mdx @@ -52,10 +52,10 @@ The SDK also exposes optional presentation settings — such as ad preloading, b ### Session configuration -| Property | Description | -| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `manifestUrl` | The channel's Break Manifest URL. **Required.** See [Retrieving the required values](#retrieving-the-required-values). | -| `assetParameters` | Session-level ad targeting parameters for VAST and Google Ad Manager breaks: appended to VAST tag URLs, or sent to Google as `adTagParameters`. Static assets do not use them. See [Ad targeting parameters](../../how-to-guides/ad-tag-parameters.mdx). | +| Property | Description | +| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `manifestUrl` | The channel's Break Manifest URL. **Required.** See [Retrieving the required values](#retrieving-the-required-values). | +| `assetParameters` | Session-level ad targeting parameters: appended to static asset and VAST tag URLs, or sent to Google as `adTagParameters`. See [Ad targeting parameters](../../how-to-guides/ad-tag-parameters.mdx). | ## Retrieving the required values From 347b33e2f40b92c8eb35b835378472e54ef14429 Mon Sep 17 00:00:00 2001 From: Maarten Rimaux Date: Fri, 23 Oct 2026 15:44:06 +0200 Subject: [PATCH 7/7] Ads: clarify empty macros in VAST values --- ads/how-to-guides/asset-parameter-macros.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ads/how-to-guides/asset-parameter-macros.mdx b/ads/how-to-guides/asset-parameter-macros.mdx index 9a00d0b8d2d0..a6db413376e0 100644 --- a/ads/how-to-guides/asset-parameter-macros.mdx +++ b/ads/how-to-guides/asset-parameter-macros.mdx @@ -251,7 +251,8 @@ What is left out depends on the value: | A plain value, such as `"gdpr_consent": "$CONSENT$"` | The whole parameter. | | Google Ad Manager `cust_params`, such as `"genre=sports&consent=$CONSENT$"` | Only the `&`-separated pair with the empty macro: `cust_params=genre=sports` is still sent. If no pair is left, the whole parameter. | | A static asset value with `&`-separated pairs | Only the pairs with the empty macro, as for `cust_params`. | -| A VAST `cust_params` value | The whole parameter. | + +For VAST, every value counts as a plain value, also one with `&`-separated pairs: the whole parameter is left out. ## Tokens the SDK cannot fill in