Skip to main content

Server Side Ad Insertion in FLAdvertisingMediatailor

Overview

The FLAdvertisingMediatailor SDK is a powerful Swift framework designed to help you build ad-enabled video players with AWS MediaTailor integration. Whether you're working with Video on Demand (VOD) or live streaming content, this SDK provides a flexible and easy-to-use builder API for seamless ad insertion and management.

Key Features

  • Server-Side Ad Insertion - Support for both VOD and live content
  • AWS MediaTailor Integration - Seamless integration with AWS MediaTailor service
  • Customizable Ad Policies - Control how ads behave during user interactions
  • Google PAL Support - Enhanced ad targeting with Publisher Advertiser Library
  • Real-Time Event Tracking - Monitor ad playback with comprehensive delegate methods
  • Flexible Configuration - Customizable session parameters for advanced use cases

Getting Started

Let's get you up and running quickly! Below are examples showing how to set up both VOD and live playback with MediaTailor.

VOD Playback Example

import FLAdvertisingMediatailor

// Create session configuration
let sessionConfig = MediaTailorSessionConfiguration.Builder()
.reportingMode(.server)
.overlayAvails(.on)
.availSuppression(mode: .behindLiveEdge, "00:00:21")
.playerParams(["domain": "example.com"])
.build()
// The fallback asset should be the original content URL (before MediaTailor processing) that you want to play if the MediaTailor session fails to load.
guard let fallbackURL = URL(string: "https://example.com/content.m3u8") else {
fatalError("Invalid fallback content URL")
}
let fallbackAsset = AVURLAsset(url: fallbackURL) // Create the fallback asset here.

// Create MediaTailor session
FLMediatailorFactory.createMediaTailorSession(
initialSessionUrl: "<vod-session-url>",
sessionConfiguration: sessionConfig,
isVODPlayback: true,
palConfig: nil
) { session in
// Create player builder with session and fallback asset
var builder = FLMediatailorFactory.createPlayerBuilder(mediatailorSession: session, fallbackAsset: fallbackAsset)
// Create ad player
let adPlayer = builder.build()
}

Live Playback Example

import FLAdvertisingMediatailor

// Create session configuration
let sessionConfig = MediaTailorSessionConfiguration.Builder()
.reportingMode(.server)
.overlayAvails(.on)
.availSuppression(mode: .behindLiveEdge, "00:00:21")
.playerParams(["domain": "example.com"])
.build()

guard let fallbackURL = URL(string: "https://example.com/content.m3u8") else {
fatalError("Invalid fallback content URL")
}
let fallbackAsset = AVURLAsset(url: fallbackURL) // Create the fallback asset here.


// Create MediaTailor session
FLMediatailorFactory.createMediaTailorSession(
initialSessionUrl: "<live-session-url>",
sessionConfiguration: sessionConfig,
isVODPlayback: false,
palConfig: nil
) { session in
// Create player builder with session and fallback asset
var builder = FLMediatailorFactory.createPlayerBuilder(mediatailorSession: session, fallbackAsset: fallbackAsset)
// Create ad player
let adPlayer = builder.build()
}

API Reference

This section provides detailed documentation for all public APIs available in the SDK.

MediaTailor Session Factory

The session factory is your starting point for creating MediaTailor sessions. It handles the initialization and configuration of your ad-enabled player.

public static func createMediaTailorSession(
initialSessionUrl: String,
sessionConfiguration: MediaTailorSessionConfiguration,
isVODPlayback: Bool,
palConfig: PALSessionConfiguration?,
loadMediaTimeout: TimeInterval = 8,
_ completion: @escaping (MediaTailorSession) -> Void
)
ParameterTypeRequiredDefaultDescription
initialSessionUrlStringYes-The initial session URL for MediaTailor.
sessionConfigurationMediaTailorSessionConfigurationYes-Configuration for session behavior, reporting, and various session parameters.
isVODPlaybackBoolYes-true for VOD playback, false for live playback.
palConfigPALSessionConfiguration?No-Optional Google PAL configuration for enhanced ad targeting.
loadMediaTimeoutTimeIntervalNo8Timeout in seconds for media loading and ad tracking requests.
completion@escaping (MediaTailorSession) -> VoidYes-Completion handler that returns the initialized session instance.

Description:

