TABLE OF CONTENTS
- 1. Introduction
- 2. Quick Start
- 3. SDK Initialization
- 4. Context & Placement Reference
- 5. API Reference
- 6. Error Handling & Compliance
- 7. Ad Fetching & VAST Parameters
- 8. Advanced Usage
- 9. Workflow diagram
- 10. Test placement ids & Demo page
- 11. FAQ & Troubleshooting
- 12. Appendix
1. Introduction
This document describes the Client-Side-Ad-Insertion (CSAI) integration of the SDK into the CTV Apps.
For the Server-Guided-Ad-Insertion (SGAI) integration please refer to these sections: Integration overview - SGAI and the Implementation Guide (SGAI).
The Teads CTV SDK is a TypeScript-based solution designed to enable seamless integration of VAST-compliant ad experiences into Connected TV (CTV) applications.
It provides a robust, event-driven API for fetching, managing, and displaying ads, with a focus on cross-platform compatibility (including older smart TV browsers), privacy compliance, and ease of integration.
Key Features:
- Simple integration via a loader script
- Support for InPlay and InPause ad placements
- Event-driven ad lifecycle management
- GDPR and privacy compliance
- Optimized for a wide range of CTV devices
Supported Platforms:
- Chromium-based Smart TVs (including legacy versions)
- Other modern smart TV browsers
- JavaScript/TypeScript client applications
Requirements:
- Internet access to load the SDK from the CDN
- Ability to inject JavaScript into your CTV app
- DOM access for ad rendering
2. Quick Start
2.1. Include the Loader Script
Add the following script tag to your application's HTML to load the SDK loader:
<script defer src="https://ctv.teads.tv/sdk/dist/loader.js"></script>
Note: The final loader URL may be updated. Please refer to the latest documentation or your Teads contact for the production URL.
2.2. Minimal Integration Example
Set up the window.teadsSdkReady
callback to initialize the SDK once it is loaded:
<script> window.teadsSdkReady = function() { // Define your application and placement contexts const appContext = { dom: { refElement: document.getElementById('ad-container'), videoElement: document.getElementById('main-video'), // optional }, application: { appId: 'YOUR_APP_ID', appStoreUrl: 'YOUR_APP_STORE_URL', }, contentMetaData: { genre: 'Documentary', language: 'en', livestream: false, network: 'NetworkName', channel: 'ChannelName', }, // Optionally add device and user info for GDPR/compliance }; const placementContext = { playerHeight: 1080, playerWidth: 1920, placementId: 241975, // Provided by Teads minDuration: 0, maxDuration: 60 }; // Create the SDK instance and initialize an InPlay placement const teadsSDK = window.teads.SDK.create(appContext); const inplayPlacement = teadsSDK.initInPlay(placementContext); // Listen for ad events inplayPlacement.addEventListener('adLoaded', function() { inplayPlacement.playAd(); }); // Load an ad inplayPlacement.loadAd(); }; </script> <!-- Somewhere in your HTML --> <div id="ad-container"> <video id="main-video"></video> </div>
This minimal example demonstrates how to load the SDK, set up the required contexts, initialize a placement, and load/play an ad.
For a more advanced integration, refer to the following sections.
3. SDK Initialization
3.1. Setting up window.teadsSdkReady
The SDK loader script will automatically call the global function window.teadsSdkReady
once the SDK is fully loaded and available. You must define this function before the loader script is included or ensure it is defined before the SDK is ready.
Example:
window.teadsSdkReady = function() { // SDK is ready to use };
3.2. Creating the SDK Instance with AppContext
To create an SDK instance, call window.teads.SDK.create(appContext)
, where appContext
is an object containing information about your application, device, user, and content.
AppContext fields:
dom.refElement
(HTMLElement, required): The container element for ad rendering.dom.videoElement
(HTMLVideoElement, optional): The video element associated with the content.application.appId
(string, required): Your app's unique identifier.application.appStoreUrl
(string, required): The app's store URL.contentMetaData
(object, optional): Metadata about the content (genre, language, etc.).device
(object, optional): Device info (userAgent, deviceType, deviceId).user
(object, optional): User info (GDPR, consent, IP).
Example:
const teadsSDK = window.teads.SDK.create(appContext);
3.3. Initializing Placements (initInPlay
, initInPause
)
The SDK supports different ad placements. Use the SDK instance to initialize a placement by calling initInPlay(placementContext)
or initInPause(placementContext)
. Each returns a placement object with the ad API.
PlacementContext fields:
playerHeight
(number, required): Height of the video player.playerWidth
(number, required): Width of the video player.placementId
(number, required): Unique identifier for the placement (provided by Teads).minDuration
(number, optional): Minimum ad duration.maxDuration
(number, optional): Maximum ad duration.
Example:
const inplayPlacement = teadsSDK.initInPlay(placementContext); // or const inpausePlacement = teadsSDK.initInPause(placementContext);
Note:
- Only one instance per placement type (singleton) is supported per page/app.
- You can add event listeners and control ads via the placement object.
4. Context & Placement Reference
4.1. AppContext
The AppContext
type is required when creating the SDK instance. It is composed of several nested types:
AppContext
Field | Type | Required | Description |
---|---|---|---|
dom | DomOptions | Yes | DOM elements for ad rendering (see DomOptions) |
application | ApplicationInfo | Yes | Application details (see ApplicationInfo) |
contentMetaData | ContentMetaData | Yes | Metadata about the content (see ContentMetaData) |
device | DeviceInfo | No | Device information (see DeviceInfo) |
user | UserInfo | No | User information (see UserInfo) |
DomOptions
Field | Type | Required | Description |
---|---|---|---|
refElement | HTMLElement | Yes | The container element for ad rendering |
videoElement | HTMLVideoElement | No | The video element associated with your content (if applicable) |
ApplicationInfo
Field | Type | Required | Description |
---|---|---|---|
appId | string | Yes | Unique identifier for your app (e.g., "G15147002586" ) |
appStoreUrl | string | Yes | URL to your app in the app store (e.g., "https://www.samsung.com/us/appstore/app/G15147002586" ) |
ContentMetaData
Field | Type | Required | Description |
---|---|---|---|
genre | string | No | Genre of the content (e.g., "Documentary" ) |
language | string | No | Language code (ISO-639-1, e.g., "en" ) |
livestream | boolean | No | Whether the content is live (true or false ) |
network | string | No | Network name (e.g., "Discovery+" , "HBO Max" , "ESPN" ) |
channel | string | No | Channel name (e.g., "Discovery Channel" , "HBO 1" , "ESPN2" ) |
DeviceInfo
Field | Type | Required | Description |
---|---|---|---|
userAgent | string | No | User agent string of the device |
deviceType | number | No | Device type (3 = Connected TV, 7 = Set-Top-box) |
deviceId | string | No | Unique device identifier (e.g., Google Ad ID, Apple IDFA) |
UserInfo
Field | Type | Required | Description |
---|---|---|---|
gdpr | number | No | Whether GDPR applies (0 = no, 1 = yes) |
gdprConsent | string | No | GDPR consent string (Base64-encoded) |
ipAddress | string | No | IP address of the user/device |
Example:
const appContext = { dom: { refElement: document.getElementById('ad-container'), videoElement: document.getElementById('main-video'), // optional }, application: { appId: 'G15147002586', appStoreUrl: 'https://www.samsung.com/us/appstore/app/G15147002586', }, contentMetaData: { genre: 'Documentary', language: 'en', livestream: false, network: 'Discovery+', channel: 'Discovery Channel', }, device: { userAgent: navigator.userAgent, deviceType: 3, deviceId: '236A005B-700F-4889-B9CE-999EAB2B605D', }, user: { gdpr: 1, gdprConsent: 'CQL4_0AQL4_...', ipAddress: '181.174.87.53', } };
4.2. PlacementContext
The PlacementContext
type is required when initializing a placement.
Field | Type | Required | Description |
---|---|---|---|
playerHeight | number | Yes | Height of the video player in pixels (e.g., 1080 ) |
playerWidth | number | Yes | Width of the video player in pixels (e.g., 1920 ) |
placementId | number | Yes | Unique identifier for the placement (provided by Teads, e.g., 241975 ) |
minDuration | number | No | Minimum ad duration in seconds (e.g., 0 ) |
maxDuration | number | No | Maximum ad duration in seconds (e.g., 60 ) |
Example:
const placementContext = { playerHeight: 1080, playerWidth: 1920, placementId: 241975, minDuration: 0, maxDuration: 60 };
5. API Reference
5.1. Placement Methods & Properties
Each placement object (returned by initInPlay
or initInPause
) exposes the following methods and properties:
Property/Method | Description | Returns |
---|---|---|
loadAd() | Fetches an ad for the placement. Emits adLoaded or adFailedToLoad events. | void |
playAd() | Starts ad playback if an ad is ready. Emits adStarted or adFailedToStart events. | void |
stopAd() | Stops the currently playing ad and cleans up resources. | void |
destroy() | Cleans up the SDK objects and event listeners for this placement. | void |
isAdReady | true if an ad is loaded and ready to play, otherwise false . | boolean |
Example:
inplayPlacement.loadAd(); if (inplayPlacement.isAdReady) { inplayPlacement.playAd(); }
Or, more typically, using events:
inplayPlacement.addEventListener('adLoaded', function() { inplayPlacement.playAd(); }); inplayPlacement.loadAd();
5.2. Event System
The SDK uses an event-driven architecture. You can listen for events on the placement object using addEventListener
.
Supported Events:
Event Name | Callback Parameters | Description |
---|---|---|
adLoaded | none or { assetsUrls } | Emitted after a successful loadAd() call. |
adFailedToLoad | { error } (string/object) | Emitted if loadAd() fails (e.g., network issues (timeout, connectivity issues), no demand, invalid VAST response). |
adStarted | none | Emitted after a successful playAd() call. |
adFailedToStart | { error } (string/object) | Emitted if playAd() fails. |
adCompleted | none | Emitted when the ad finishes playing and is cleaned up. |
requestPlayerResize | { contentResize } | Emitted if the SDK requests a player resize (see Advanced Usage). |
adError | { error } (string/object) | Emitted for general errors. |
Clarification:
For all error events, the callback parameter will be a string or an object containing a description of the error:
e.g.{ error: "Network error: timeout" }
or{ error: { code: 1001, message: "No demand" } }
).
5.3. Usage Example
// Load and play an ad, handling events inplayPlacement.addEventListener('adLoaded', function() { inplayPlacement.playAd(); }); inplayPlacement.addEventListener('adCompleted', function() { console.log('Ad playback completed'); }); inplayPlacement.addEventListener('adFailedToLoad', function(event) { console.error('Ad failed to load:', event.detail.error); }); inplayPlacement.loadAd();
6. Error Handling & Compliance
6.1. Error Handling
The SDK uses an event-driven approach to surface errors. You can opt in to listen for error events on the placement object and handle them in your application if you wish to provide custom error handling or user feedback. The SDK also handles errors internally to ensure stability.
Common Error Events:
adFailedToLoad
: Emitted if an ad could not be loaded (e.g., network issues, no demand, invalid VAST).adFailedToStart
: Emitted if an ad could not be started (e.g., playback error).adError
: Emitted for general or unexpected errors.
Error Event Payloads:
- The event's
detail.error
property will contain a string or an object describing the error. - Example:
inplayPlacement.addEventListener('adFailedToLoad', function(event) { console.error('Ad failed to load:', event.detail.error); // Optionally show fallback UI, retry, etc. });
6.2. Compliance & Privacy
The SDK is designed to help you comply with privacy regulations such as GDPR.
What you need to provide:
- If your app is subject to GDPR, set the
gdpr
andgdprConsent
fields in theuser
object of yourAppContext
.gdpr
:1
if GDPR applies,0
otherwise.gdprConsent
: The user's consent string (Base64-encoded).
Example:
const appContext = { // ... user: { gdpr: 1, gdprConsent: 'CQL4_0AQL4_...', // ... } };
Security:
- The SDK communicates with the ad server over HTTPS.
7. Ad Fetching & VAST Parameters
- How the SDK fetches ads:
- the SDK builds a VAST tag URL from the objects passed at SDK initialization, it url-encodes all values
- then it makes an HTTP GET call and expects to get a response with VAST XML markup
- List of VAST parameters and their meaning: these are not in scope of this documentation but resemble the SDK objects.
8. Advanced Usage
8.1. Handling (content) Player Resize Requests (requestPlayerResize
Event)
Some ad experiences require the video player to be resized and/or repositioned (for example, to display picture-in-picture or squeeze-back / L-shape ads). The SDK emits a requestPlayerResize
event on the placement object when such a change is needed.
Important:
- If you do not provide the video player element (
videoElement
) in theAppContext
, your application is expected to listen for therequestPlayerResize
event and handle the resize operation. Else the video player resize is handled by the SDK.
How to handle:
- Listen for the
requestPlayerResize
event on your placement object. - The event's
detail.contentResize
property will contain the resize parameters (see table below). - The SDK expects the resize request to be handled immediately and according to the specified parameters.
- It is crucial that you call the provided
onComplete
callback after the resize operation is finished (or immediately if you do not animate). This ensures a smooth user experience and allows the ad to play properly.
Resize Parameters:
Field | Type | Description |
---|---|---|
duration | number | Animation duration in milliseconds (e.g., 300 ) |
scaleX | number | X-axis scaling factor (e.g., 1.0 for no scale) |
scaleY | number | Y-axis scaling factor (e.g., 1.0 for no scale) |
x | number | X-axis target position in pixels |
y | number | Y-axis target position in pixels |
onComplete | function | Callback to invoke when the resize operation is complete |
Example:
inplayPlacement.addEventListener('requestPlayerResize', function(event) { const resize = event.detail.contentResize; // Animate or immediately set your video player to the new size/position animatePlayer(resize.x, resize.y, resize.scaleX, resize.scaleY, resize.duration, function() { resize.onComplete(); }); });
Summary:
- If you do not provide a
videoElement
, you must handlerequestPlayerResize
. - Handle the resize as soon as the event is received, using the provided parameters.
- Always call the
onComplete
callback to allow the SDK to continue.
8.2. Obtain the ad experience visual assets
The SDK exposes an object on the adLoaded event with all the visual asset URLs of the ad experience. This can be used by the app for its own creative approval.
// the ad experience visual asset urls will be passed in adLoaded event: inplayPlacement.addEventListener('adLoaded', (e) => { console.log(e.details.assets) })
9. Workflow diagram
A visual representation of the SDK API calls and events flow:
10. Test placement ids & Demo page
Test placementId for InPlay
- Overlay
- placementId = 241974
- Squeeze-back
- placementId = 241975
- placementId = 241973
- Picture-in-picture
- placementId = 241972
Test placementId for InPause
- Fullscreen in-loop
- placementId = [to-be-provided on request]
Demo page for InPlay
The code samples from this page are implemented in this demo page:
See the section with more ad experiences - here
11. FAQ & Troubleshooting
Q: What happens if I don't provide a videoElement
in the AppContext
?
A: If you do not provide a videoElement
, your application is responsible for handling the requestPlayerResize
event. This is required for certain ad experiences (such as squeeze-back and picture-in-picture) to function correctly. See Advanced Usage for details.
Q: How do I know when an ad is ready to play?
A: Listen for the adLoaded
event on your placement object. When this event is emitted, you can safely call playAd()
.
Q: What should I do if an ad fails to load or play?
A: You can listen for the adFailedToLoad
and adFailedToStart
events. The event's detail.error
property will provide information about the failure. You may choose to display fallback content, retry, or simply log the error.
Q: Is GDPR/consent required for all integrations?
A: If your app is distributed in regions where GDPR applies, you must provide the gdpr
and gdprConsent
fields in the user
object of your AppContext
. If not, you may omit these fields.
Q: Who do I contact for support or to obtain placement IDs?
A: Please contact your Teads account manager or support representative for integration support, placement IDs, or additional documentation.
12. Appendix
Glossary
Term | Definition |
---|---|
SDK | Software Development Kit; a set of tools and APIs for integrating Teads ad experiences. |
Placement | A logical location in your app where an ad can be shown (e.g., InPlay, InPause). |
AppContext | An object containing information about your app, device, user, and content. |
PlacementContext | An object containing information specific to an ad placement (e.g., player size, ID). |
VAST | Video Ad Serving Template; an industry-standard XML format for video ad responses. |
GDPR | General Data Protection Regulation; EU privacy law requiring user consent for data use. |
Consent String | A Base64-encoded string representing the user's privacy consent choices. |
Event | A notification emitted by the SDK to signal ad lifecycle changes or errors. |
References
- Teads Developer Portal
- VAST Specification (IAB)
- GDPR Overview (EU)
- MDN: HTMLVideoElement
- MDN: HTMLElement