Skip to content

Examples ​

Three HTML5 reference repositories show four ways to integrate TrueX and IDVx ads into a CTV web app. The first repository contains two examples, one for each way ads are inserted:

ExampleRepositoryAd sourceAd break behavior
Manual CSAItruex-ctv-web-reference-appAd breaks defined in video-streams-csai.jsonThe app pauses the content, plays the ad pod itself, and resumes the content
Manual SSAItruex-ctv-web-reference-appAd breaks defined in video-streams-ssai.jsonThe ads are stitched into one video stream, so the app calculates the ad break times
Google IMA CSAItruex-ctv-google-ima-csai-ref-appA VAST ad playlist (sample-ad-playlist.xml)Google IMA requests and sequences client-side ads
Google IMA SSAItruex-ctv-google-ima-ssai-ref-appGoogle Ad Manager VAST tags stitched into the streamOne stream with stitched ad breaks, defined in video-streams.json

Each example has its own player, ad, and TruexAdRenderer code on purpose, so you can pick the one closest to your setup and read it from top to bottom. All of them are webpack apps that load the renderer from the @truex/ad-renderer package - see SDK Integration.

NOTE

The Google IMA apps may still construct the renderer from the VAST config URL as a legacy fallback. For new integrations, construct it from adParameters as described in Integration Flow. The Manual examples already accept an adParameters JSON object for IDVx ads.

Running the Apps ​

Requirements:

  • The Node version in the repository's .nvmrc (14.16 at the time of writing)

Run an app locally:

bash
npm install
npm start

The app is served at http://localhost:8080. To build a deployable version in the dist folder, run npm run build and host its contents. To test on a device, open your computer's local network address (for example http://192.168.1.72:8080) in the device's browser, or use it as the launcher URL of the device's app.

Each repository has platform-specific instructions under its platforms folder for Fire TV / Android TV, Vizio, LG, Tizen, PS4, PS5, and Xbox One.

While the app is running:

  • Select "4" or Menu on the remote, or click the left stick on the controller, to show the in-app debug console. The back action closes it.
  • Select "2" on the remote, or click the right stick on the controller, to skip the current ad break (Manual examples).

Shared Rules ​

All the examples follow the same rules, described in Integration Flow:

  • An ad with <AdSystem> trueX is a TrueX ad only when it is the first ad in the pod. An ad with <AdSystem> IDVx can be in any position.
  • The content and ad playback are paused before the renderer is created.
  • Each example has an InteractiveAd component (interactive-ad.js) that creates the renderer, subscribes to its events, calls init and start, and removes the ad overlay when a terminal event arrives.
  • adFreePod only sets a flag. The playback timeline moves when the terminal event arrives: with the flag set, the app skips the rest of the ad break; without it, the app plays the next ad in the pod.
  • The renderer is created with supportsUserCancelStream: true, so a user who backs out of the choice card closes the video.
  • The back action is handled with a popstate handler that ignores the renderer's own history state (onBackAction, pushBackActionBlock, and pushBackActionStub in main-csai.js, main-ssai.js, or main.js).

Manual CSAI ​

Repository: truex-ctv-web-reference-app. Open index-csai.html (main-csai.js, src/components/csai/), hosted at ctv.truex.com/web/ref-app/master/index-csai.html.

The ad breaks are defined in src/data/video-streams-csai.json:

  • timeOffset: the content time when the ad break starts
  • description: the VAST config URL of a TrueX ad
  • adParameters: the JSON configuration of an IDVx ad
  • mediaFile: the fallback video ad

Flow:

  1. The VideoController receives the video stream in startVideo, and setAdPlaylist creates an AdBreak for each ad break.
  2. When the content reaches a timeOffset, the content pauses and the ads play separately. No time adjustments are needed, because the ads are not part of the content timeline.
  3. For a TrueX or IDVx ad, an InteractiveAd creates the renderer and starts it.
  4. On a terminal event, skipAdBreak skips the rest of the ad break if the user earned adFreePod, or playNextAdInBreak plays the next ad. The content then resumes from the pause point.

Manual SSAI ​

Repository: truex-ctv-web-reference-app. Open index.html (main-ssai.js, src/components/ssai/), hosted at ctv.truex.com/web/ref-app/master/index.html.

The ad breaks are defined under the vmap key of src/data/video-streams-ssai.json:

  • timeOffset: the content time of the ad break
  • videoAdDuration: the total length of the stitched ads (placeholders and fallback ads) in seconds
  • ads: the ads of the break, each with adSystem (trueX, IDVx, or GDFP), duration, and description (VAST config URL) or adParameters (JSON)

Flow:

  1. The SSAI VideoController calculates the startTime and endTime of each ad break from its timeOffset and the durations of all the earlier ads, because the ads are stitched into the timeline. It subtracts the ad durations from the raw video position to get the content time.
  2. When playback reaches the start of an Infillion ad's placeholder, the app pauses and an InteractiveAd creates and starts the renderer.
  3. On a terminal event, skipAdBreak jumps past the end of the ad break if the user earned adFreePod; otherwise resumeAdBreak continues with the next stitched ad.

Google IMA CSAI ​

Repository: truex-ctv-google-ima-csai-ref-app. It uses the HTML5 Google IMA SDK for client-side ad insertion, with two versions of the same app:

VersionEntry pointHosted copy
Plain IMA SDK with your own HTML5 video elementsrc/simple/simple.js, simple-video-controller.jsindex.html
IMA with video.jssrc/videojs/videojs-demo.js, videojs-controller.jsvideojs-demo.html

The content is defined in src/data/video-streams.json, and the ads in src/data/sample-ad-playlist.xml, with a preroll and a midroll ad break that can contain TrueX and IDVx ads.

Flow:

  1. The video controller fields the IMA ad events in onAdEvent. On AdEvent.Type.STARTED, startInteractiveAd() identifies the ad: an <AdSystem> of trueX at pod position 1 is a TrueX ad, and IDVx is an IDVx ad. Any other ad keeps playing in the adsManager.
  2. For an Infillion ad, the app creates an InteractiveAd (src/components/interactive-ad.js), which creates the renderer and starts it. The trafficking parameters come from the IMA ad object (getTraffickingParametersString()).
  3. On a terminal event, skipAdBreak() discards the ad break if the user earned adFreePod; otherwise resumeAdPlayback() lets the adsManager play the next ad.

Google IMA SSAI ​

Repository: truex-ctv-google-ima-ssai-ref-app, hosted at ctv.truex.com/web/ref-app-google-IMA/master/index.html. It uses Google Ad Manager to stitch the ads into the video stream.

The content and its ad breaks, preroll and midroll-1, are defined in src/data/video-streams.json:

  • timeOffset: the content time where the ad break starts. The ads are stitched in, so the real video time is the content plus all the ad durations.
  • videoAdDuration: the length of the stitched fallback video
  • vastUrl: the VAST config URL of the Infillion ad

Flow:

  1. The VideoController (src/components/video-controller.js) receives the stream in startVideo, and setAdPlaylist creates an AdBreak for each entry of the vmap array.
  2. When onVideoTimeUpdate reaches the start of an ad break, an InteractiveAd creates and starts the renderer over the playback page.
  3. On a terminal event, the app seeks to the end of the placeholder if the user did not earn adFreePod, or to the end of the pod if they did, and playback continues.

The VAST responses served to Google Ad Manager are hosted on dedicated endpoints - a change there is eventually picked up by Google Ad Manager.

Integration documentation for Infillion Ads