This method creates a new MediaTailorSession asynchronously and may perform network requests (for example, to AWS MediaTailor or related ad / tracking endpoints) as part of the initialization process. It allows you to configure the session URL, session parameters, VOD/live mode, PAL integration, and request timeout. Once initialization is complete, the completion handler will provide you with a ready-to-use session instance. The completion handler is marked as @escaping and may be invoked on a background thread; if you need to update UI in the completion block, dispatch those updates to the main queue (e.g. via DispatchQueue.main.async).


MediaTailorSessionConfiguration

The MediaTailorSessionConfiguration object gives you fine-grained control over your ad session behavior. You can customize ad reporting modes, overlay ad insertion, avail suppression policies, and much more. Create this configuration before initializing your MediaTailor session.

Configuration Example
let config = MediaTailorSessionConfiguration.Builder()
.reportingMode(.server)
.overlayAvails(.on)
.availSuppression(mode: .behindLiveEdge, "00:00:21")
.playerParams(["domain": "example.com"])
.build()
Configuration Options
  • playerParams - Add player-specific parameters such as domain information.
  • originParams - Include additional session-level parameters.
  • manifestParams - Specify query parameters for manifests and tracking URLs.
  • overlayAvails - Enable or disable overlay ad insertion using .on or .off.
  • availSuppression - Control when and how ad breaks are suppressed relative to the live edge. This is useful for skipping ad personalization before or after the live edge and defining fill policies. Available options:
    • .off: Disables ad suppression.
    • .behindLiveEdge: Suppresses ads behind the live edge (with FULL_AVAIL_ONLY policy).
    • .afterLiveEdgeFull_Avail_Only: Suppresses ads after the live edge (with FULL_AVAIL_ONLY policy).
    • .afterLiveEdgePartial_Avail: Suppresses ads after the live edge (with PARTIAL_AVAIL policy).
  • adSignaling - Enable or disable ad ID signaling for tracking purposes.
  • reportingMode - Choose how ad tracking and reporting should work for your session:
    • .server - Server-side tracking mode where MediaTailor sends all standard ad tracking beacons on your behalf. The SDK also exposes the corresponding tracking URLs and metadata to your app as read-only client-side payloads that you can use for secondary purposes (for example, logging, forwarding summary data to analytics providers, or compliance reporting), but your app is not expected to fire these tracking URLs.
    • .client(configId, playerRootView, friendlyObstructions) - Client-side tracking mode with DataZoom integration, where ad tracking events are emitted from the client (using the provided configuration and view context) for enhanced ad measurement and viewability tracking. In this mode, your client integration is responsible for emitting the tracking events rather than relying on MediaTailor to send them server-side.

Client-Side Tracking Mode Dependencies

If you're implementing client-side tracking with DataZoom integration, you'll need to include these SDK dependencies in your project:

Via CocoaPods
  1. Add the following dependencies to your Podfile:
pod 'DzAVPlayerAdapter', '1.8.4'
pod 'DzMediaTailorAdapter', '1.9.0'
  1. Install the dependencies by running:
pod install
  1. Import the frameworks in your Swift files:
import DzAVPlayerAdapter
import DzMediaTailorAdapter
Via Swift Package Manager (SPM)
  1. In Xcode, go to FileAdd Package Dependencies...

  2. Add the following packages one by one:

    • DzAVPlayerAdapter

      • Repository URL: https://gitlab.com/datazoom/apple/libraries-release/apple_dz_avplayer_adapter
      • Version: 1.8.4
    • DzMediaTailorAdapter

      • Repository URL: https://gitlab.com/datazoom/apple/libraries-release/apple_dz_mediatailor_adapter
      • Version: 1.9.0
  3. Alternatively, add the packages to your Package.swift file:

dependencies: [
.package(url: "https://gitlab.com/datazoom/apple/libraries-release/apple_dz_avplayer_adapter", .exact("1.8.4")),
.package(url: "https://gitlab.com/datazoom/apple/libraries-release/apple_dz_mediatailor_adapter", .exact("1.9.0"))
]
  1. Import the frameworks in your Swift files:
import DzAVPlayerAdapter
import DzMediaTailorAdapter

Client-Side Tracking Example

// Step 1: Set your DataZoom MediaTailor configuration ID
// Learn more at: https://help.datazoom.io/getting-started/how-to-implement-mediatailor
let configId = "your-dz-mediatailor-config-id"

// Step 2: Provide the player root view (must be accessed on the main thread)
// This view is used for viewability measurement and ad tracking
let playerRootView = yourPlayerView

// Step 3: Configure friendly obstructions (optional)
// Friendly obstructions are UI elements that overlay the ad (like skip buttons,
// countdown timers, or ad badges). These should be reported to avoid negatively
// impacting viewability measurement.
let friendlyObstructions: [AdOverlayUIScope] = [] // Add overlay views if needed

// Step 4: Build the session configuration with client-side tracking
let sessionConfig = MediaTailorSessionConfiguration.Builder()
.reportingMode(.client(configId, playerRootView, friendlyObstructions))
.playerParams(["domain": "example.com"])
.build()

// Step 5: Create the MediaTailor session
FLMediatailorFactory.createMediaTailorSession(
initialSessionUrl: initialSessionUrl,
sessionConfiguration: sessionConfig,
isVODPlayback: true,
palConfig: nil
) { session in
// Step 6: Build the player with the session
var builder = FLMediatailorFactory.createPlayerBuilder(
mediatailorSession: session,
fallbackAsset: fallbackAsset
)
let adPlayer = builder.build()
}

AdPlaybackPolicy

Defines rules for ad playback behavior during various user interactions. to know more

let adPolicy = AdPlaybackPolicy(
fastForwardRule: .TRICK_FW_PLAY_LAST,
rewindRule: .TRICK_RW_SKIP_ALL,
interruptRule: .INTERRUPT_RESUME,
autoSeekRule: .AUTO_SEEK_SKIP_ALL,
repeatRule: .REPEAT_PLAY_ONCE
)

PAL Configuration

Configure Google Publisher Advertiser Library (PAL) for enhanced ad targeting and measurement. to know more

let palConfig = FLPALFactory.palConfiguration(
willAdAutoPlay: .on,
descriptionUrl: contentUrl,
nonceLengthLimit: 3000,
playerVersion: FLPlayer.version(),
ppid: "unique-publisher-id",
omidPartnerName: "YourAppName",
omidPartnerVersion: Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "1.0",
omidVersion: [OMIDSDK versionString]
)

Player Builder Factory

Once you have a MediaTailor session, use the player builder factory to create and configure your ad-enabled player.

public static func createPlayerBuilder(mediatailorSession: MediaTailorSession, fallbackAsset: AVURLAsset) -> MediaTailorPlayerBuilder

Parameters

ParameterTypeRequiredDescription
mediatailorSessionMediaTailorSessionYesThe MediaTailor session created via createMediaTailorSession
fallbackAssetAVURLAssetYesAsset to play if the MediaTailor session stream cannot be used

Description:

This method creates a new MediaTailorPlayerBuilder instance configured to play using your MediaTailor session, and to automatically fall back to the provided asset if the MediaTailor stream cannot be used (for example, due to network failures while fetching the MediaTailor manifest or segments, invalid or expired session URLs, or request timeouts).

MediaTailorPlayerBuilder

The MediaTailorPlayerBuilder protocol provides a fluent interface for configuring your player before building it. Chain together the configuration methods you need, then call build() to create your player.

public protocol MediaTailorPlayerBuilder {
@discardableResult
func withAdPlaybackPolicy(_ adPlaybackPolicy: AdPlaybackPolicy) -> MediaTailorPlayerBuilder
@discardableResult
func withThumbnailConfiguration(_ configuration: ContentThumbnailPreviewConfiguration) -> MediaTailorPlayerBuilder
@discardableResult
func withLiveTrackingTimeInterval(_ interval: TimeInterval) -> MediaTailorPlayerBuilder
func build() -> AdPlayer
}

Available Methods

  • withAdPlaybackPolicy(_:) - Define how ads should behave during user interactions like fast-forward, rewind, or seeking.
  • withThumbnailConfiguration(_:) - Set up thumbnail preview options for your player.
  • withLiveTrackingTimeInterval(_:) - Configure the API request timeout interval for fetching ad metadata during live playback.
  • build() - Build and return your configured ad-enabled player (synchronous operation).

MediaTailorAdPlayer

public protocol MediaTailorAdPlayer: AdPlayer, PALSessionClient {
func onVideoClick()
}

This is the player object returned by the builder. It supports both ad playback and Google PAL session integration, giving you full control over ad interactions.

Methods

  • onVideoClick() - In client-side tracking mode, call this method when a user taps on the video during ad playback. It tracks user interactions with the ad and notifies the DataZoom MediaTailor session for accurate viewability and engagement metrics. In server-side tracking mode, calling this method is a safe no-op and does not affect server-side tracking. You can therefore always call onVideoClick() on video taps and let the SDK ignore it when server-side tracking is enabled, or optionally wrap it in a condition so it is only invoked in client-side mode.

  • getPalGestureRecognizer() - Returns a UIGestureRecognizer? from the Google PAL SDK that tracks click events in your ad playback view. Attach this recognizer to any view where ads are displayed to enable proper ad interaction tracking. If PAL is not configured or is disabled for the current session, this method returns nil, so be sure to safely unwrap the result before adding it to a view.

  • sendClick() - Notifies Google's ad servers that a user clicked through on an ad. Call this before opening the ad click-through URL (for example, before presenting an in-app browser or calling UIApplication.shared.open) to ensure proper tracking.

Usage Example

// MARK: - Properties
class YourViewController: UIViewController {
// MediaTailor ad player instance
var adPlayer: MediaTailorAdPlayer!

// Store the current ad's click-through URL
var currentAdClickThroughURL: String?

// UI elements
var visitAdvertiserButton: UIButton!
var adPlayerView: UIView!

// MARK: - Setup Player with Full Configuration
func setupMediaTailorPlayer() {
// 1. Configure Ad Playback Policy
let adPolicy = AdPlaybackPolicy(
fastForwardRule: .TRICK_FW_PLAY_LAST,
rewindRule: .TRICK_RW_SKIP_ALL,
interruptRule: .INTERRUPT_RESUME,
autoSeekRule: .AUTO_SEEK_SKIP_ALL,
repeatRule: .REPEAT_PLAY_ONCE
)

// 2. Configure Google PAL (optional)
let palConfig = FLPALFactory.palConfiguration(
willAdAutoPlay: .on,
descriptionUrl: "https://example.com/content",
nonceLengthLimit: 3000,
playerVersion: FLPlayer.version(),
ppid: "unique-publisher-id",
omidPartnerName: "YourAppName",
omidPartnerVersion: Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "1.0",
omidVersion: [OMIDSDK versionString]
)

// 3. Create Session Configuration
let sessionConfig = MediaTailorSessionConfiguration.Builder()
.reportingMode(.server)
.overlayAvails(.on)
.availSuppression(mode: .behindLiveEdge, "00:00:21")
.playerParams(["domain": "example.com"])
.build()

// 4. Create MediaTailor Session
FLMediatailorFactory.createMediaTailorSession(
initialSessionUrl: "https://your-mediatailor-session-url.com",
sessionConfiguration: sessionConfig,
isVODPlayback: true,
palConfig: palConfig,
loadMediaTimeout: 8
) { [weak self] session in
guard let self = self else { return }

// 5. Create Player Builder
let fallbackAsset = AVURLAsset(url: URL(string: "https://your-fallback-url.com/video.m3u8")!)
var builder = FLMediatailorFactory.createPlayerBuilder(
mediatailorSession: session,
fallbackAsset: fallbackAsset
)

// 6. Configure Player Builder
builder = builder
.withAdPlaybackPolicy(adPolicy)

// 7. Build Player
self.adPlayer = builder.build() as? MediaTailorAdPlayer

// 8. Set Ad Delegate
self.adPlayer.adDelegate = self

// 9. Setup PAL Gesture Recognizer
self.setupPALGestureRecognizer()
}
}

// MARK: - Handle Click-Through URL on Ad Start
func adPlayerDidStart(ad: Ad) {
// Check if the ad has a click-through URL
if let videoClickThroughURL = ad.vastProperties.videoClickThroughURL,
!videoClickThroughURL.isEmpty {
// Show the "Visit Advertiser" button
visitAdvertiserButton.isHidden = false
// Store the click-through URL for later use
currentAdClickThroughURL = videoClickThroughURL
} else {
visitAdvertiserButton.isHidden = true
currentAdClickThroughURL = nil
}
}

// MARK: - Handle Button Click to Open Advertiser Site
@objc func visitAdvertiserButtonTapped(_ sender: UIButton) {
guard let clickThroughURL = currentAdClickThroughURL,
let url = URL(string: clickThroughURL) else {
return
}

// Notify Google ad servers about the click-through event
adPlayer.sendClick()

// Open the advertiser's website
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}

// MARK: - Track Video Clicks During Ad Playback
func handleVideoTap() {
// In client-side tracking mode, use onVideoClick() to report video click events.
// In server-side tracking mode, this call is a no-op and safe to invoke unconditionally.
adPlayer.onVideoClick()
}

// MARK: - Attach PAL Gesture Recognizer
func setupPALGestureRecognizer() {
// Attach PAL gesture recognizer to ad playback view
if let palGestureRecognizer = adPlayer.getPalGestureRecognizer() {
adPlayerView.addGestureRecognizer(palGestureRecognizer)
}
}

// MARK: - Clean Up PAL Gesture Recognizer
func adPlayerDidEnd(adBreak: AdBreak) {
// Remove gesture recognizer when ad playback completes
if let palGestureRecognizer = adPlayer.getPalGestureRecognizer() {
adPlayerView.removeGestureRecognizer(palGestureRecognizer)
}

// Hide the visit advertiser button
visitAdvertiserButton.isHidden = true
currentAdClickThroughURL = nil
}
}

Listening to Ad Events

You can monitor ad playback events by setting an adDelegate on your ad player. This allows you to track the state of ad playback and implement custom UI elements like progress indicators or skip buttons.

Available Delegate Methods

The AdPlayer will invoke these delegate methods throughout the ad playback lifecycle:

/// Called on ad playback failure
func adPlayer(ad: Ad?, didFailWith error: Error)

/// Called when cue points are available
func adPlayerDidProvide(cuepoints: [Int])

/// Called on ad break start
func adPlayerDidStart(adBreak: AdBreak)

/// Called on ad start
func adPlayerDidStart(ad: Ad)

/// Called on ad playback progress change
func adPlayer(ad: Ad?, didChange progress: TimeInterval)

/// Called on ad playback buffer state change
func adPlayer(ad: Ad?, didChangeBuffer isBuffering: Bool)

/// Called on occurance of ad track event
func adPlayer(ad: Ad?, didTrack event: AdTrackingEvent)

/// Called on ad end
func adPlayerDidEnd(ad: Ad)

/// Called on ad break end
func adPlayerDidEnd(adBreak: AdBreak)

Ad Metadata Objects

These objects provide detailed information about ads and ad breaks during playback.

AdBreak

The AdBreak object contains information about an ad break (a group of ads that play together).

PropertyTypeDescription
positionAdPositionThe position of the ad break, can be on of preroll, midroll or postroll
startTimeTimeIntervalThe start position in seconds
durationTimeIntervalThe duration of the ad break, in seconds
totalAdsIntTotal number of adverts in the ad break

The Ad object represents a single advertisement within an ad break.

PropertyTypeDescription
adIdStringThe identifier of the advert
sequenceIntThe sequence of the advert
durationTimeIntervalThe duration of the advert in seconds
isSkippableBoolIndicates if the ad is skippable
adBreakAdBreakThe ad break which the advert belongs to
vastPropertiesVASTPropertiesRepresents key VAST properties to be shared with all registered verification providers.

VASTProperties

The VASTProperties object contains metadata from the VAST (Video Ad Serving Template) response, providing detailed information about the ad.

PropertyTypeDescription
skipOffsetTimeIntervalThe number of seconds before the skip button is presented
isAutoPlayBoolWhether the player will auto-play content
adPositionAdPositionThe position of the ad break, can be on of preroll, midroll or postroll
adSystemStringThe source ad server of the advert
AdTitleStringThe common name of the advert
adServingIdStringAn identifier used to compare impression-level data across systems
creativeIdStringCreativeId of the advert
categoryStringCategory of the advert content
descriptionStringThe longer description of the advert
advertiserStringAdvertiser name
pricingStringPricing element of the advert
surveyStringAn URI to any resource file having to do with collecting survey data
expiresStringNumber of seconds in which the ad is valid for execution
industryIconsArray of IndustryIconThe list of IndustryIcon instances
extensionsExtensionsThe custom VAST extensions properties

tvOS Platform Limitations

Please be aware of these limitations when using the tvOS system player controller with MediaTailor:

  • Live Playback - InterstitialEvent notifications are not available
  • VOD Playback - Interstitial events are not updated after playback (cue points for played ads remain in the timeline)